Why is my getchar() not working here? - c

In my program I'm just calculating the costs of things. However, at the end I want a little break at the program asking for the user to just press the Enter button. I supposed getchar() would work here but it doesn't even stop, it just continues to keep printing. I even tried to put a space after the scant formats like scanf("%s ").
So two things how do I stop the program to ask for input at getchar() and how do I make it recognize just a enter button.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char hotels_houses[5];
int houses, hotels, cost;
printf("Enter amount of houses on board: \n");
scanf("%s", hotels_houses);
houses = atoi(hotels_houses);
printf("Enter amount of hotels on board: \n");
scanf("%s", hotels_houses);
hotels = atoi(hotels_houses);
printf("Cost of houses: %d\n", houses);
printf("Cost of hotels: %d\n", hotels);
cost = (houses *40) + (hotels * 115);
puts("Click enter to calculate total cash ");
getchar(); /* just a filler */
printf("Total cost: %d\n", cost);
return(0);
}

My best guess is that it is retrieving the remaining newline after the user has entered their input. You can print out the return value to verify. If I'm correct, it'll be "10" or "13" depending on your OS.
You might want to change your program to use getline. There are other examples on how to write a get line at How to read a line from the console in C?

When code calls scanf("%s", ... the program waits for input.
You type "123" and nothing happens yet as stdin is buffered input and waits for a \n thus the system has not given any data to scanf().
Then you type "\n" and "123\n" is given to stdin.
scanf("%s",...) reads stdin and scans optional leading white-space then the non-white space "123". Finally it sees "\n" and puts it back in stdin and completes.
Code calls scanf("%s", ... again. scanf() scans the "\n" as part of its scanning optional leading white-space. Then it waits for more input.
You type "456" and nothing happens yet as stdin is buffered input and waits for a \n thus the system has not given any data to scanf().
Then you type "\n" and "456\n" is given to stdin.
scanf("%s",...) reads stdin and scans optional leading white-space then the non-white space "456". Finally it sees "\n" and puts it back in stdin and completes.
Finally you call getchar() and puff, it reads the previous line's \n from stdin.
So how to do I stop the program to ask for input at getchar() and how do I make it recognize just a enter button.
Best approach: use fgets()
char hotels_houses[5+1];
// scanf("%s", hotels_houses);
fgets(hotels_houses, sizeof hotels_houses, stdin);
houses = atoi(hotels_houses);
...
// scanf("%s", hotels_houses);
fgets(hotels_houses, sizeof hotels_houses, stdin);
hotels = atoi(hotels_houses);
...
puts("Click enter to calculate total cash ");
fgets(bhotels_houses, sizeof hotels_houses, stdin); // do nothing w/hotels_houses
printf("Total cost: %d\n", cost);
Checking for a NULL return value from fgets() is useful to test for a closed stdin.
Using strtol() has error checking advantages over atoi().

Related

C while loop does not stop running once input is made

I am trying to create a program that repeatedly asks the user for input. However, in this case, the program just keeps printing "Enter your input" until it crashes after I enter something for the first time.
#include <stdio.h>
int main() {
while (1) {
char input[100];
printf("Enter a input: ");
scanf("%[^\n]s", input);
}
}
In:
scanf("%[^\n]s", input);
There are 2 problems:
The s is not part of that specific specifier, it should be only %[^\n].
That specifier leaves the \n newline character in the input buffer.
Your cycle will enter an infinite loop because there is always something to read there, but it's something that must not be parsed and should remain in the buffer.
A simple way to get rid of it is to place a space before the specifier:
scanf(" %[^\n]", input);
^
|
You are asking scanf() to read everything up to, but not including, the line break that ends the user's input.
So, the line break stays in the input buffer. Then on subsequent calls to scanf(), the line break is still not read from the input buffer, preventing scanf() from reading any new input.
You need to read that line break from the input buffer so that a subsequent call to scanf() can read the user's next input.

Using scanf() function two times: works in one case but not in other case [duplicate]

This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 3 years ago.
I'm the learning the very basics of C programming right now, and I'm practicing the scanf() function. This very, very simple program takes in a number and a letter and uses the printf() function to display the number and letter.
If I ask the user to enter the number first, the program works, i.e., asks for a number, asks for a letter, and prints the input. If I ask for the letter first, the program asks for a letter but then doesn't ask for a number.
I've tried multiple ways and reordered it, but it doesn't seem to work.
This works:
#include<stdio.h>
void main(){
int number;
char letter;
printf("Enter letter...");
scanf("%c", &letter);
printf("Enter number....");
scanf("%d", &number);
printf("Number entered: %d and letter entered: %c.\n", number, letter);
}
But, this combination doesn't work:
#include<stdio.h>
void main(){
int number;
char letter;
printf("Enter number....");
scanf("%d", &number);
printf("Enter letter...");
scanf("%c", &letter);
printf("Number entered: %d and letter entered: %c.\n", number, letter);
}
The output I get for the first program is:
Enter letter...a
Enter number....9
Number entered: 9 and letter entered: a.
Which is correct
But the second case doesn't work, and I don't get why it wouldn't work -- skips the "enter letter" part
the output is
Enter number....9
Enter letter...Number entered: 9 and letter entered:
.
Context: I entered "a" for letter and "9" for number in the above example.
It turns out there's a surprising difference between %d and %c. Besides the fact that %d scans potentially multiple digits while %c scans exactly one character, the surprising difference is that %d skips any leading whitespace, while %c does not.
And then there's another easily-overlooked issue when you're using scanf to read user inputs, which is, what happens to all those newlines -- the \n characters -- that get inserted when the user hits the ENTER key to input something?
So here's what happened. Your first program had
printf("Enter letter...");
scanf("%c", &letter);
printf("Enter number....");
scanf("%d", &number);
The user typed a letter, and ENTER, and a number, and ENTER. The first scanf call read the letter and nothing else. The \n stayed in the input stream. And then the second scanf call, with %d, skipped the \n (because \n is whitespace) and read the number, just like you wanted.
But in your second program you had the inputs in the other order, like this:
printf("Enter number....");
scanf("%d", &number);
printf("Enter letter...");
scanf("%c", &letter);
Now, the user types a number and hits ENTER, and the first scanf call reads the number and leaves the \n on the input stream. But then in the second scanf call, %c does not skip whitespace, so the "letter" it reads is the \n character.
The solution in this case is to explicitly force the whitespace-skipping that %c doesn't do by default. Another little-known fact about scanf is that a space in a format string doesn't mean "match one space character exactly", it means "match an arbitrary number of whitespace characters". So if you change your second program to:
printf("Enter number....");
scanf("%d", &number);
printf("Enter letter...");
scanf(" %c", &letter);
Now, the space character in " %c" in the second scanf call will skip over the \n that was left over after the user typed the number, and the second scanf call should read the letter it's supposed to.
Finally, a bit of editorializing. If you think this is a bizarre situation, if you think the exception to the way %c works is kind of strange, if you think it shouldn't have been this hard to read a number followed by a letter, if you think my explanation of what's going on has been far longer and more complicated than it ought to have been -- you're right. scanf is one of the uglier functions in the C Standard Library. I don't know any C programmers who use it for anything -- I don't believe I've ever used it. Realistically, its only use is for beginning C programmers to get data into their first programs, until they learn other, better ways of performing that task, ways that don't involve scanf.
So my advice to you is not to spend too much time trying to get scanf to work, or learning about all of its other foibles. (It has lots.) As soon as you're comfortable, start learning about the other, better ways of doing input, and leave scanf comfortably behind forever.
Try this
#include <stdio.h>
int main(void) {
int number;
char letter;
printf("Enter letter...");
scanf("%s", &letter);
printf("Enter number....");
scanf("%d", &number);
printf("Number entered: %d and letter entered: %c.\n", number, letter);
return 0;
}
If you change the %c to %s then you get the correct output.
Add a space before %c. So, change this:
scanf("%c", &letter);
to this:
scanf(" %c", &letter);
As I have written in caution when using scanf, this will make scanf eat the whitespaces and special characters (otherwise it will consider them as inputs).
Here, it will consume the newline character, on other words, the Enter you press, after typing your input!
To be exact, in your example, think of what the user (in this case you) do:
You type 9
You press Enter
You type 'a'
You press Enter
Now, when you input something, from your keyboard in this case, this will go into the Standard Input buffer, where it will patiently await to be read.
Here, scanf("%d", &number); will come and read a number. It finds 9 in the first cell of the STDIN buffer, it reads it, thus deleting it from the buffer.
Now, scanf("%c", &letter); comes, and it reads a character. It finds the newline character, that's the first Enter you pressed, and the function is now happy - it was told to read a character, and that's exactly what it did. Now that newline character gets deleted from the buffer (now what's left in there is 'a' and a newline character - these two are not going to be read, since there is no other function call. left for that).
So what changes if I write scanf(" %c", &letter); instead?
The first scanf will still read the number 9, and the buffer will now have a newline character, the 'a' character, and another newline character.
Now scanf(" %c", &letter);` is called, and it goes to search for a character to read in the STDIN buffer, only that now it will first consume any special characters found.
So there it goes to the buffer, it firstly encounters the newline character, it consumes it.
Then, it will encounter 'a', which is not a special character, and therefore it will read normally, and stored to the passed variable in scanf.
The last newline character will remain in the STDIN buffer, untouched and unseen, until the program terminates and the buffer gets deallocated.
Tip: You probably meant to write int main(void), instead of void main(). Read more in What should main() return in C and C++?
Specifying scanf the following way
scanf("%c", &letter);
does not skip white spaces and can read for example a new line character stored in the input buffer when the user pressed Enter entering previous data.
Use instead
scanf(" %c", &letter);
^^^
to skip white spaces.
From the C Standard (7.21.6.2 The fscanf function)
8 Input white-space characters (as specified by the isspace function)
are skipped, unless the specification includes a [, c, or n specifier.
and
5 A directive composed of white-space character(s) is executed by
reading input up to the first non-white-space character (which remains
unread), or until no more characters can be read.
Pay attention to that according to the C Standard the function main without parameters shall be declared like
int main(void)
From the C Standard (5.1.2.2.1 Program startup)
1 The function called at program startup is named main. The
implementation declares no prototype for this function. It shall be
defined with a return type of int and with no parameters:
int main(void) { /* ... */ }

Reading newline from previous input when reading from keyboard with scanf()

This was supposed to be very simple, but I'm having trouble to read successive inputs from the keyboard.
Here's the code:
#include <string.h>
#include <stdio.h>
int main()
{
char string[200];
char character;
printf ("write something: ");
scanf ("%s", string);
printf ("%s", string);
printf ("\nwrite a character: ");
scanf ("%c", &character);
printf ("\nCharacter %c Correspondent number: %d\n", character, character);
return 0;
}
What is happening
When I enter a string (e.g.: computer), the program reads the newline ('\n') and puts it in character. Here is how the display looks like:
write something: computer
computer
Character:
Correspondent number: 10
Moreover, the program does not work for strings with more than one word.
How could I overcome these problems?
First scanf read the entered string and left behind \n in the input buffer. Next call to scanf read that \n and store it to character.
Try this
scanf (" %c", &characte);
// ^A space before %c in scanf can skip any number of white space characters.
Program will not work for strings more than one character because scanf stops reading once find a white space character. You can use fgets instead
fgets(string, 200, stdin);
OP's first problem is typically solved by prepending a space to the format. This will consume white-space including the previous line's '\n'.
// scanf("%c", &character);
scanf(" %c", &character);
Moreover, the program does not work for strings with more than one word. How could I overcome these problems?
For the the 2nd issue, let us go for a more precise understanding of "string" and what "%s" does.
A string is a contiguous sequence of characters terminated by and including the first null character. 7.1.1 1
OP is not entering a string even though "I enter a string (e.g.: computer)," is reported. OP is entering a line of text. 8 characters "computer" followed by Enter. There is no "null character" here. Instead 9 char "computer\n".
"%s" in scanf("%s", string); does 3 things:
1) Scan, but not save any leading white-space.
2) Scan and save into string any number of non-white-space.
3) Stop scanning when white-space or EOF reached. That char is but back into stdin. A '\0' is appended to string making that char array a C string.
To read a line including spaces, do not use scanf("%s",.... Consider fgets().
fgets(string, sizeof string, stdin);
// remove potential trailing \r\n as needed
string[strcspn(string, "\n")] = 0;
Mixing scanf() and fgets() is a problem as calls like scanf("%s", string); fgets(...) leave the '\n' in stdin for fgets() to read as a line consisting of only "\n". Recommend instead to read all user input using fgets() (or getline() on *nix system). Then parse the line read.
fgets(string, sizeof string, stdin);
scanf(string, "%c", &character);
If code must user scanf() to read user input including spaces:
scanf("%*[\n]"); // read any number of \n and not save.
// Read up to 199 `char`, none of which are \n
if (scanf("%199[^\n]", string) != 1) Handle_EOF();
Lastly, code should employ error checking and input width limitations. Test the return values of all input functions.
What you're seeing is the correct behavior of the functions you call:
scanf will read one word from the input, and leave the input pointer immediately after the word it reads. If you type computer<RETURN>, the next character to be read is the newline.
To read a whole line, including the final newline, use fgets. Read the documentation carefully: fgets returns a string that includes the final newline it read. (gets, which shouldn't be used anyway for a number of reasons, reads and discards the final newline.)
I should add that while scanf has its uses, using it interactively leads to very confusing behavior, as I think you discovered. Even in cases where you want to read word by word, use another method if the intended use is interactive.
You can make use of %*c:
#include <string.h>
#include <stdio.h>
int main()
{
char string[200];
char character;
printf ("write something: ");
scanf ("%s%*c", string);
printf ("%s", string);
printf ("\nwrite a character: ");
scanf ("%c%*c", &character);
printf ("\nCharacter %c Correspondent number: %d\n", character, character);
return 0;
}
%*c will accept and ignore the newline or any white-spaces
You cal also put getchar() after the scanf line. It will do the job :)
The streams need to be flushed. When performing successive inputs, the standard input stream, stdin, buffers every key press on the keyboard. So, when you typed "computer" and pressed the enter key, the input stream absorbed the linefeed too, even though only the string "computer" was assigned to string. Hence when you scanned for a character later, the already loaded new line character was the one scanned and assigned to character.
Also the stdout streams need to be flushed. Consider this:
...
printf("foo");
while(1)
{}
...
If one tries to execute something like this then nothing is displayed on the console. The system buffered the stdout stream, the standard output stream, unaware of the fact it would be encounter an infinite loop next and once that happens, it never gets a chance to unload the stream to the console.
Apparently, in a similar manner whenever scanf blocks the program and waits on stdin, the standard input stream, it affects the other streams that are buffering. Anyway, whatsoever may be the case it's best to flush the streams properly if things start jumbling up.
The following modifications to your code seem to produce the desired output
#include <string.h>
#include <stdio.h>
int main()
{
char string[200];
char character;
printf ("write something: ");
fflush(stdout);
scanf ("%s", string);
fflush(stdin);
printf ("%s", string);
printf ("\nwrite a character: ");
fflush(stdout);
scanf ("%c", &character);
printf ("\nCharacter %c Correspondent number: %d\n", character, character);
return 0;
}
Output:
write something: computer
computer
write a character: a
Character a Correspondent number: 97

Fgets skipping input and printing next line?

I'm trying to read a string including spaces so scanf wouldn't work so I'm trying to use fgets. When I run it and it hits the if statement what prints on screen is:
Please enter the course name.
You entered the course:
Please enter the course ID.
=======================
if(coursetotal==0)/*start of 1 course*/
{
printf("Please enter the course name.\n");
fgets(course[0].name,sizeof(course[0].name),stdin);
printf("You entered the course name: %s\n",course[0].name);
printf("\nPlease enter the four digit course ID.\n");
int temp=0,temp1=0,count=0; /*Variables used to check if 4 digits*/
scanf("%d",&temp);
temp1=temp;
while(temp1!=0)
{
temp1/=10;
count++;
}
if(count==4)/*start of is 4 digits*/
{
course[0].id=temp;
coursetotal+=1;
printf("You entered the course ID: %d\n",course[0].id);
}/*end of is 4 digits*/
else
{
printf("The course ID you input was not 4 digits.\n");
return;
}
printf("You have successfully added the course: %s. The ID is : %d, and you now have a total of %d course.\n",course[0].name,course[0].id,coursetotal);
} /*end 1 course*/
First I have to address the pet peeve I see here:
I'm trying to read a string including spaces so scanf wouldn't work
That's not true at all. There's something called a negated scanset you can use it to read past the white space characters (such as space) that normally terminate scanf()s input for a string.
That said. You should really pick just one input mechanism scanf() or fgets() and use that exclusively. When you intermix, things get weird and missed. The fact that you've done it here tells me you've done it other places and you probably used scanf() prior to this leaving yourself an "unclean" stdin buffer. This will fix your issue.
Now just a quick example for you, given a int (num) and a char * (`string):
scanf("%d", &num);
fgets(string, sizeof(string), stdin);
printf("%d\n%s\n", num, string);
You'll seemingly skip the ability to enter anything for the fgets as it really just took int the newline character leftover from the scanf()'s number entry. You'll see on the output something like:
5
5
// <-- and a couple
// <-- of blank lines
Indicating that you picked up a newline character. Even more obvious if you were to look at the ASCII value of the string's first (and only) character:
printf("%d\n", string[0]); // this would yield 10 the ASCII value of \n

Line not prompting for input

I'm new to programming and have been working on an assignment in class. For some strange reason the program keeps printing 2 different printf's on the same line and not giving me a chance to input information
Here is the code:
#include <stdio.h>
#include <stdlib.h>
int main (void)
{ char Name[20];
char cid1[6]="", cid2[6]="", cid3[6]="", cid4[6]="", cid5[6]="", cid6[6]="";
char Description1[21]="", Description2[21]="", Description3[21]="", Description4[21]="", Description5[21]="", Description6[21]="";
int hrs1 = 0, hrs2=0, hrs3=0, hrs4=0, hrs5=0, hrs6=0;
char grade1[2]="",grade2[2]="",grade3[2]="",grade4[2]="",grade5[2]="",grade6[2]="";
printf("Enter Students Name ");
fgets(Name, 20, stdin);
printf("Enter Class ID ");
scanf("%5s", cid1);
printf("Enter Class Description "); // Problem
fgets(Description1, 20, stdin); // here
printf("Enter Class Hours ");
scanf("%d", &hrs1);
printf("Enter Class Grade ");
fgets(grade1, 1, stdin);
printf("%s\n", Name);
printf("%s\n", cid1);
printf("%s\n", Description1);
printf("%d\n", hrs1);
printf("%s\n", grade1);
system("pause");
return 0;
The area marked “Problem here” is where the problem is currently occurring. In stead of prompting for the class description it will skip straight to entering class hours and completely ignore the enter class grade at the bottom.
It prints it as: Enter Class DescriptionEnter Class Hours.
They are trying to teach you the difference between scanf and fgets. And they are probably tricking you by telling you that the Class ID has to be 4 characters.
So if your Class ID is "1234" and you hit Enter after, what ends up in stdin is:
1234\r\n
The %5s format in scanf says to read 5 characters and then move on. So, you read in 1234\r and leave \n in the stdin stream. Then when fgets executes, it reads in the \n and moves on.
From the above on fgets:
Get string from stream
Reads characters from stream and stores them as a C string into str
until (num-1) characters have been read or either a newline or the
end-of-file is reached, whichever happens first.
There is a newline left in the input buffer, from the previous input operation. One way to get rid of it is to read character by character until you've read a '\n'.
You did not consume the newline characters by your scanf calls. As fgets returns when it reads a newline character, it returns immediatelly.
You could change the scanf format string to consume newline characters as follow
scanf("%5s\r\n", cid1);
It seems like you are running this on windows. Windows has issues with flushing its stdin properly. Try using an
fflush(stdin);
after any reads from the console.

Resources