1

I'm trying to compare something that i read with fgets with the words from the first column of the array, but I can't get it, I thing it could be the \0 at the end of each string but I can't get the comparison works

#include <stdio.h>
#include <string.h>
#define MAX_STRLEN 3  

const char *bdato [][columns]={
    {"tc","Torta Cubana"},
    {"th","Torta Huatulco"},
    {"tm","Torta Mexicana"},
    {"tr","Torta Rusa"},
    {"r", "Refresco"},
    {"a", "Agua sabor"}};

int total() {
    char v[20];
    int flag=0,cont=0;
    fgets(v,sizeof(v),stdin);
    do {
        if(strcmp(v,bdato[cont][0])==0){ /*this*/
            flag=1;
            printf("I found one");
        }
        cont++;
    } while(!(flag==1||cont==5));
}

the rewritten code:

  #defines .....
  .............
  .............
 int total(){
 size_t len = strlen(v);
        printf("something here");
        fgets(v,sizeof(v),stdin);
        len = strlen(v);
        if(len>0){
        v[len - 1] = '\0';}
        if(strcmp((v,bdato[cont][0])==0)){
            /*another code*/
        }
 }
2
  • 3
    fgets includes a newline. Also, you appear to have an extra closing brace. Commented Apr 28, 2015 at 12:50
  • yeah, I didn't remember that Commented Apr 28, 2015 at 13:05

4 Answers 4

3

Your string comparisons are failing because fgets() includes the newline that ends the input line.

You need to strip that out, something like

const size_t len = strlen(v);
if(len > 0)
  v[len - 1] = '\0';

should do it. The if is just to be somewhat sure we're not about to index backwards.

Also, you should check that fgets() succeeds before relying on v to have valid input.

Sign up to request clarification or add additional context in comments.

4 Comments

@user2461687: Consider two cases: Case 1: There was no newline at the end of the line. Case 2: There was no input at all.
@Bill Lynch: you are correct for case 1. For case 2, fgets() will return NULL and v is untouched, so anything can happen. fgets() return value should definitely be checked.
I was at the school,mmm I don't know how to implement this into my code
I had to remove the const declaration because this is always reading, the if decision is between a loop
2

If you're using a sh to compile your c program (most of us do that for such small samples i guess) a good thing to learn is to use the program cat with the option -e , let's take a look at your program. For the sake of the example i added a printf() in your do while like so :

print("%s",v); //note that they are no \n

Let's now look at the output if i enter Torta Cubana for example :

Torta Cubana$

The $ (thanks to cat -e) does tell us one thing, you got a \n in your string v. And that's why your strcmp() is failing, since your array bdato doesnt have \n inside your strings.

You have two choices here, the first and the most clean way, is to remove the \n from v (And for this case the answer from unwind is well-fitting).

The second, way uglier is to change your bdato to this :

const char *bdato [][columns]={
    {"tc","Torta Cubana\n"},
    {"th","Torta Huatulco\n"},
    {"tm","Torta Mexicana\n"},
    {"tr","Torta Rusa\n"},
    {"r", "Refresco\n"},
    {"a", "Agua sabor\n"}
};

But you would not do that, would you ?

2 Comments

I made something like that but I knew it was not a good way to do it, so how it should be the code for the comparison
@user2461687 look at unwind's answer for doing the clean way, my answer was more about using cat to detect thoses behaviours and how to act thereafter.
2

You should remove the '\n' at the end of the v array before comparing:

if (!fgets(v,sizeof(v),stdin))
    return -1;
v[strcspn(v, "\n")] = '\0';

3 Comments

Sorry for trying to be creative. The beauty of using strcspn() is that it works in all cases, including when there is a missing '\n' at the end of file.
That's a pretty nice way of going about it actually. I misunderstood the return value of strcspn. (I just assumed it was going to return -1 or something like that if the '\n' wasn't found.)
Learn something new everyday... I started C in 1980, still learning too.
1

The simplest & cleaner approach is as @unwind had suggested. But even in that approach I always prefer to use the safer strncmp() than strcmp(). This is particularly useful in such scenarios as you facing.

Applying strncmp() approach here & if you knew that fgets() appends a newline character, then the changes required in your code are from:

if(strcmp(v,bdato[cont][0])==0){ /*this*/

to

if ((strlen(v) == strlen(bdato[cont][0])) && (strncmp(v,bdato[cont][0],strlen(v))==0)){ /*this*/

the "-1" after strlen(v) is to ignore the newline character.

9 Comments

Not a good approach: if the user enters "t", strncmp() will erroneously match 4 entries, and an empty string, all 6!
@chqrlie: True! I missed that. Thanks.
@chqrlie: Just rectified my solution. I hope this works! Do tell.
What exactly are you gaining with this convoluted alternative to strcmp that happens to be exactly equivalent?
@chqrlie: Isn't it recommended to use the 'n' functions (like strncpy, strncmp, ...) when possible?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.