0

The loop in this program doesn't work as I expect:

int main() {
    char userresponse;
    char x;

    do {
        printf("are you human");
        scanf("%c", &userresponse);
        if (userresponse == 'y') {
            printf("welcome");
        }
        if (userresponse == 'y') {
            printf("please leave");
        }
        printf("type z to repeat");
        scanf("%c", &x);
    } while (x == 'z');

    return 0;
}

It gets to "type z to repeat", and then it finishes. When I tried defining char x='z'; the program runs fine the first time, but at the end it loops like 2 or 4 times, displaying all the printf messages, even the else ones, in the if statements.

I expect the program to wait for input at the bottom of the loop, and to either break out of the loop or continue looping based on that input. Why isn't it doing that?

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
new here
  • 7
  • 5
  • 4
    Please fix your indentation. No indentation makes it hard to understand code. – skrrgwasme Oct 20 '15 at 20:36
  • 1
    Welcome to Stack Overflow. Please read the [About] page soon. When presenting code here, please indent it in a moderately orthodox style. Lay it out in the edit box as you'd like it too look (ignore the preview), then select the code and use the **`{}`** button above the edit box to indent it by four spaces, which makes it appear as code. Your code will be a lot easier to understand if it is indented. As originally presented, it is close to inscrutable. Don't forget to include a newline at the end of outputs that are not prompts (and do include a space at the end of outputs that are prompts). – Jonathan Leffler Oct 20 '15 at 20:39
  • 1
    when you press `y` and `enter` as input.. it will go 2 characters to your program. You are getting the first `y`.. but there's also the `\n` next. You can fix by forcing it to ignore new line with [`scanf("%c%*c",&x)`](http://stackoverflow.com/questions/7898215/how-to-clear-input-buffer-in-c) – wendelbsilva Oct 20 '15 at 20:41
  • 3
    "even the else ones": There are no `else`s in your program. There are 2 identical `if`s which produce seemingly opposite results. – Scott Hunter Oct 20 '15 at 20:41
  • 3
    The simplest fix is to use `" %c"` to read characters; it will ignore white space, including newlines, and processes the next character that is not white space. – Jonathan Leffler Oct 20 '15 at 20:41
  • as per @ScottHunter, that second `if` should probably be an `else` instead without the if logic. Or a 'n' check for the letter n. – Michael Dorgan Oct 20 '15 at 20:45
  • Did you step through your debugger? – Qix - MONICA WAS MISTREATED Oct 20 '15 at 21:29

4 Answers4

5
  1. If you enter a character, you implicitly enter another one: the newline, which partially causes the weird behavior. This can be ignored by replacing the format string "%c" with "%c%*c".

  2. You check for 'y' twice. Replace the second 'y' with a 'n'.

  3. Does not influence the program's action but may improve performance: replace the second if with an else if. This will make the program not even test the condition of the second if clause if the first one evaluates to true.

  4. You don't check for another character than y or n. Either add a seperate else or, instead of my point 3., replace the second if by an else1.


1 As @JonathanLeffler mentioned in the comments to this answer

cadaniluk
  • 15,027
  • 2
  • 39
  • 67
4

When you type in y for userresponse, you probably have to hit Enter after that, right?

Enter counts as a charater! Since it wasn't stored in userresponse, it stays in the input buffer. And the next line to read from the input-buffer is scanf("%c",&x);. So you end up with an Enter in the x variable.

Next, you described that the program displays all the printf messages, even the else ones,"
Do you see the keyword else in your program? (cause I don't)

abelenky
  • 63,815
  • 23
  • 109
  • 159
1

but at the end it loops like 2 or 4 times, displaying all the printf messages,

There are several ways to avoid that, one will be to add after scanf this:

while((check=getchar()) != EOF && check != '\n');

Any way a minimal code will look like this:

#include <stdio.h>
#include <stdlib.h>

int main(void){
    char a;
    int check,ok=0;

    do {
        printf("Give an A: ");

        if ((scanf("%c",&a)) == 1){
            while((check=getchar()) != EOF && check != '\n');

            if ((a == 'a') || (a == 'A')){
                printf("True\n");
                ok=0;
            } else {
                printf("False\n");
                ok = 1;
            }
        }else{
            printf("Error");
            exit(1);
        }

    }while (ok == 1);

    return 0;
}

But the way how you approach this , a fix will probably look like this:

#include <stdio.h>
#include <stdlib.h>

int main(void){
    char userresponse;
    int check,ok=0;
    char x;

    do {
        printf("are you human:  ");

        if ((scanf("%c",&userresponse)) == 1){
            while((check=getchar()) != EOF && check != '\n');

            if ((userresponse == 'y') || (userresponse == 'Y')){
                printf("welcome\n");
                break;
            } else {
                printf("please leave\n\n");
                printf("type z to repeat");
                if(scanf("%c",&x) == 1){
                    while((check=getchar()) != EOF && check != '\n');
                    if(x=='z' || x == 'Z'){
                        ok = 1;
                    }else{
                        printf("\n");
                        printf("Wrong Input\nGoodBye\n");
                        break;
                    }
                }else{
                    break;
                }
            }
        }else{
            printf("Error");
            exit(1);
        }

    }while (ok == 1);

    return 0;
}

What I'm trying here to explain is that there is no reason to stick with a condition in that while like x=='z', just use another variable like in the above examples.

Just give it a try.

EDIT:

If you need to start form your code, than here is a quick fix:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    char userresponse;
    char x;

    do {
        printf("are you human");
        if(scanf(" %c", &userresponse) ==1){
            if (userresponse == 'y' || userresponse == 'Y') {
                printf("welcome\n");
            }
            printf("type z to repeat\n");
            if(scanf(" %c", &x) != 1){
                printf("Error");
                exit(1);
            }
        }else{
            printf("Error");
            exit(1);
        }

    } while (x == 'z' || x == 'Z');

    return 0;
}

As you probably see, I try to avoid your problems. 1) I check scanf for errors

2) i put a space in front of %c to avoid '\n'.

3) I check for y and Y and for z and Z.

Michi
  • 5,175
  • 7
  • 33
  • 58
0

This works fine:

int main()
{
  char userresponse;
  char x;

  do
  {
    printf("are you human");
    scanf(" %c", &userresponse);

    if (userresponse == 'y')
        printf("welcome\n");
    else
        printf("please leave\n");

    printf("type z to repeat");
    scanf(" %c", &x);
  }
  while (x == 'z');

  return 0;
}
Konrad Lindenbach
  • 4,911
  • 1
  • 26
  • 28
BobRun
  • 756
  • 5
  • 12
  • You don't check scanf and what happens if user press **Y** instead of **y**? – Michi Oct 20 '15 at 21:11
  • In my very very humble opinion, the first step is to take non working code and make it work. Then it can be improved. In the process people learn. As long as one is stuck because it does not run, nothing happens. I tend to fix only what is needed to make it run. Otherwise I need to explain too much and confuse people even more. – BobRun Oct 20 '15 at 22:39
  • I'm agree with you, but if we give an Answer, well we should at least take care of that problem, or at least we can inform the OP. Isn't it :) ? – Michi Oct 20 '15 at 22:41