Comparing string input to enum data type

D

dtschoepe

Greetings.

I am working on an assignment and can't seem to get the right concept
for something I'm attempting to do with enum data types.

I have defined the following in my code:

enum color {red, blue, green, yellow, black, purple, pink};

What I am doing now is reading from a text file a string (char *). I
wish to compare the value read into the array and determine which
color it is from the enum data type. How can I compare a string like
"red" to see if it exists in the values that are part of the
enumerated data type 'color'? I know I need to write some kind of
compare function, but I'm not getting anywhere figuring out how that
should work.

David
 
W

Walter Roberson

How can I compare a string like
"red" to see if it exists in the values that are part of the
enumerated data type 'color'?

You don't. By the time you run the program, the names assigned
to the enumerated values no longer have meaning; at that point,
C is working purely with their numeric values.

In your code, you can prepare a list of strings with the names
and compare against that.

There just might be a way to use a macro to name the enumeration
constant and to "stringify" and store away the name at the same
time, but if there is then it escapes me at the moment.
 
B

Bill Pursell

Greetings.

I am working on an assignment and can't seem to get the right concept
for something I'm attempting to do with enum data types.

I have defined the following in my code:

enum color {red, blue, green, yellow, black, purple, pink};

What I am doing now is reading from a text file a string (char *). I
wish to compare the value read into the array and determine which
color it is from the enum data type. How can I compare a string like
"red" to see if it exists in the values that are part of the
enumerated data type 'color'? I know I need to write some kind of
compare function, but I'm not getting anywhere figuring out how that
should work.

If you've red the string into a, and you want to set c:

if( 0 == strncmp("red", a, sizeof "red") )
c = red;
else if ...
 
D

dtschoepe

If you've red the string into a, and you want to set c:

if( 0 == strncmp("red", a, sizeof "red") )
c = red;
else if ...

OK, so this brings up something else, the part where you have

sizeof "red"

Normally I have used it as sizeof(name) with the ()'s. Is this format
with ""'s used with enumerated data types? I am not familiar with this
way of using that operator.

What does this return, the int value of the enum type based on the
position in the list?

David
 
C

Carl R. Davies

OK, so this brings up something else, the part where you have

sizeof "red"

Normally I have used it as sizeof(name) with the ()'s. Is this format
with ""'s used with enumerated data types?

I believe sizeof only needs the () with types and not names or literals:

int x;

sizeof(int);
sizeof x;
 
Y

Yevgen Muntyan

Bill said:
If you've red the string into a, and you want to set c:

if( 0 == strncmp("red", a, sizeof "red") )
c = red;
else if ...

Funny thing it actually works since 'sizeof "red"' is
greater than length of "red". Still, a rather strange
way to compare strings.

Yevgen
 
K

Keith Thompson

Bill Pursell said:
If you've red the string into a, and you want to set c:

if( 0 == strncmp("red", a, sizeof "red") )
c = red;
else if ...

Why not just strcmp("red", a)?
 
K

Keith Thompson

OK, so this brings up something else, the part where you have

sizeof "red"

Normally I have used it as sizeof(name) with the ()'s. Is this format
with ""'s used with enumerated data types? I am not familiar with this
way of using that operator.

There are two syntactic forms of the sizeof operator:

sizeof unary-expression

sizeof ( type-name )

A unary-expression can be a parenthesized expression, so given:

int obj;

either "sizeof obj" or "sizeof(obj)" is legal; in the latter, the
parentheses are part of the operand, not part of the syntax of the
sizeof operator itself.
 
E

Eric Sosman

Bill Pursell wrote On 02/27/07 16:16,:
If you've red the string into a, and you want to set c:

if( 0 == strncmp("red", a, sizeof "red") )
c = red;
else if ...

Why not just strcmp("red", a) ?
 
R

Racaille

OK, so this brings up something else, the part where you have

sizeof "red"

Normally I have used it as sizeof(name) with the ()'s. Is this format
with ""'s used with enumerated data types? I am not familiar with this
way of using that operator.

What does this return, the int value of the enum type based on the
position in the list?

no, it returns the 'size' of the literal, as if the literal was used
to initialize an array:

char a[] = "foobar";

sizeof a == sizeof(a) == sizeof "foobar" == sizeof("foobar") == 7
 
U

user923005

Greetings.

I am working on an assignment and can't seem to get the right concept
for something I'm attempting to do with enum data types.

I have defined the following in my code:

enum color {red, blue, green, yellow, black, purple, pink};

What I am doing now is reading from a text file a string (char *). I
wish to compare the value read into the array and determine which
color it is from the enum data type. How can I compare a string like
"red" to see if it exists in the values that are part of the
enumerated data type 'color'? I know I need to write some kind of
compare function, but I'm not getting anywhere figuring out how that
should work.
From the C-FAQ:

20.17: Is there a way to switch on strings?

A: Not directly. Sometimes, it's appropriate to use a separate
function to map strings to integer codes, and then switch on
those. Otherwise, of course, you can fall back on strcmp() and
a conventional if/else chain. See also questions 10.12, 20.18,
and 20.29.

References: K&R1 Sec. 3.4 p. 55; K&R2 Sec. 3.4 p. 58; ISO
Sec. 6.6.4.2; H&S Sec. 8.7 p. 248.

If you read the strings into an array called strclr, then you could
make a perfect hash with strclr[2] and switch on that.
red = d
blue = u
green = e
yellow = l
black = a
purple = r
pink = n

bcnu
 
B

Ben Pfaff

user923005 said:
If you read the strings into an array called strclr, then you could
make a perfect hash with strclr[2] and switch on that.

I'd recommend not using strclr as the name, because it's in a
namespace reserved for the C standard library. It might
technically be OK to use it as the name of a local variable (I'm
not sure) but it's better to just avoid it.
 
C

CBFalconer

Yevgen said:
Bill Pursell wrote:
.... snip ...

Funny thing it actually works since 'sizeof "red"' is
greater than length of "red". Still, a rather strange
way to compare strings.

sizeof "red" had better be 4.

If it works you are comparing against a nul terminated string, and
you don't need the foofaraw of strncmp. Just use:

if (0 == strcmp("red", a)) c = red;
else if (....
 
W

websnarf

I am working on an assignment and can't seem to get the right concept
for something I'm attempting to do with enum data types.

I have defined the following in my code:

enum color {red, blue, green, yellow, black, purple, pink};

What I am doing now is reading from a text file a string (char *). I
wish to compare the value read into the array and determine which
color it is from the enum data type. How can I compare a string like
"red" to see if it exists in the values that are part of the
enumerated data type 'color'? I know I need to write some kind of
compare function, but I'm not getting anywhere figuring out how that
should work.

As others have posted, by the time your code is compiled these are
just values and not translated to strings. I've recently discovered
(don't know if I'm the first) a more maintainable way of dealing with
this sort of thing. If you make a seperate include file which just
looks like the following.

colors.h:
=========
invoke(red)
invoke(blue)
invoke(green)
....
invoke(pink)

--------------
Then in your .c file you would have something like:

#define invoke(c) c,
enum color {
#include "colors.h"
COLOR_ERROR
};
undef invoke

#define invoke(c) case c: return #c;
char * colorEnumToName (enum color c) {
switch (c) {
#include "colors.h"
default: break;
}
return NULL;
}
#undef invoke

#define invoke(c) if (0 == strcmp (#c, s)) return c;
enum color colorNameToEnum (const char * s) {
if (NULL == s) return COLOR_ERROR;
#include "colors.h"
return COLOR_ERROR;
}
#undef invoke
 
D

dtschoepe

If you've red the string into a, and you want to set c:

if( 0 == strncmp("red", a, sizeof "red") )
c = red;
else if ...

Hmmmm, ok, I did some testing. I created the following program....

#include <stdio.h>

int main()
{

enum color { red, blue, brown, black, purple };

printf("red is %i\n", sizeof red);
}

This prints the number 4. My understanding of enum data types is that
the first one is 0, the second one is 1, etc. While this reply was
interesting and I learned something, it didn't really solve my
problem.

I hope one of the other replies caught my true question. By the way,
this resource is really good for people just starting out. I really
have enjoyed seeing the replies and reading through the other threads.

David
 
B

Beej Jorgensen

printf("red is %i\n", sizeof red);
This prints the number 4.

red is an integer type (like all enum expressions), and it's 4 bytes big
in your case. This doesn't have anything to do with the value of the
enum expression "red".
My understanding of enum data types is that the first one is 0, the
second one is 1, etc.

Yes, unless the member is explicitly set to something else in the enum
specifier:

enum foo {
A, /* 0 */
B, /* 1 */
C, /* 2 */
D=12, /* 12 */
E, /* 13 */
F=2, /* 2 */
G /* 3 */
};
While this reply was interesting and I learned something, it didn't
really solve my problem.

What people are getting at is that there's really no way to effortlessly
get the symbolic names of the enum members in your code. You have to
compare strings (or some clever variant) to accomplish your goal.

-Beej
 
Y

Yevgen Muntyan

CBFalconer said:
sizeof "red" had better be 4.

What do you mean? It doesn't matter if it's 4 or 15, as long as it's
greater than 3 (and it is).
If it works you are comparing against a nul terminated string,

Of course, what else?
and
you don't need the foofaraw of strncmp.

Indeed. That's why I said it was rather strange way to compare strings.

Yevgen
 
N

Nelu

Yevgen said:
What do you mean? It doesn't matter if it's 4 or 15, as long as it's
greater than 3 (and it is).

sizeof "red" must be 4 no matter where you run the program. It
should give you the length of the array holding the string.
 
Y

Yevgen Muntyan

Nelu said:
sizeof "red" must be 4 no matter where you run the program. It
should give you the length of the array holding the string.

I say it 'sizeof "red" *is* 4', so I don't understand 'sizeof "red" had
better be 4'.
 
F

Flash Gordon

Hmmmm, ok, I did some testing. I created the following program....

#include <stdio.h>

int main()
{

enum color { red, blue, brown, black, purple };

printf("red is %i\n", sizeof red);

Bill did 'sizeof "red"' not 'sizeof red'. Note the quotation marks, they
are important. It means Bill was taking the size of the string literal
"red" where as you were taking the size of the enumeration constant red.
A bit like the difference between weighing an apple and weighing a piece
of paper with the word apple written on it.
}

This prints the number 4.

An unlucky coincidence. It could have been 2 (on a 16 bit system) or 8
(on a 64 bit system), or some other value, and you would get the same
result if you substituted purple for red.
> My understanding of enum data types is that
the first one is 0, the second one is 1, etc.

Yes, but that has nothing to do with the size. I have a bag with 1000
dollars in it, how large is the bag? It is not 1000 dollars big it is
50cm by 50cm by 10cm.
> While this reply was
interesting and I learned something, it didn't really solve my
problem.

Whatever you learnt I don't think it was either correct or what Bill was
trying to teach you.
I hope one of the other replies caught my true question.

Bills answer *did* catch your true question, read it again. Bill was
saying you have to read the input and then manually compare the input
against the strings "red", "purple" etc, and you cannot do this
automatically. Also, because of this, if you type the comparison string
as "reed" instead of "red" in your source code the compiler will not
notice because it is just a string and is not (as far as the compiler is
concerned) related to your enumeration.

As others have said, I would write Bill's code as
if (strcmp("red", a) == 0)
c = red;
else if ...

Note, I've change the spacing and swapped the comparison around as well
as changing to strcmp instead of strncmp. The important change is
changing to strcmp because it means less typing and less repetition of
information (hence less chance of getting it wrong), the other changes
are a matter of personal style, and obviously I prefer my style to
Bill's ;-)
> By the way,
this resource is really good for people just starting out. I really
have enjoyed seeing the replies and reading through the other threads.

I'm glad you are enjoying it and, I hope, benefiting from it. Do not
worry if some of the threads go over your head.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,268
Latest member
AshliMacin

Latest Threads

Top