SuperManEver
SuperManEver

Reputation: 2362

Don't understand how to input/print and compare string in loop in C

I'm newcomer to C and I am stuck. I want to write simple program, which will take input from keyboard and output it if it isn't an 'exit' word. I've tried few different approaches and none of them works. Almost in all cases I get infinite output of the first input.

Here is one of my approaches:

#include <stdio.h>

int main() {
    char word[80];

    while (1) {
        puts("Enter a string: ");
        scanf("%79[^\n]", word);

        if (word == "exit")
            break;

        printf("You have typed %s", word);
    }

    return 0;
}

I thought after it finish every loop it should give me prompt again, but it doesn't. What I am doing wrong.

Please if you know give me some advice.

Thanks in advance. Really, guys I will be so happy if you help me to understand what I am doing wrong.

Oh, by the way I've noticed that when I typed some word and press 'Enter', the result string also include Enter at the end. How can I get rid of this ?

Upvotes: 2

Views: 238

Answers (5)

JonS
JonS

Reputation: 651

Your first problem is that you can't compare a string with '=='. So:

if (word == "exit")

should be

if ( strncmp( word, "exit", 4 ) == 0 )

(You could also use strncmp( word, "exit", strlen(word) ) if you know that word is zero-terminated and safe from bad values. There's a few other options also.)

Your second problem is that scanf() is not consuming the input, probably because it's not matching what you've told it to expect. Here is a good explanation of how to do what you want to do:

http://home.datacomm.ch/t_wolf/tw/c/getting_input.html

Upvotes: 0

humodz
humodz

Reputation: 602

The specifier [^\n] will abort scanf if the next character is a newline (\n), without reading the newline. Because of that, the scanf calls after the first one won't read any input.

If you want to read single words, use the %79s specifier and the following code to remove the \n at the end of your string:

if(word[strlen(word)]=='\n')
    word[strlen(word)]='\0';

If you want to read whole lines, you can remove the newline from the input buffer this way:

char line[80];
int i;
while(1)
{
    puts("Enter a string:");
    i=-1;
    scanf("%79[^\n]%n",line,&i);
    //%n returns the number of characters read so far by the scanf call

    //if scanf encounters a newline, it will abort and won't modify i
    if(i==-1)
        getchar(); //removes the newline from the input buffer

    if(strcmp(line,"exit")==0)
        break;

    printf("You have typed %s\n",line);
}
return 0;

Upvotes: 2

It is better to clear (to have a reproducible content) with memset(3) the memory buffer before reading it, and you should use strcmp(3) to compare strings. Also, consider using fflush(3) before input (even if it is not actually necessary in your case), don't forget to test result of scanf(3), also most printf(3) format control strings should end with a \n -for end-of-line with flushing- so:

#include <stdio.h>
int main() {
  char word[80];
  while(1) {
     puts("Enter a string: ");
     memset (word, 0, sizeof(word)); // not strictly necessary
     fflush(stdout); // not strictly necessary
     if (scanf("%79[^\n]", word)<=0)  exit(EXIT_FAILURE);
     if (!strcmp(word,"exit"))
        break;
     printf("You have typed %s\n", word);
  };
  return 0; 
}

I would suggest reading a whole line with fgets(3) and getting rid of its ending newline (using strchr(3)). Also read about getline(3)

Don't forget to compile with all warnings and debug info (e.g. gcc -Wall -g) and learn how to use the debugger (e.g. gdb)

Upvotes: 1

chux
chux

Reputation: 153508

  1. Improper string compare - use strcmp().

    if (word == "exit") simply compares 2 address: the address of the first char in word and the address of the first char in string literal "exit". Code needs to compare the content beginning at those addresses: strcmp() does that.

  2. Left-over '\n' from the previous line's Enter. Add a space to scanf() format to consume optional leading white-space. Also check scanf() results.

    scanf() specifiers like "%d", "%u" and "%f" by themselves consume optional leading white-space. 3 exceptions: "%c", "%n" and "%[".

  3. Add '\n' at end of printf() format. @ Matt McNabb

    #include <stdio.h>
    int main() {
        char word[80];
        while (1) {
            puts("Enter a string: ");
            //         v space added here
            if (scanf(" %79[^\n]", word) != 1) 
                break;  // Nothing saved into word or EOF or I/O Error
            if (strcmp(word, "exit") == 0)
                break;
            printf("You have typed %s\n", word);
        }
        return 0;
    }
    

Nice that OP used a proper width limited value of 79 in scanf()

Upvotes: 3

M.M
M.M

Reputation: 141598

Oh, by the way I've noticed that when I typed some word and press 'Enter', the result string also include Enter at the end. How can I get rid of this ?

This is because you don't output a newline after printf("You have typed %s", word);. The next statement executed is puts("Enter a string: "); . So you will see You have typed helloEnter a string:. To fix this, change to printf("You have typed %s\n", word);

As others have mentioned, use strcmp to compare strings in C.

Finally, the scanf format string "%79[^\n]" does not match a newline. So the input stream still contains a newline. Next time you reach this statement the newline is still in the stream , and it still doesn't match because you specifically excluded newlines.

You will need to discard that newline (and any other input on the line) before getting the next line. One way to do that is to change the input to scanf("%79[^\n]%*[^\n]", word); getchar(); That means:

  • Read up to 79 non-newlines
  • Read all the non-newline things , and don't store them
  • Read a character (which must be a newline now) and don't store it

Finally it would be a good idea to check the return value of scanf so that if there is an error then you can exit your program instead of going into an infinite loop.

Upvotes: 2

Related Questions