5

I have a struct here with something like:

char *sname;
........
players[i].sname

equalling "James".

I need to check for equality between values like so:

if (players[i].sname == 'Lee')

but am not having much luck. Is there a str* function I should be using or is there anyway to fix up my if statement?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Dominic Bou-Samra
  • 14,799
  • 26
  • 100
  • 156
  • 3
    Note that you need to use a double-quote string and not a single-quote multi-character constant. – Jonathan Leffler Oct 21 '09 at 02:27
  • Yeah - i'll leave it in for others to learn from I suppose. – Dominic Bou-Samra Oct 21 '09 at 03:27
  • Note that there is an essentially duplicate question [How do I properly compare strings in C](http://stackoverflow.com/questions/8004237/how-do-i-properly-compare-strings-in-c) that was asked years after this one. There's also [Why does `strcmp()` return 0 when its inputs are equal](http://stackoverflow.com/questions/595450/why-does-strcmp-return-0-when-its-inputs-are-equal) – Jonathan Leffler Feb 10 '17 at 05:22

4 Answers4

12

The short answer: strcmp().

The long answer: So you've got this:

if(players[i].sname == 'Lee')

This is wrong in several respects. First, single-quotes mean "character literal" not "string literal" in C.

Secondly, and more importantly, "string1" == "string2" doesn't compare strings, it compares char *s, or pointers to characters. It will tell you if two strings are stored in the same memory location. That would mean they're equal, but a false result wouldn't mean they're inequal.

strcmp() will basically go through and compare each character in the strings, stopping at the first character that isn't equal, and returning the difference between the two characters (which is why you have to say strcmp() == 0 or !strcmp() for equality).

Note also the functions strncmp() and memcmp(), which are similar to strcmp() but are safer.

Chris Lutz
  • 73,191
  • 16
  • 130
  • 183
  • Thank you so much - I knew there was something fundamentally wrong. When you don't know which part is wrong from many parts, it's hard to actually look it up :P – Dominic Bou-Samra Oct 21 '09 at 02:45
11

You should be using strcmp():

if (strcmp(players[i].sname, "Lee") == 0) { ...

Also note that strings in C are surrounded by double quotes: "". Single characters are surrounded by single quotes: ''. I'm not sure exactly what your compiler might be doing with 'Lee', but it's almost certainly not what you want.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • The compiler will probably generate the number `0x004c6565`. I'm not sure if multibyte characters were legal in C89, but I'm pretty sure they're part of C99. – Chris Lutz Oct 21 '09 at 02:51
  • Multi-character integer constants are legal in C89 and later, but their value is implementation-defined. ISO/IEC 9899:2011 §6.4.4.4 Character constants: _¶10 … The value of an integer character constant containing more than one character (e.g., `'ab'`), or containing a character or escape sequence that does not map to a single-byte execution character, is implementation-defined. …_ The wording is essentially equivalent in C89. (Intriguingly, C89 has an example `'ab'` in the initial description; both C99 and C11 removed the early example of a multi-character constant.) – Jonathan Leffler Feb 10 '17 at 05:39
4

You'd be looking for strcmp() from the header <string.h>.

Note that you need a string — 'Lee' is not a string but a multi-character constant, which is allowed but seldom useful, not least because the representation is defined by the compiler, not the C standard.

If you are looking to compare two strings — call the pointers to them first and second, then you write:

if (strcmp(first, second) == 0)    // first equal to second
if (strcmp(first, second) <= 0)    // first less than or equal to second
if (strcmp(first, second) <  0)    // first less than second
if (strcmp(first, second) >= 0)    // first greater than or equal to second
if (strcmp(first, second) >  0)    // first greater than second
if (strcmp(first, second) != 0)    // first unequal to second

This, in my view, makes it clear what the comparison is and so the notation should be used. Note that strcmp() may return any negative value to indicate 'less than' or any positive value to indicate 'greater than'.

You will find people who prefer:

if (strcmp(first, second))    // first unequal to second
if (!strcmp(first, second))   // first equal to second

IMO, they have the advantage of brevity but the disadvantage of being less clear than the explicit comparisons with zero. YMMV.

Be cautious about using strncmp() instead of strcmp(), which was suggested in one answer. If you have:

if (strncmp(first, "command", 7) == 0)

then if first contains "commander", the match will be valid. If that's not what you want but you want to use strncmp() anyway, you would write:

if (strncmp(first, "command", sizeof("command")) == 0)

This will correctly reject "commander".

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0

strcmp works fine, provided one of the strings is null terminated. If both are max length and identical, the comparison will walk off the end, and most likely give a false negative result for the equality test. If one string is fixed inside of "" marks in the strcmp itself, that's not an issue, because we know it's null terminated.

If we are comparing two string variables, and we don't know if they are max length or not (maximum length ones are not null terminated), then we need to use strncmp, and use sizeof on one of them to get the third parameter. This solves the problem, because the sizeof is aware of the maximum length. Strcmp is 100% safe if one of the strings is a literal in double quotes.

Mr. Beeblebrox
  • 186
  • 1
  • 5
  • All strings are null-terminated. A character sequence that's not null-terminated is not a C string! – Toby Speight Jul 05 '21 at 10:51
  • String literals are null terminated for you always. Character arrays are NOT guaranteed to be. They usually ARE if you just did a strcpy into one, but there is an exception. If you have a char[20] array and try to put a 20 character string in it, the null terminator will be either outside the array, or nonexistent. You can still work with the array, because thee maximum size is known. But heaven help you if you do a strcpy in this state. – Mr. Beeblebrox Jul 06 '21 at 22:52