views:

541

answers:

5

I'm trying to compare two strings. One stored in a file, the other retrieved from the user (stdin).

Here is a sample program:

int main()
{
    char targetName[50];
    fgets(targetName,50,stdin);

    char aName[] = "bob";
    printf("%d",strcmp(aName,targetName));

    return 0;
}

In this program, strcmp returns a value of -1 when the input is 'bob'. Why is this? I thought they should be equal. How can i get it so that they are?

+1  A: 

Because fgets is embededing the newline character into the variable targetName. This is throwing off the comparison.

JaredPar
A: 

fgets appends the newline to the string, so you'll end up with bob\n\0 which isn't the same as bob\0.

Blindy
A: 

Mostly because of the end of line char in the input "\n" under unix like system.

RC
+3  A: 

fgets reads until it sees a newline then returns, so when you type bob, in the console, targetName contains "bob\n" which doesn't match "bob". From the fgets documenation: (bolding added)

Reads characters from stream and stores them as a C string into str until (num-1) characters have been read or either a newline or a the End-of-File is reached, whichever comes first. A newline character makes fgets stop reading, but it is considered a valid character and therefore it is included in the string copied to str. A null character is automatically appended in str after the characters read to signal the end of the C string.

You need to remove the newline from the end of targetName before you compare.

int cch = strlen(targetName);
if (cch > 1 && targetName[cch-1] == '\n')
   targetName[cch-1] = '\0';

or add the newline to your test string.

char targetName[50];
fgets(targetName,50,stdin);

char aName[] = "bob\n";
printf("%d",strcmp(aName,targetName));
John Knoeller
I'd suggest using `sizeof(targetName)`, don't hardcode it in the `fgets()`.
mctylr
+2  A: 

strcmp is one of the few functions that has the reverse results of true and false...if the strings are equal, the result is 0, not 1 as you would think....

if (strcmp(a, b)){
   /* Do something here as the strings are not equal */
}else{
   /* Strings are equal */
}

Speaking of fgets, there is a likelihood that there is a newline attached to the end of the string...you need to get rid of it...

+-+-+-+--+--+
|b|o|b|\n|\0|
+-+-+-+--+--+

To get rid of the newline do this:

aName[strlen(aName) - 1] = '\0';

+-+-+-+--+
|b|o|b|\0|
+-+-+-+--+

Now, strcmp should return 0...

tommieb75
Thanks, other answers were good, but yours included a solution (I thought the problem might be \n, but thought it could have also been something else), because you include a solution (and a nice array picture lol), I've marked yours as the best. And yes, now strcmp works.
Blackbinary
strcmp does not reverse the results of true and false. strcmp doesn't return a boolean, it returns an integral value based on how the two strings relate to each other. "if (strcmp(a,b))" works, but obscures this fact since when dealing with integral values, the "if" statement will treat it as "if (n != 0)". A more clear way of writing this would be "if (strcmp(a,b) != 0)" which state explicitly what is being tested.
Torlack
@Torlack: or if (!strcmp(a,b))....regardless of what you say, anything that is non-zero is true, and zero is false hence my emphasis on it...
tommieb75
yea, strcmp actually returns 0 if they match, otherwise it will be some negative number if one is less than the other, or some positive, if one is greater then the other (it does some weird math, haha)But it is inverted in a way, 0 being 'true' and 1 or any other number = false. If you just think of the return value as 'the amount of difference' it makes more sense.
Blackbinary
But your statement is still incorrect regarding it being the reverse. If what you said is true, then "if (strcmp(a,b)!=true)" would also be correct, but it is not (assuming that we are talking about a version of C or C++ with a proper implementation of a boolean that can only have the state of true and false). http://blogs.msdn.com/ericlippert/archive/2004/07/15/184431.aspx
Torlack