Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Roman numerals to ints

Reply
Thread Tools

Roman numerals to ints

 
 
Christopher Benson-Manica
Guest
Posts: n/a
 
      09-12-2003
Inspired by a thread on clc++, I decided to try it out...

#include <stdio.h>
#include <stdlib.h>

int main( int argc, char *argv[] )
{
int i;
int result=0;
int this;
int last=0;

if( argc != 2 ) {
printf( "No string specified\n" );
return( EXIT_FAILURE );
}
for( i=0 ; argv[1][i] != '\0' ; i++ ) {
switch( argv[1][i] ) {
case 'M':
this=1000;
break;
case 'D':
this=500;
break;
case 'C':
this=100;
break;
case 'L':
this=50;
break;
case 'X':
this=10;
break;
case 'V':
this=5;
break;
case 'I':
this=1;
break;
default:
printf( "Bad character %c\n", argv[1][i] );
return( EXIT_FAILURE );
}
result+=this;
if( this > last ) {
result-=2*last;
}
last=this;
}
printf( "Result is %d\n", result );
return( EXIT_SUCCESS );
}

This seems to work (and this time I didn't forget my header files ).
Questions:

A) Is it 100% legal, ANSI C?
B) Is there a more efficient way to implement it?

--
Christopher Benson-Manica | Jumonji giri, for honour.
ataru(at)cyberspace.org |
 
Reply With Quote
 
 
 
 
Tom Zych
Guest
Posts: n/a
 
      09-12-2003
Christopher Benson-Manica wrote:

Looks pretty good overall. A few ways to make it shorter:

> for( i=0 ; argv[1][i] != '\0' ; i++ ) {
> switch( argv[1][i] ) {


char *p;

for (p = argv[1]; *p; p++) {
switch (*p) {

Pointers are your friend, in C.

> case 'M':
> this=1000;
> break;
> case 'D':
> this=500;
> break;


This way uses 1/3 as many lines and is easier to read besides:
case 'M': this = 1000; break;
case 'D': this = 500; break;

You could also use a table for the conversion, something like:

char letters[] = "MDCLXVI";
char values[] = {1000, 500, 100, 50, 10, 5, 1};

And use strchr(), but you'd have to subtract pointers and mess
around a bit. I think the switch statement is cleaner, really.

Now (getting silly here), if you had to convert *lots* of roman
numerals to arabic *really fast*, you could build a table of 256
values, where table['M'] = 1000, etc, and invalid characters were
zero...

--
Tom Zych
This email address will expire at some point to thwart spammers.
Permanent address: echo '(E-Mail Removed)' | rot13
 
Reply With Quote
 
 
 
 
Neil Cerutti
Guest
Posts: n/a
 
      09-12-2003
In article <bjt643$r67$(E-Mail Removed)>, Christopher Benson-Manica wrote:
> Inspired by a thread on clc++, I decided to try it out...
>
> #include <stdio.h>
> #include <stdlib.h>
>
> int main( int argc, char *argv[] )
> {
> int i;
> int result=0;
> int this;
> int last=0;
>
> if( argc != 2 ) {
> printf( "No string specified\n" );


A usage note is good here, e.g. roman: usage roman
[roman numeral]. It makes the error message a little more
helpful.

> return( EXIT_FAILURE );
> }
> for( i=0 ; argv[1][i] != '\0' ; i++ ) {
> switch( argv[1][i] ) {
> case 'M':
> this=1000;
> break;
> case 'D':
> this=500;
> break;
> case 'C':
> this=100;
> break;
> case 'L':
> this=50;
> break;
> case 'X':
> this=10;
> break;
> case 'V':
> this=5;
> break;
> case 'I':
> this=1;
> break;
> default:
> printf( "Bad character %c\n", argv[1][i] );
> return( EXIT_FAILURE );
> }
> result+=this;
> if( this > last ) {
> result-=2*last;
> }
> last=this;
> }
> printf( "Result is %d\n", result );
> return( EXIT_SUCCESS );
> }
>
> This seems to work (and this time I didn't forget my header
> files ). Questions:
>
> A) Is it 100% legal, ANSI C?


If you mean: "Is it 100% in accordance with the langauge
described in the C standard everybody is talking about?", then
yes.

I have no idea if writing such a program as the above is actually
legal. Consult a lawyer for that.

> B) Is there a more efficient way to implement it?


I think it's efficient enough.

C) Does it work?

It seems to. The best way to test this program is with another
program that converts base 10 to roman numerals, or obtain a huge
table of conversions. You can then write a quick script to
convert a few million numbers there and back again, and thus have
more confidence in your program.

It would be nice if it also accepted lower case roman digits.

Finally, it may work for valid roman numerals, but it doesn't
provide useful diagnostics for nonsense combinations of roman
digits like "VIM" or "IXI".

--
Neil Cerutti
 
Reply With Quote
 
The Real OS/2 Guy
Guest
Posts: n/a
 
      09-14-2003
On Fri, 12 Sep 2003 19:17:23 UTC, Christopher Benson-Manica
<(E-Mail Removed)> wrote:

> Inspired by a thread on clc++, I decided to try it out...
>
> #include <stdio.h>
> #include <stdlib.h>
>
> int main( int argc, char *argv[] )
> {
> int i;
> int result=0;
> int this;
> int last=0;
>
> if( argc != 2 ) {
> printf( "No string specified\n" );
> return( EXIT_FAILURE );
> }
> for( i=0 ; argv[1][i] != '\0' ; i++ ) {
> switch( argv[1][i] ) {
> case 'M':
> this=1000;
> break;
> case 'D':
> this=500;
> break;
> case 'C':
> this=100;
> break;
> case 'L':
> this=50;
> break;
> case 'X':
> this=10;
> break;
> case 'V':
> this=5;
> break;
> case 'I':
> this=1;
> break;
> default:
> printf( "Bad character %c\n", argv[1][i] );
> return( EXIT_FAILURE );
> }
> result+=this;
> if( this > last ) {
> result-=2*last;
> }
> last=this;
> }
> printf( "Result is %d\n", result );
> return( EXIT_SUCCESS );
> }
>
> This seems to work (and this time I didn't forget my header files ).
> Questions:
>
> A) Is it 100% legal, ANSI C?


Yes.

> B) Is there a more efficient way to implement it?
>


/* you may use this table to convert dec to roman too */

struct {
char rom;
long dec;
} rom_dec[] = {
{ 'I', 1 },
{ 'V', 5; },
{ 'X', 10 },
{ 'L', 50 },
{ 'C', 100 },
{ 'D', 500 },
{ 'M', 1000},
{ 0, 0 } /* end of list, bail out, unknown letter */
};

char *r = argv[1];
char *d = rom_dec;
long result = 0;
long last = 0;

for (; *r, r++) {
for (d = rom_dec; d->rom && *r != d->rom; d++) ; /* for body is
empty! */
if (!d->rom) {
printf("unable to convert %c\n", *r);
return EXIT_FAILTURE;
}
result += d->dec;
if (d->dec > last)
result -= 2*last;
last = this;
}

Not tested yet, but should work

--
Tschau/Bye
Herbert

eComStation 1.1 Deutsch Beta ist verügbar
 
Reply With Quote
 
Richard Heathfield
Guest
Posts: n/a
 
      09-14-2003
The Real OS/2 Guy wrote:

<snip>

> for (; *r, r++) {
> for (d = rom_dec; d->rom && *r != d->rom; d++) ; /* for body is
> empty! */
> if (!d->rom) {
> printf("unable to convert %c\n", *r);
> return EXIT_FAILTURE;
> }
> result += d->dec;
> if (d->dec > last)
> result -= 2*last;
> last = this;
> }
>
> Not tested yet, but should work


On the contrary, the compiler will issue a diagnostic for this code, and
almost certainly refuse to provide a binary.

--
Richard Heathfield : http://www.velocityreviews.com/forums/(E-Mail Removed)
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
 
Reply With Quote
 
Christopher Benson-Manica
Guest
Posts: n/a
 
      09-14-2003
The Real OS/2 Guy <(E-Mail Removed)> spoke thus:

> for (; *r, r++) {
> for (d = rom_dec; d->rom && *r != d->rom; d++) ; /* for body is
> empty! */
> if (!d->rom) {
> printf("unable to convert %c\n", *r);
> return EXIT_FAILTURE;
> }


Is looping through a table more efficient than a switch statement? (the code
certainly looks cleaner)

--
Christopher Benson-Manica | Jumonji giri, for honour.
ataru(at)cyberspace.org |
 
Reply With Quote
 
The Real OS/2 Guy
Guest
Posts: n/a
 
      09-14-2003
On Sun, 14 Sep 2003 11:58:30 UTC, Richard Heathfield
<(E-Mail Removed)> wrote:

> The Real OS/2 Guy wrote:
>
> <snip>
>
> > for (; *r, r++) {
> > for (d = rom_dec; d->rom && *r != d->rom; d++) ; /* for body is
> > empty! */
> > if (!d->rom) {
> > printf("unable to convert %c\n", *r);
> > return EXIT_FAILTURE;
> > }
> > result += d->dec;
> > if (d->dec > last)
> > result -= 2*last;
> > last = this;
> > }
> >
> > Not tested yet, but should work

>
> On the contrary, the compiler will issue a diagnostic for this code, and
> almost certainly refuse to provide a binary.
>

Why should it? Don't cry that it is not a complete function!

--
Tschau/Bye
Herbert

eComStation 1.1 Deutsch Beta ist verügbar
 
Reply With Quote
 
Jirka Klaue
Guest
Posts: n/a
 
      09-14-2003
The Real OS/2 Guy wrote:
>Richard Heathfield wrote:
>>The Real OS/2 Guy wrote:
>>
>>>for (; *r, r++) {

^
....
>>On the contrary, the compiler will issue a diagnostic for this code, and
>>almost certainly refuse to provide a binary.

>
> Why should it?


Why do you ask?

Jirka

 
Reply With Quote
 
Kevin D. Quitt
Guest
Posts: n/a
 
      09-15-2003
On Sun, 14 Sep 2003 22:05:35 +0000 (UTC), "The Real OS/2 Guy"
<(E-Mail Removed)> wrote:


>On Sun, 14 Sep 2003 11:58:30 UTC, Richard Heathfield
><(E-Mail Removed)> wrote:
>> On the contrary, the compiler will issue a diagnostic for this code, and
>> almost certainly refuse to provide a binary.
>>

>Why should it? Don't cry that it is not a complete function!


gcc foo.c
foo.c:6: parse error before ';' token
foo.c:15: `argv' undeclared here (not in a function)
foo.c:16: warning: initialization from incompatible pointer type
foo.c:20: parse error before "for"
foo.c:20: conflicting types for `r'
foo.c:15: previous declaration of `r'
foo.c:20: conflicting types for `r'
foo.c:20: previous declaration of `r'
foo.c:20: parse error before '++' token
foo.c:30: conflicting types for `last'
foo.c:18: previous declaration of `last'
foo.c:30: `this' undeclared here (not in a function)
foo.c:30: warning: data definition has no type or storage class
foo.c:31: parse error before '}' token

--
#include <standard.disclaimer>
_
Kevin D Quitt USA 91387-4454 96.37% of all statistics are made up
Per the FCA, this address may not be added to any commercial mail list
 
Reply With Quote
 
Neil Cerutti
Guest
Posts: n/a
 
      09-16-2003
In article <bk2255$bjs$(E-Mail Removed)>, Christopher Benson-Manica wrote:
> The Real OS/2 Guy <(E-Mail Removed)> spoke thus:
>
>> for (; *r, r++) {
>> for (d = rom_dec; d->rom && *r != d->rom; d++) ; /* for body is
>> empty! */
>> if (!d->rom) {
>> printf("unable to convert %c\n", *r);
>> return EXIT_FAILTURE;
>> }

>
> Is looping through a table more efficient than a switch
> statement? (the code certainly looks cleaner)


I don't think there's much benefit to it over a big switch unless
the table allows lookup faster than linear time (O(n)).

You could do that with a table big enough to hold every valid
character value, or with a table sorted by char value, on which
you can use binary search.

A linear search through the table, as above, probably isn't
better than what you've got now.

--
Neil Cerutti
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
progrm for converting integers to roman numerals using files in clanguage kotlakirankumar@gmail.com C Programming 26 01-28-2008 09:55 PM
Roman Numerals dragonsfall21@gmail.com Java 10 08-18-2007 10:12 PM
Decimal to Roman Numerals ARMAS C Programming 31 02-06-2007 09:54 AM
[QUIZ] Roman Numerals (#22) Ruby Quiz Ruby 25 03-09-2005 08:44 PM
ints ints ints and ints Skybuck Flying C Programming 24 07-10-2004 04:48 AM



Advertisments