1

I want to compare some strings, but unfortunately I don't find any proper way to do it.

The idea behind is to ask for a keyboard input, read a variable, one symbol and if it is "y" or "n" ("yes" or "no" apparently) it executes certain activities. If the value of the char is neither of them, the question is asked again, until either of "y" or "n" is not pressed. I don't understand how to implement that.

#include <stdio.h>
#include <string.h>

int main()
{
    char answer;

    answer='a';

    while (answer!='n'&&answer!='y')

    {

        printf("\nQuestion? (y/n) ");
        scanf("%c",&answer);

    }

    return 0;
}

This actually works pretty nice, but if I don't press 'y' or 'n', the "while" starts again and due to a reason I cannot understand, the "printf" is executed one times more, than the length of the input. So if we run this code and we apply "asdf" as an input (four symbols) the "printf" in the "while" is displayed five (four plus one) times. The result is:

Question? (y/n)
Question? (y/n)
Question? (y/n)
Question? (y/n)
Question? (y/n)

Everything else works really nice in my code, but this... Obviously, this is not the best way to approach. I have also tried "strcmp()":

#include <stdio.h>
#include <string.h>

int main()
{
    char answer='a';

    while (strcmp(answer,'n')!=0&&strcmp(answer,'y')!=0)

    {

        printf("Question?");
        scanf("%c",&answer);

    }

    return 0;
}

I don't know why, but the program doesn't even start. It is clear, that I haven't implemented "strcmp" properly and I don't understand what is wrong.

Any ideas, what should I do, so I can avoid multiple execution of the "printf" in the "while" or to make "strcmp" work the way I demand it to?

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

3 Answers3

1

You probably want to read an entire line instead and interpret it as a whole. This way, you don't get the extra unwanted iterations when you enter a line with multiple characters, nor the extra one for the newline character. Look at the fgets() function.

scanf() is generally a poor choice beyond very simple input requirements, precisely because it is somewhat fuzzy and don't allow you to validate parts of the input before parsing it.

Dolda2000
  • 25,216
  • 4
  • 51
  • 92
  • Thank you for your reply @Dolda2000. I have substituted **_scanf(" %c",&answer)_** with **_fgets(answer,1,stdin)_** and the program doesn't even start. Substituted with **_fgets(answer,2,stdin)_** causes the program to crash after I input a symbol. :( – ecclesiastes Nov 19 '17 at 20:38
  • To begin with, `answer` in your case is a character, rather than a pointer, so if anything, it should be `&answer` rather than just `answer`. However, in order to read an entire line, you'll definitely want a larger buffer than just one character. – Dolda2000 Nov 19 '17 at 20:40
  • @ecclesiastes: Note, also, that if you had compiled with warnings turned on, your compiler would have most likely told you that `fgets(answer, 1, stdin)` is wrong. – Dolda2000 Nov 19 '17 at 20:47
  • **_"warning: passing argument 1 of 'fgets' makes pointer from integer without a cast [enabled by default]"_**, **_"warning: assignment makes integer from pointer without a cast [enabled by default]"_** You are correct. – ecclesiastes Nov 19 '17 at 21:10
1

The %c format specifier to scanf will read any character, including whitespace characters such as a newline.

So if you enter in a letter and press the ENTER key, the scanf will read the letter and return, leaving the newline in the input buffer. On the next iteration of the loop, the scanf will immediately consume the newline left in the buffer and answer will contain the newline character. That's why you're seeing the prompt printed twice.

You need to add a leading space in your scanf format:

scanf(" %c",&answer);

The space will consume any whitespace characters that are entered so that answer will only contain non-whitespace.

The reason you're having problems with strcmp is because you're not actually comparing strings but individual characters. Each argument to strcmp is expected to be a pointer to a character array containing a string. Instead, you're passing in a single character. The value of that character is then interpreted as an address and dereferenced. This invokes undefined behavior.

dbush
  • 205,898
  • 23
  • 218
  • 273
0

In C, a string literal is represented this way: "n", but you have char literals, 'n' ... they're very different. Use a string literal for the argument, and it should work better.

Eljay
  • 4,648
  • 3
  • 16
  • 27
  • in the first example the poster is using chars - although in the 2nd case they do need to be strings – Martin Beckett Nov 19 '17 at 20:14
  • If I understood correctly, substituting every **"** with **'** is what you suggest. Unfortunately neither of the two posted scripts works differently. Absolutely the same things happen. :( – ecclesiastes Nov 19 '17 at 20:19