So basically I'm trying to create a simple buffer for input.
If the user inputs something other than the letter 'R' or 'S', then the do while loop will return the code back to where the user inputs the letter.
However, when I tried entering 'Z' for example, the loop repeats itself twice, asking for input on the second loop.
I don't understand why, please help me understand.
I tried... using a while loop? That doesn't work. I don't want to use goto.
<stdio.h>
<stdlib.h>
int main(void)
{
char r_or_s;
printf("Number Reverser/Shuffler v0.1\t");
printf("Written by REN\n");
printf("This program reverses and shuffles the order of numbers.\n\n");
do
{
printf("Would you like to reverse or shuffle numbers? (Press R/S):");
r_or_s = getchar();
printf("\n");
if (r_or_s == 'R')
{
reverseno();
}
else if (r_or_s == 'S')
{
shuffleno();
}
} while (r_or_s != 'R' || r_or_s != 'S');
return 0;
}
Expected output of
Would you like to reverse or shuffle numbers? (Press R/S):
after rejection of input, but the actual output is:
Would you like to reverse or shuffle numbers? (Press R/S):
Would you like to reverse or shuffle numbers? (Press R/S):
This happens because you input 'Z' for example, then you also pressed the Enter!
So, how many characters did you input? Two!
Then getchar() consumes 'Z' from the standard input buffer, goes back to read again from user, but the newline character (Enter) awaits in the Standard input buffer.
As a result, getchar() consumes the newline character now, resulting in "the loop repeating itself twice".
You have to take into account the newlines as well. For instance, you could do this:
if(r_or_s == '\n')
r_or_s = getchar(); // we read the trailing newline character before, read again
Moreover, you want to stop looping when the user input 'R' or 'S, thus you need to change this:
while (r_or_s != 'R' || r_or_s != 'S');
to this:
while (r_or_s != 'R' && r_or_s != 'S');
Related
I'm currently learning C by a book "C Programming a modern approach" and encountered this code. When I tried to run it, after typing consecutive characters like 'abc' and hitting Enter (new line), nothing was printed. Please explain what is going on here.
char ch;
do {
scanf("%c" , &ch);
} while (ch != '\n');
printf("%c", ch);
You're asking the user to input a character using scanf. This is happening in a loop until the user inputs a '\n' or newline character (the same as pressing the enter key), which is when the loop will break.
Your print statement will then print the character in the variable ch, which at that point will be '\n' (since this variable just stores one character, the last one you typed).
This newline character will probably be invisible when you run your program so you may not be seeing it. You can add another print statement after the loop and if that print statement starts at a newline, you know that the '\n' was printed on the previous line.
Something like:
#include <stdio.h>
int main()
{
char ch;
do
{
scanf("%c" , &ch);
} while (ch != '\n');
printf("%c", ch);
printf("I should show up on a newline");
return 0;
}
The code you provided reads characters from the input using the scanf() function and stores them in the variable ch until a newline character (\n) is encountered. After that, the program prints the last character that was read, which is the newline character.
The reason you are not seeing any output when you enter characters followed by a newline character is because the printf() statement is only executed after the loop has finished running. So, the program is waiting for you to enter a newline character to terminate the loop and print the last character that was read.
If you want to see the characters you enter, you can add a printf() statement inside the loop, like this:
char ch;
do {
scanf("%c" , &ch);
printf("%c", ch);
} while (ch != '\n');
This will print out each character as it is read from the input, so you can see what you're typing. Happy coding :)
When I tried to run it, after typing consecutive characters like abc and hitting Enter (new line), nothing was printed.
Well with the posted code, if the loop even finishes, the last byte read by scanf("%c", &ch) and stored into ch is the newline character. Hence printf("%c", ch) outputs this newline and it seems nothing is printed but something is, the newline which is invisible on the terminal but does move the cursor to the next line.
You can make this more explicit by changing the printf call to this:
printf("last value: '%c'\n", ch);
Note however that the posted code is not a recommended way to read the contents of the input stream:
scanf("%c", &ch) may fail to read a byte if the stream is at end of file. Failure to test this condition leads to undefined behavior (ch is unmodified, hence stays uninitialized if the input stream is an empty file) or to an infinite loop as ch may never receive a newline.
this code is a typical example of a do / while with a classic bug. It would be much better to write the code using getchar() and a while loop.
Here is a modified version:
#include <stdio.h>
int main(void) {
int c; // must use int to distinguish EOF from all valid byte values
int count = 0; // to tell whether a byte was read at all
char ch = 0; // the last byte read
// read all bytes from the input stream until end of file or a newline
while ((c = getchar()) != EOF && c != '\n') {
ch = (char)c;
count++;
}
if (count == 0) {
printf("no characters entered: ");
if (c == EOF) {
printf("end of file or read error\n");
} else {
printf("empty line\n");
}
} else {
printf("last character on line is '%c'\n", ch);
if (c == EOF) {
printf("end of file or input error encountered\n");
}
}
return 0;
}
I'm going through lessons at S.Prata book: 'C Primer Plus'. Chapter 6, control question #8:
// Given the input Go west, young man!, what would each of the following
// programs produce for output? (The ! follows the space character in the
// ASCII sequence.)
#include <stdio.h>
int main(void) {
char ch;
scanf("%c", &ch);
while (ch != 'g') {
printf("%c", ch);
scanf("%c", &ch);
}
return 0;
}
The thing is... as far as I know %c in scanf should be used for a single character, not for a phrase like 'Go west, young man!'. Why this program read all the line and stores all of it (except last word), not only first character? Does it automatically store stuff in scanf as an array?
I thought it will print just 'G'... But it actually prints 'Go west, youn'. Why? It's not %s, but %c.
I suppose it could be because %c stores all input to 'char'.. but in specifications it said that it stores only single character, not several ones.
There is a loop, which has the scanf() in it's body
while ( ch != 'g' )
so, it keeps on reading the inputs present in the buffer, until it finds a 'g'.
So, for the input
'Go west, young man!'.
^---------------- here is the 'g'
It'll keep on reading the characters one by one, in each iteration till it reads the 'g' and encounters the exit criteria for the loop.
The character ch will never store a whole string, it only stores one character. The output you're getting is NOT given by a single printf execution, it's by multiple executions of printfs (The loop enters multiple times). You can confirm that by changing the code to:
#include <stdio.h>
int main(void)
{
char ch;
scanf("%c", &ch);
while (ch != 'g')
{
printf("PRINTING: %c\n", ch);
scanf("%c", &ch);
}
return 0;
}
Now, let's see why the loop enters multiple times.
You entered many characters in the scanf outside the loop, then in the loop you expect it to print the first character, which is totally correct. BUT, you think it will wait for the user input again, which is not correct. In the first scanf, when you entered multiple characters, it just read the first one. But there is somehow a hidden cursor in the stdin (standard input) that keeps track of what has been read. When you entered "Go west, young man!", the G is stored in ch and the cursor is put before the o. When you next call scanf, it will look at the cursor position and finds an o, so it won't wait for user input and just reads it. etc.
To summarize, I suspect your problem is that you misunderstand how scanf works. You think that it will always wait for user input whenever called. That is not the case, it may read from the previous input.
If you want the next scanfs to ignore the long first input, you should actually read it (or seek the stdin which will work in Windows but not Linux). Example:
#include <stdio.h>
int main(void)
{
char ch;
scanf("%c", &ch);
while (getchar() != '\n'); // Get to the end of the stdin.
// The previous line can be replaced with fseek(stdin, 0, SEEK_END); but it will work under Windows only.
while (ch != 'g')
{
printf("PRINTING: %c\n", ch);
scanf("%c", &ch);
}
return 0;
}
The program simply reads all characters one by one of the input.
So for an input such as
Go west, young man!
then the first call to scanf reads the single character 'G'. Then in the loop you print that single 'G', followed by reading the single character 'o'. Then in the next iteration of the loop you print the single character 'o' (that you read in the previous iteration) and then read the space ' '. And so on.
Also note that 'G' is not equal to 'g'. Character comparison is case-sensitive.
This question already has answers here:
Problems with C scanf("%c") function to read characters one by one
(4 answers)
Closed 6 years ago.
I am writing some code and I have a prompt in the program driven by a while loop where you make a choice. However, it prints the prompt twice every time it goes through the loop and I just can't figure it out.
while (choice != 'x');
{
printf("\nChoice (a)dd (v)iew e(X)it [ ]\b\b");
scanf("%c",&choice);
if (choice == 'a') add_record();
if (choice == 'v') view_record();
}
The printf line is the one that prints twice. Thanks in advance for any help.
When you enter a character (i.e. type 'a' and press 'Enter'), the newline character ('\n') is also being read in from stdin. You can add a leading space to the format specifier to avoid this:
scanf(" %c", &choice);
The space indicates to scanf to ignore whitespace characters (such as '\n').
There are few things to notice in the question posted.
The outer while loop behavior depends on the variables initialization at first then the values being entered subsequently.
It then manipulates into print the prompt to enter choice, repeatedly (not just twice) depending on how many characters entered as input before 'enter' key is pressed.
The char i/o driver buffers the input entered and each of the characters entered is read by scarf() one at a time in this case, from the buffer. So it is needed to rewrite the code to work as following (expected from my understanding)
char choice = '!', ws = ' ';
int attempts = 0;
while (choice != 'x')
{
printf("\nAttempt:%d Choice (a)dd (v)iew e(X)it [ ]\b\b", ++attempts);
// Eat up the '\n', if one exist and Wait for valid input
while ((scanf("%c", &choice) > 0) && (choice == '\n'));
// Eat up all white space and other chars entered so far, except the last '\n'
while ((scanf("%c", &ws) > 0) && (ws != '\n'));
if (choice == 'a') add_record();
if (choice == 'v') view_record();
}
This question already has answers here:
Using getchar() in a while loop
(3 answers)
Closed 9 years ago.
I'm currently learning C and C++ on my own. In this little "program practice" I ask the user to enter either 'i' or 'd' to know whether they want to work with integers or decimal (float) numbers. I have a while loop that makes sure the user enter 'i' or 'd' by telling them if they entered the wrong char. For some reason, the prompt inside the while loop prints two times before going to the getchar(). I'm having a bit of hard time understanding what's happening under the hood in this situation. Any help is super appreciated. I'm using Xcode (don't know if it's relevant).
#include <stdio.h>
int main()
{
char action;
printf("Please enter 'i' to work with integers or 'd' to work with decimals.\n\n");
scanf("%c", &action);
while (action != 'i' || action != 'd')
{
printf("You didn't entered the right command. Please try again (i/d)\n");
action = getchar()
}
}
So what I'm getting as an output is this:
You didn't entered the right command. Please try again (i/d)
You didn't entered the right command. Please try again (i/d)
What is happening is that when you enter a character and hit a return, you are actually entering two characters - the character and the return character ('\n'). The loop executes once for each character. Which is why you see it go through twice.
The trick is to filter out the return character explicitly, like so:
#include <stdio.h>
int main()
{
char action;
printf("Please enter 'i' to work with integers or 'd' to work with decimals.\n\n");
scanf("%c", &action);
while (action != 'i' || action != 'd')
{
if (action != '\n')
{
printf("You didn't entered the right command. Please try again (i/d)\n");
}
action = getchar();
}
}
As correctly diagnosed by Ziffusion in his answer, you get the double prompt because you get the newline after the user's incorrect input as a separate character, and that too is neither i nor d.
Here is a rewrite with some improvements:
#include <stdio.h>
int main(void)
{
char action = '\0';
printf("Please enter 'i' to work with integers or 'd' to work with decimals: ");
while (scanf(" %c", &action) == 1 && action != 'i' && action != 'd')
printf("You didn't enter the right command. Please try again (i/d): ");
printf("Action selected: %d\n", action);
}
What's changed?
The prompt doesn't end with a newline, so the user's response appears immediately after it. Standard I/O normally synchronizes standard output and standard input so that the prompt will be flushed, despite not ending with a newline. If the prompt doesn't appear, you can add a fflush(stdout); or fflush(0); after each of the prompting printf() statements.
The result of scanf() is checked to deal with EOF.
The format of scanf() includes a leading space. This will skip white space before the character that's returned, so you get a non-blank, non-newline character.
The original condition action != 'i' || action != 'd' is always true; you need the && instead.
Nitpick: improve grammar of error message.
Note that after the loop, action might not be either i or d if the user triggered EOF (typed Control-D or equivalent). If you get EOF (for example, the user ran the program with standard input from /dev/null), you would not have a deterministic value in action except for the initialization to '\0'.
Here I fixed you code:
#include <stdio.h>
int main()
{
char action;
printf("Please enter 'i' to work with integers or 'd' to work with decimals.\n\n");
scanf("%c", &action);
while (action != 'i' && action != 'd') // here the loop will stop if action is 'i' or 'd'
{
printf("You didn't entered the right command. Please try again (i/d)\n");
scanf("\n%c", &action);// here to deal with '\n'
}
}
I am having a problem scanning chars into an array. Every time I do it will skip the next scan and go to the next. I know what is happening because the input also adds '\n' to the input but I do not know how to remedy the cause of it. Here is some sample code:
char charray [MAX], ffs;
int inarray [MAX], i;
for (i = 0; i < MAX; i++)
{
charray[i] = getchar();
printf ("%c\n",charray[i]);
scanf ("%d", &inarray[i]);
printf ("%d\n",inarray[i]);
}
You can do like this.
while((c = getchar()) != '\n')
{
putchar(c);
}
this may solve your problem. or you can go till EOF also.
You are reading from the standard input with 2 functions: getchar() and scanf(). You need to understand how they work.
getchar() is easy: it returns the next available character in the input stream (or waits for one or returns EOF)
scanf("%d", ...) is more complex: first, it optionally discards whitespace (spaces, enters, tabs, ...), then it reads as many characters as possible to represent an integer, and stops at the first character that can't be used for integers, like a '\n'.
As you have them in a loop, your getchar() call will get the character that stopped the scanf() and the next scanf() will procedd from there.
If your input is something like "q1w22e333r4444" (with MAX == 4), your program will work.
If your input is something like
q 1
w 22
e 333
r 4444
after the first time through the loop (where charray[0] gets 'q' and inarray[0] gets 1), the getchar() will get '\n' leaving the 'w' "ready" for scanf, which of course fails ... and is then "caught" by the next getchar(); and the "22" gets assigned in the 3rd time through the loop (to inarray[2]).
So, you need to review your code.
Also, scanf() returns a value. Use that value
if (scanf("%d", &inarray[i]) != 1) /* error */;
You should actually scan a string into the array directly, rather than characters using scanf("%s",&charray);
However your code will work if you add a while(getchar() != '\n' ); statement. This will get all characters till the '\n'.
charray[i] = getchar();
do{
c = getchar();
}while(c != '\n' && c!= EOF);
printf ("%c\n",charray[i]);
scanf ("%d", &inarray[i]);
do{
c = getchar();
}while(c != '\n' && c!= EOF);
printf ("%d\n",inarray[i]);