Fgets skipping input and printing next line? - c

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

Related

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) { /* ... */ }

Program To Check If A Number Is Present In An Array

I wrote the below C code to check if a number is present in an array whose elements are input by the user. But weirdly it's skipping the the third printf statement, directly taking the input and printing Enter the number you wish to look for after taking that input. What is causing this? Included input and output box below code.
CODE:
#include <stdio.h>
#include <stdlib.h>
void main() {
int arr[30], size, i, num, flag=0;
printf("Enter size of array. \n");
scanf("%d",&size);
printf("Enter %d array elements one by one. \n",size);
for (i=0; i<size; i++) {
scanf("%d \n",&arr[i]);
}
printf("Enter the number you wish to look for. \n");
scanf("%d",&num);
for(i=0;i<size;i++) {
if (num == arr[i]) {
flag++;
}
}
if (flag>0) {
printf("The number %d is present in the array.",num);
} else {
printf("The number %d is not present in the array.",num);
}
}
INPUT/OUTPUT:
Enter size of array.
5
Enter 5 array elements one by one.
1
2
3
4
5
5
Enter the number you wish to look for.
The number 5 is present in the array.
You can see that Enter the number you wish to look for. should come before 5, but it is not so.
Solved
Simply fixed by removing \n from scanf.
In scanf, a space character already represents any whitespace. So in your "%d \n" the function already processes the new line right after the last digit, but then you force it to wait for another newline.
This causes the program to wait for yet another line. After it's input, the program continues and asks for the number to search, and at that point the input was already entered.
Just use only one space in scanf, it will already work for the newline, ideally before the digit itself so that you don't need one extra line to complete the operation:
scanf(" %d", arr + i);
The space in the input format string "%d \n" tells the input system to
consume... all available consecutive whitespace characters from the input
(described here)
So when you enter your last number 5, the system now tries to consume all whitespace characters. To do that, it waits for additional input, until it's not a whitespace. So, paradoxically or not, to consume spaces, the system has to read a non-space, which is the second 5 you input.
To fix this behavior, you can tell your system to input only a number, without consuming whitespace:
scanf("%d",&arr[i]);
However, this will leave the whitespace in the buffer, which may interfere with later input. To discard the whitespace, you can use various techniques, described e.g. here.
In my opinion, the most correct technique (however, maybe the most cryptic one) is
scanf("%d%*[^\n]%*c",&arr[i]);
%d - read the number
%*[^\n] - read a string, terminated by a newline byte; discard it and don't store it anywhere
%*c - read a byte (which is a newline byte); discard it and don't store it anywhere
BTW in your format string "%d \n", there are two whitespaces: a regular space and an end-of-line. They both tell scanf to consume all whitespaces in input. The effect is exactly the same as with one space "%d " or with one end-of-line "%d\n", so this particular format string may be highly confusing to whoever reads your code (including yourself).

Why are the if conditions not being executed?

This is a menu driven program asking for user's choice.
Why are if conditions not executed?
Output is attached.
Creating a program asking for user's input:
void main()
{
float a,b,ans=0;char ch,choice;
choice='y';
while(choice=='Y'||choice=='y')
{
printf("Enter two numbers \n");
scanf("%f %f",&a,&b);
printf("1.+for Addition\n");
printf("2.-for subtraction \n");
printf("3.*for multiplication \n ");
printf("4./for Division \n");
printf("Enter your choice of operation \n");
scanf("%c",&ch);
if(ch=='+')
ans=a+b;
else if (ch=='-')
ans=a-b;
else if(ch=='*')
ans=a*b;
else if(ch=='/')
ans=a/b;
else
{
printf("wrong choice entered\n");
}
printf("Answer is %f \n",ans);
printf("Do you want to coninue (Y/N)\n");
scanf("%c",&choice);
}
printf("program Terminated\n");
}
Output:
/* Enter two numbers
1010
22
1.+for Addition
2.-for subtraction
3.*for multiplication
4./for Division
Enter your choice of operation
wrong choice entered
Answer is 0.000000
Do you want to coninue (Y/N)
n
program Terminated
*/
The above is the output screen.
It doesn't perform operations.
When you input first 2 numbers, they are placed into variables a and b. BUT after entering those 2 numbers, you pressed enter. Computer sees that as new input and place it in first next appropriate variable that requires input. In this case it's your variable ch, and instead of +,-./ or *, ch has value of "new line". If you try to write value of ch on standard output as an integer, it will write number 10. It's ASCII character of new line. Simply adding getchar() after inputting first 2 numbers will collect that new line sign, and your next scanf will work properly.
By the way, you have same problem with your last input scanf("%c",&choice); because pressing enter after previous operation decision, will also cause your program not to work properly. Do the same thing for this part, or simply leave blank character before %c.
Try the following
scanf(" %c",&ch);
^^
and
scanf(" %c",&ch);
^^
Otherwise a next character is read that can be a white space character.
Take into account that according to the C Standard function main without parameters shall be declared like
int main( void )
scanf() does not consume trailing newlines. The skipped scanf() receives the newline from the previous line typed by the user and terminates without receiving more input as you would expect...
scanf() is a bit cumbersome with newlines. A possible solution would be to use fgets() to get a line from the console and then employ sscanf() to parse the received string.
Another, more targeted, solution would be to use " %c" in the format string of the last scanf() call. The %c format specifier does not consume leading whitespace on its own, which is why it gets the remaining newline, rather than a character typed by the user.

how field specifier works in C

I need to take two int values from user. First value is using field specifier and second is normal integer value.
#include<stdio.h>
int main()
{
int num, num1;
printf("Enter first number: \n");
scanf("%2d", &num);
printf("First number is %2d\n", num);
printf("Enter second number: \n");
scanf("%d", &num1);
printf("Second number is %d\n", num1);
return 0;
}
and the output is
Enter first number:
12345
First number is 12
Enter second number:
Second number is 345
It won't give control to enter second number. I don't know why?
You see this behaviour because you have limited the size of input that the first scanf statement can consume. scanf("%2d", &num) says that scanf should read a field of width at most 2 and convert that into into num.
Change the scanf to scanf("%d", &num) and the entirety of 12345 will be processed.
you don't get to enter second num because your program gets it from first num.
First time, your scanf lets your num get first two digits of the number you entered, and rest remains in the buffer/stream.
next time scanf is executed, it reads the remaining digits from the stream till an enter stroke, hence you don't get to enter the second no.
if you want to read the second no.
try flushing the stream before using second scanf(), you will get what you want.
Why would you expect it to "give control"? The fist scanf() explicitly consumed at most two digits, leaving "345" unconsumed. The next scan begins with the unconsumed input. What else would you expect?
If you want to discard any unconsumed input before the next scan, use fpurge(stdin).
There is always a tradeoff with scanf. If you want to enter a whole number and then consume the trailing newline (left in the input buffer (stdin) as the result of pressing [enter]), you canappend a %*c to read and discard the trailing newline. This itself causes problems if an empty-string is entered.
However, limiting your scanf format string and specifier to %2d and then entering 123456, you intentially leave 3456\n in the input buffer which is taken as your input to the second scanf call. The only way to insure each of your scanf calls will only accept your expected input is to manually empty the input buffer after each read by scanf to insure there are no characters remaining prior to the next call. A simple way to do this is with either a do .. while or simply a while ; using getchar() to read each character in stdin until a '\n' is encountered or EOF:
#include<stdio.h>
int main()
{
int c, num, num1;
printf("Enter first number: \n");
scanf("%2d", &num);
while ((c = getchar()) && c != '\n' && c != EOF) ;
printf("First number is %2d\n", num);
printf("Enter second number: \n");
scanf("%d", &num1);
printf("Second number is %d\n", num1);
return 0;
}
output:
$ ./bin/scanf_tradeoff
Enter first number:
123456
First number is 12
Enter second number:
12345
Second number is 12345
The reason for second value is not getting from you, in first scanf you are mentioning that
get the two values from the input. You are giving more than two that time the remaining value is stored in the buffer. So second scanf will get the value from the buffer.
If you want to avoid this you can use this statement before the second scanf.
while ((c=getchar())!='\n' && c!=EOF);// clearing the buffer.
So now the second input will get from the user.

Why is my getchar() not working here?

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().

Resources