Why is my second "scanf" being skipped? - c

This is in my main function..
printf("How many marking components in the course? ");
scanf("%d", &numberOfComponents );
for (int i=0; i<numberOfComponents; i++){
char c[MAX_STR];
printf("enter next component name: ");
fgets(c, sizeof(c), stdin);
scanf(c, " %c", &c);
Component comp;
initComp(&comp, c);
class.comps[i] = comp;
}
printf("How many marking schemes? ");
scanf(" %d", &numberOfSchemes);
I have tried the white space but it still persists

You should test that your input operations worked; things go haywire when you don't.
This call to scanf():
scanf(c, " %c", c);
should (as chux diagnoses in his answer) be written differently, but I think it should be more like:
char filler;
if (scanf(" %c", &filler) != 1)
…report problem…
The original version uses the line that was just read as the format string, and it is almost certain to fail matching the second input. If you simply use scanf(" %c", c), which is the simplest edit, then you overwrite the first character of the line of input with the next non-blank character.
There's then the question of why you're making the user enter the extra data after the component name. They have to enter something. On the next fgets(), the code will read after the first character up to the next newline. So, if you typed:
component-1
component-2
The first fgets() would read component-1 and the newline; the scanf() as amended would read the c of component-2 into c[0], and then the next fgets() would read omponent-2 plus the newline into c on the next iteration.
You could see more of what is going on by adding code to print what you read as you read it:
printf("Line 1: [[%s]]\n", c); // after the fgets()
printf("Line 2: [[%s]]\n", c); // after the scanf()
This is one of the most basic of debugging techniques; echo what you've read to make sure the program got the data you think it got.

Mixing fgets() with scanf() often causing problems.
scanf("%d"... leaves any following white-space like '\n' in stdin for fgets() to get. The same happens after scanf(c, " %c", &c); (which likely was meant to be scanf(" %c", c); or sscanf(c, " %c", c);).
scanf("%d", &numberOfComponents );
...
fgets(c, sizeof(c), stdin);
Recommend using only fgets() to get user input and use sscanf(), strtol(), etc. to parse that input.
fgets(c, sizeof(c), stdin);
sscanf(c, "%d", &numberOfComponents );
....
fgets(c, sizeof(c), stdin);
// I do not think you need the following line of code.
// Besides it is UB as it attempts to scan and save into the same buffer.
// sscanf(c, "%c", &c );
Error checking of the result of fgets(), sscanf() omitted, but still good to do.

Related

C language: Why my for loop code is using printf multiple times? [duplicate]

I have the following program:
int main(int argc, char *argv[])
{
int a, b;
char c1, c2;
printf("Enter something: ");
scanf("%d", &a); // line 1
printf("Enter other something: ");
scanf("%d", &b); // line 2
printf("Enter a char: ");
scanf("%c", &c1); // line 3
printf("Enter another char: ");
scanf("%c", &c2); // line 4
printf("Done"); // line 5
system("PAUSE");
return 0;
}
As I read in the C book, the author says that scanf() left a newline character in the buffer, therefore, the program does not stop at line 4 for user to enter the data, rather it stores the new line character in c2 and moves to line 5.
Is that right?
However, does this only happen with char data types? Because I did not see this problem with int data types as in line 1, 2, 3. Is it right?
The scanf() function skips leading whitespace automatically before trying to parse conversions other than characters. The character formats (primarily %c; also scan sets %[…] — and %n) are the exception; they don't skip whitespace.
Use " %c" with a leading blank to skip optional white space. Do not use a trailing blank in a scanf() format string.
Note that this still doesn't consume any trailing whitespace left in the input stream, not even to the end of a line, so beware of that if also using getchar() or fgets() on the same input stream. We're just getting scanf to skip over whitespace before conversions, like it does for %d and other non-character conversions.
Note that non-whitespace "directives" (to use POSIX scanf terminology) other than conversions, like the literal text in scanf("order = %d", &order); doesn't skip whitespace either. The literal order has to match the next character to be read.
So you probably want " order = %d" there if you want to skip a newline from the previous line but still require a literal match on a fixed string, like this question.
Use scanf(" %c", &c2);. This will solve your problem.
Another option (that I got from here) is to read and discard the newline by using the assignment-supression option. To do that, we just put a format to read a character with an asterisk between % and c:
scanf("%d%*c",&a); // line 1
scanf("%c%*c",&c1); // line 3
scanf will then read the next char (that is, the newline) but not assign it to any pointer.
In the end, however, I would second the FAQ's last option:
Or, depending on your requirements, you could also forget about scanf()/getchar(), use fgets() to get a line of text from the user and parse it yourself.
To echo what I have posted in another answer about C++: I suggest to toss scanf() away, to never use it, and to instead use fgets() and sscanf().
The reason for this is, that at least in Unix-like systems by default, the terminal your CLI program runs on does some processing of the user input before your program sees it. It buffers input until a newline is entered, and allows for some rudimentary line editing, like making backspace work.
So, you can never get a single character at a time, or a few single characters, just a full line. But that's not what e.g. scanf("%d") processes, instead it processes just the digits, and stops there, leaving the rest buffered in the C library, for a future stdio function to use. If your program has e.g.
printf("Enter a number: ");
scanf("%d", &a);
printf("Enter a word: ");
scanf("%s", word);
and you enter the line 123 abcd, it completes both scanf()s at once, but only after a newline is given. The first scanf() doesn't return when a user has hit space, even though that's where the number ends (because at that point the line is still in the terminal's line buffer); and the second scanf() doesn't wait for you to enter another line (because the input buffer already contains enough to fill the %s conversion).
This isn't what users usually expect!
Instead, they expect that hitting enter completes the input, and if you hit enter, you either get a default value, or an error, with possibly a suggestion to please really just give the answer.
You can't really do that with scanf("%d"). If the user just hits enter, nothing happens. Because scanf() is still waiting for the number. The terminal sends the line onward, but your program doesn't see it, because scanf() eats it. You don't get a chance to react to the user's mistake.
That's also not very useful.
Hence, I suggest using fgets() or getline() to read a full line of input at a time. This exactly matches what the terminal gives, and always gives your program control after the user has entered a line. What you do with the input line is up to you, if you want a number, you can use atoi(), strtol(), or even sscanf(buf, "%d", &a) to parse the number. sscanf() doesn't have the same mismatch as scanf(), because the buffer it reads from is limited in size, and when it ends, it ends -- the function can't wait for more.
(fscanf() on a regular file can also be fine if the file format is one that supports how it skims over newlines like any whitespace. For line-oriented data, I'd still use fgets() and sscanf().)
So, instead of what I had above, use something like this:
printf("Enter a number: ");
fgets(buf, bufsize, stdin);
sscanf(buf, "%d", &a);
or, actually, check the return value of sscanf() too, so you can detect empty lines and otherwise invalid data:
#include <stdio.h>
int main(void)
{
const int bufsize = 100;
char buf[bufsize];
int a;
int ret;
char word[bufsize];
printf("Enter a number: ");
fgets(buf, bufsize, stdin);
ret = sscanf(buf, "%d", &a);
if (ret != 1) {
fprintf(stderr, "Ok, you don't have to.\n");
return 1;
}
printf("Enter a word: ");
fgets(buf, bufsize, stdin);
ret = sscanf(buf, "%s", word);
if (ret != 1) {
fprintf(stderr, "You make me sad.\n");
return 1;
}
printf("You entered %d and %s\n", a, word);
}
Of course, if you want the program to insist, you can create a simple function to loop over the fgets() and sscanf() until the user deigns to do what they're told; or to just exit with an error immediately. Depends on what you think your program should do if the user doesn't want to play ball.
You could do something similar e.g. by looping over getchar() to read characters until a newline after scanf("%d") returned, thus clearing up any garbage left in the buffer, but that doesn't do anything about the case where the user just hits enter on an empty line. Anyway, fgets() would read until a newline, so you don't have to do it yourself.
Use getchar() before calling second scanf().
scanf("%c", &c1);
getchar(); // <== remove newline
scanf("%c", &c2);
Two workarounds. One is catch the extra whitespace trickly.
getchar(); // (1) add `getchar()`
scanf("%c", &c1);
scanf(" %c", &c1); // (2) add whitespace before %c
The other is using fgets() to instead scanf(). Note: gets() is unsafe, see why gets is dangerous
By contrast, I would prefer to recommend the second way. Because it's more readable and maintainable. For example, in first way, you must think a while before adding/moving some scanf().
/*Take char input using scanf after int input using scanf just use fflush(stdin) function after int input */
#include<stdio.h>
#include<conio.h>
void main()
{
int x;
char y;
clrscr();
printf(" enter an int ");
scanf("%d",&x);
fflush(stdin);
printf("\n Now enter a char");
scanf("%c",&y);
printf("\n X=%d and Y=%c",x,y);
getch();
}

I am a beginner in programming. I am using Dev C++ and there is a bug. Can anyone help me to find out [duplicate]

I have the following program:
int main(int argc, char *argv[])
{
int a, b;
char c1, c2;
printf("Enter something: ");
scanf("%d", &a); // line 1
printf("Enter other something: ");
scanf("%d", &b); // line 2
printf("Enter a char: ");
scanf("%c", &c1); // line 3
printf("Enter another char: ");
scanf("%c", &c2); // line 4
printf("Done"); // line 5
system("PAUSE");
return 0;
}
As I read in the C book, the author says that scanf() left a newline character in the buffer, therefore, the program does not stop at line 4 for user to enter the data, rather it stores the new line character in c2 and moves to line 5.
Is that right?
However, does this only happen with char data types? Because I did not see this problem with int data types as in line 1, 2, 3. Is it right?
The scanf() function skips leading whitespace automatically before trying to parse conversions other than characters. The character formats (primarily %c; also scan sets %[…] — and %n) are the exception; they don't skip whitespace.
Use " %c" with a leading blank to skip optional white space. Do not use a trailing blank in a scanf() format string.
Note that this still doesn't consume any trailing whitespace left in the input stream, not even to the end of a line, so beware of that if also using getchar() or fgets() on the same input stream. We're just getting scanf to skip over whitespace before conversions, like it does for %d and other non-character conversions.
Note that non-whitespace "directives" (to use POSIX scanf terminology) other than conversions, like the literal text in scanf("order = %d", &order); doesn't skip whitespace either. The literal order has to match the next character to be read.
So you probably want " order = %d" there if you want to skip a newline from the previous line but still require a literal match on a fixed string, like this question.
Use scanf(" %c", &c2);. This will solve your problem.
Another option (that I got from here) is to read and discard the newline by using the assignment-supression option. To do that, we just put a format to read a character with an asterisk between % and c:
scanf("%d%*c",&a); // line 1
scanf("%c%*c",&c1); // line 3
scanf will then read the next char (that is, the newline) but not assign it to any pointer.
In the end, however, I would second the FAQ's last option:
Or, depending on your requirements, you could also forget about scanf()/getchar(), use fgets() to get a line of text from the user and parse it yourself.
To echo what I have posted in another answer about C++: I suggest to toss scanf() away, to never use it, and to instead use fgets() and sscanf().
The reason for this is, that at least in Unix-like systems by default, the terminal your CLI program runs on does some processing of the user input before your program sees it. It buffers input until a newline is entered, and allows for some rudimentary line editing, like making backspace work.
So, you can never get a single character at a time, or a few single characters, just a full line. But that's not what e.g. scanf("%d") processes, instead it processes just the digits, and stops there, leaving the rest buffered in the C library, for a future stdio function to use. If your program has e.g.
printf("Enter a number: ");
scanf("%d", &a);
printf("Enter a word: ");
scanf("%s", word);
and you enter the line 123 abcd, it completes both scanf()s at once, but only after a newline is given. The first scanf() doesn't return when a user has hit space, even though that's where the number ends (because at that point the line is still in the terminal's line buffer); and the second scanf() doesn't wait for you to enter another line (because the input buffer already contains enough to fill the %s conversion).
This isn't what users usually expect!
Instead, they expect that hitting enter completes the input, and if you hit enter, you either get a default value, or an error, with possibly a suggestion to please really just give the answer.
You can't really do that with scanf("%d"). If the user just hits enter, nothing happens. Because scanf() is still waiting for the number. The terminal sends the line onward, but your program doesn't see it, because scanf() eats it. You don't get a chance to react to the user's mistake.
That's also not very useful.
Hence, I suggest using fgets() or getline() to read a full line of input at a time. This exactly matches what the terminal gives, and always gives your program control after the user has entered a line. What you do with the input line is up to you, if you want a number, you can use atoi(), strtol(), or even sscanf(buf, "%d", &a) to parse the number. sscanf() doesn't have the same mismatch as scanf(), because the buffer it reads from is limited in size, and when it ends, it ends -- the function can't wait for more.
(fscanf() on a regular file can also be fine if the file format is one that supports how it skims over newlines like any whitespace. For line-oriented data, I'd still use fgets() and sscanf().)
So, instead of what I had above, use something like this:
printf("Enter a number: ");
fgets(buf, bufsize, stdin);
sscanf(buf, "%d", &a);
or, actually, check the return value of sscanf() too, so you can detect empty lines and otherwise invalid data:
#include <stdio.h>
int main(void)
{
const int bufsize = 100;
char buf[bufsize];
int a;
int ret;
char word[bufsize];
printf("Enter a number: ");
fgets(buf, bufsize, stdin);
ret = sscanf(buf, "%d", &a);
if (ret != 1) {
fprintf(stderr, "Ok, you don't have to.\n");
return 1;
}
printf("Enter a word: ");
fgets(buf, bufsize, stdin);
ret = sscanf(buf, "%s", word);
if (ret != 1) {
fprintf(stderr, "You make me sad.\n");
return 1;
}
printf("You entered %d and %s\n", a, word);
}
Of course, if you want the program to insist, you can create a simple function to loop over the fgets() and sscanf() until the user deigns to do what they're told; or to just exit with an error immediately. Depends on what you think your program should do if the user doesn't want to play ball.
You could do something similar e.g. by looping over getchar() to read characters until a newline after scanf("%d") returned, thus clearing up any garbage left in the buffer, but that doesn't do anything about the case where the user just hits enter on an empty line. Anyway, fgets() would read until a newline, so you don't have to do it yourself.
Use getchar() before calling second scanf().
scanf("%c", &c1);
getchar(); // <== remove newline
scanf("%c", &c2);
Two workarounds. One is catch the extra whitespace trickly.
getchar(); // (1) add `getchar()`
scanf("%c", &c1);
scanf(" %c", &c1); // (2) add whitespace before %c
The other is using fgets() to instead scanf(). Note: gets() is unsafe, see why gets is dangerous
By contrast, I would prefer to recommend the second way. Because it's more readable and maintainable. For example, in first way, you must think a while before adding/moving some scanf().
/*Take char input using scanf after int input using scanf just use fflush(stdin) function after int input */
#include<stdio.h>
#include<conio.h>
void main()
{
int x;
char y;
clrscr();
printf(" enter an int ");
scanf("%d",&x);
fflush(stdin);
printf("\n Now enter a char");
scanf("%c",&y);
printf("\n X=%d and Y=%c",x,y);
getch();
}

scanf_s("%c", &mathOparation, 1); doesn't work [duplicate]

I have the following program:
int main(int argc, char *argv[])
{
int a, b;
char c1, c2;
printf("Enter something: ");
scanf("%d", &a); // line 1
printf("Enter other something: ");
scanf("%d", &b); // line 2
printf("Enter a char: ");
scanf("%c", &c1); // line 3
printf("Enter another char: ");
scanf("%c", &c2); // line 4
printf("Done"); // line 5
system("PAUSE");
return 0;
}
As I read in the C book, the author says that scanf() left a newline character in the buffer, therefore, the program does not stop at line 4 for user to enter the data, rather it stores the new line character in c2 and moves to line 5.
Is that right?
However, does this only happen with char data types? Because I did not see this problem with int data types as in line 1, 2, 3. Is it right?
The scanf() function skips leading whitespace automatically before trying to parse conversions other than characters. The character formats (primarily %c; also scan sets %[…] — and %n) are the exception; they don't skip whitespace.
Use " %c" with a leading blank to skip optional white space. Do not use a trailing blank in a scanf() format string.
Note that this still doesn't consume any trailing whitespace left in the input stream, not even to the end of a line, so beware of that if also using getchar() or fgets() on the same input stream. We're just getting scanf to skip over whitespace before conversions, like it does for %d and other non-character conversions.
Note that non-whitespace "directives" (to use POSIX scanf terminology) other than conversions, like the literal text in scanf("order = %d", &order); doesn't skip whitespace either. The literal order has to match the next character to be read.
So you probably want " order = %d" there if you want to skip a newline from the previous line but still require a literal match on a fixed string, like this question.
Use scanf(" %c", &c2);. This will solve your problem.
Another option (that I got from here) is to read and discard the newline by using the assignment-supression option. To do that, we just put a format to read a character with an asterisk between % and c:
scanf("%d%*c",&a); // line 1
scanf("%c%*c",&c1); // line 3
scanf will then read the next char (that is, the newline) but not assign it to any pointer.
In the end, however, I would second the FAQ's last option:
Or, depending on your requirements, you could also forget about scanf()/getchar(), use fgets() to get a line of text from the user and parse it yourself.
To echo what I have posted in another answer about C++: I suggest to toss scanf() away, to never use it, and to instead use fgets() and sscanf().
The reason for this is, that at least in Unix-like systems by default, the terminal your CLI program runs on does some processing of the user input before your program sees it. It buffers input until a newline is entered, and allows for some rudimentary line editing, like making backspace work.
So, you can never get a single character at a time, or a few single characters, just a full line. But that's not what e.g. scanf("%d") processes, instead it processes just the digits, and stops there, leaving the rest buffered in the C library, for a future stdio function to use. If your program has e.g.
printf("Enter a number: ");
scanf("%d", &a);
printf("Enter a word: ");
scanf("%s", word);
and you enter the line 123 abcd, it completes both scanf()s at once, but only after a newline is given. The first scanf() doesn't return when a user has hit space, even though that's where the number ends (because at that point the line is still in the terminal's line buffer); and the second scanf() doesn't wait for you to enter another line (because the input buffer already contains enough to fill the %s conversion).
This isn't what users usually expect!
Instead, they expect that hitting enter completes the input, and if you hit enter, you either get a default value, or an error, with possibly a suggestion to please really just give the answer.
You can't really do that with scanf("%d"). If the user just hits enter, nothing happens. Because scanf() is still waiting for the number. The terminal sends the line onward, but your program doesn't see it, because scanf() eats it. You don't get a chance to react to the user's mistake.
That's also not very useful.
Hence, I suggest using fgets() or getline() to read a full line of input at a time. This exactly matches what the terminal gives, and always gives your program control after the user has entered a line. What you do with the input line is up to you, if you want a number, you can use atoi(), strtol(), or even sscanf(buf, "%d", &a) to parse the number. sscanf() doesn't have the same mismatch as scanf(), because the buffer it reads from is limited in size, and when it ends, it ends -- the function can't wait for more.
(fscanf() on a regular file can also be fine if the file format is one that supports how it skims over newlines like any whitespace. For line-oriented data, I'd still use fgets() and sscanf().)
So, instead of what I had above, use something like this:
printf("Enter a number: ");
fgets(buf, bufsize, stdin);
sscanf(buf, "%d", &a);
or, actually, check the return value of sscanf() too, so you can detect empty lines and otherwise invalid data:
#include <stdio.h>
int main(void)
{
const int bufsize = 100;
char buf[bufsize];
int a;
int ret;
char word[bufsize];
printf("Enter a number: ");
fgets(buf, bufsize, stdin);
ret = sscanf(buf, "%d", &a);
if (ret != 1) {
fprintf(stderr, "Ok, you don't have to.\n");
return 1;
}
printf("Enter a word: ");
fgets(buf, bufsize, stdin);
ret = sscanf(buf, "%s", word);
if (ret != 1) {
fprintf(stderr, "You make me sad.\n");
return 1;
}
printf("You entered %d and %s\n", a, word);
}
Of course, if you want the program to insist, you can create a simple function to loop over the fgets() and sscanf() until the user deigns to do what they're told; or to just exit with an error immediately. Depends on what you think your program should do if the user doesn't want to play ball.
You could do something similar e.g. by looping over getchar() to read characters until a newline after scanf("%d") returned, thus clearing up any garbage left in the buffer, but that doesn't do anything about the case where the user just hits enter on an empty line. Anyway, fgets() would read until a newline, so you don't have to do it yourself.
Use getchar() before calling second scanf().
scanf("%c", &c1);
getchar(); // <== remove newline
scanf("%c", &c2);
Two workarounds. One is catch the extra whitespace trickly.
getchar(); // (1) add `getchar()`
scanf("%c", &c1);
scanf(" %c", &c1); // (2) add whitespace before %c
The other is using fgets() to instead scanf(). Note: gets() is unsafe, see why gets is dangerous
By contrast, I would prefer to recommend the second way. Because it's more readable and maintainable. For example, in first way, you must think a while before adding/moving some scanf().
/*Take char input using scanf after int input using scanf just use fflush(stdin) function after int input */
#include<stdio.h>
#include<conio.h>
void main()
{
int x;
char y;
clrscr();
printf(" enter an int ");
scanf("%d",&x);
fflush(stdin);
printf("\n Now enter a char");
scanf("%c",&y);
printf("\n X=%d and Y=%c",x,y);
getch();
}

C: When using this series of if, else if, and else statements, why does the else always perform [duplicate]

I have the following program:
int main(int argc, char *argv[])
{
int a, b;
char c1, c2;
printf("Enter something: ");
scanf("%d", &a); // line 1
printf("Enter other something: ");
scanf("%d", &b); // line 2
printf("Enter a char: ");
scanf("%c", &c1); // line 3
printf("Enter another char: ");
scanf("%c", &c2); // line 4
printf("Done"); // line 5
system("PAUSE");
return 0;
}
As I read in the C book, the author says that scanf() left a newline character in the buffer, therefore, the program does not stop at line 4 for user to enter the data, rather it stores the new line character in c2 and moves to line 5.
Is that right?
However, does this only happen with char data types? Because I did not see this problem with int data types as in line 1, 2, 3. Is it right?
The scanf() function skips leading whitespace automatically before trying to parse conversions other than characters. The character formats (primarily %c; also scan sets %[…] — and %n) are the exception; they don't skip whitespace.
Use " %c" with a leading blank to skip optional white space. Do not use a trailing blank in a scanf() format string.
Note that this still doesn't consume any trailing whitespace left in the input stream, not even to the end of a line, so beware of that if also using getchar() or fgets() on the same input stream. We're just getting scanf to skip over whitespace before conversions, like it does for %d and other non-character conversions.
Note that non-whitespace "directives" (to use POSIX scanf terminology) other than conversions, like the literal text in scanf("order = %d", &order); doesn't skip whitespace either. The literal order has to match the next character to be read.
So you probably want " order = %d" there if you want to skip a newline from the previous line but still require a literal match on a fixed string, like this question.
Use scanf(" %c", &c2);. This will solve your problem.
Another option (that I got from here) is to read and discard the newline by using the assignment-supression option. To do that, we just put a format to read a character with an asterisk between % and c:
scanf("%d%*c",&a); // line 1
scanf("%c%*c",&c1); // line 3
scanf will then read the next char (that is, the newline) but not assign it to any pointer.
In the end, however, I would second the FAQ's last option:
Or, depending on your requirements, you could also forget about scanf()/getchar(), use fgets() to get a line of text from the user and parse it yourself.
To echo what I have posted in another answer about C++: I suggest to toss scanf() away, to never use it, and to instead use fgets() and sscanf().
The reason for this is, that at least in Unix-like systems by default, the terminal your CLI program runs on does some processing of the user input before your program sees it. It buffers input until a newline is entered, and allows for some rudimentary line editing, like making backspace work.
So, you can never get a single character at a time, or a few single characters, just a full line. But that's not what e.g. scanf("%d") processes, instead it processes just the digits, and stops there, leaving the rest buffered in the C library, for a future stdio function to use. If your program has e.g.
printf("Enter a number: ");
scanf("%d", &a);
printf("Enter a word: ");
scanf("%s", word);
and you enter the line 123 abcd, it completes both scanf()s at once, but only after a newline is given. The first scanf() doesn't return when a user has hit space, even though that's where the number ends (because at that point the line is still in the terminal's line buffer); and the second scanf() doesn't wait for you to enter another line (because the input buffer already contains enough to fill the %s conversion).
This isn't what users usually expect!
Instead, they expect that hitting enter completes the input, and if you hit enter, you either get a default value, or an error, with possibly a suggestion to please really just give the answer.
You can't really do that with scanf("%d"). If the user just hits enter, nothing happens. Because scanf() is still waiting for the number. The terminal sends the line onward, but your program doesn't see it, because scanf() eats it. You don't get a chance to react to the user's mistake.
That's also not very useful.
Hence, I suggest using fgets() or getline() to read a full line of input at a time. This exactly matches what the terminal gives, and always gives your program control after the user has entered a line. What you do with the input line is up to you, if you want a number, you can use atoi(), strtol(), or even sscanf(buf, "%d", &a) to parse the number. sscanf() doesn't have the same mismatch as scanf(), because the buffer it reads from is limited in size, and when it ends, it ends -- the function can't wait for more.
(fscanf() on a regular file can also be fine if the file format is one that supports how it skims over newlines like any whitespace. For line-oriented data, I'd still use fgets() and sscanf().)
So, instead of what I had above, use something like this:
printf("Enter a number: ");
fgets(buf, bufsize, stdin);
sscanf(buf, "%d", &a);
or, actually, check the return value of sscanf() too, so you can detect empty lines and otherwise invalid data:
#include <stdio.h>
int main(void)
{
const int bufsize = 100;
char buf[bufsize];
int a;
int ret;
char word[bufsize];
printf("Enter a number: ");
fgets(buf, bufsize, stdin);
ret = sscanf(buf, "%d", &a);
if (ret != 1) {
fprintf(stderr, "Ok, you don't have to.\n");
return 1;
}
printf("Enter a word: ");
fgets(buf, bufsize, stdin);
ret = sscanf(buf, "%s", word);
if (ret != 1) {
fprintf(stderr, "You make me sad.\n");
return 1;
}
printf("You entered %d and %s\n", a, word);
}
Of course, if you want the program to insist, you can create a simple function to loop over the fgets() and sscanf() until the user deigns to do what they're told; or to just exit with an error immediately. Depends on what you think your program should do if the user doesn't want to play ball.
You could do something similar e.g. by looping over getchar() to read characters until a newline after scanf("%d") returned, thus clearing up any garbage left in the buffer, but that doesn't do anything about the case where the user just hits enter on an empty line. Anyway, fgets() would read until a newline, so you don't have to do it yourself.
Use getchar() before calling second scanf().
scanf("%c", &c1);
getchar(); // <== remove newline
scanf("%c", &c2);
Two workarounds. One is catch the extra whitespace trickly.
getchar(); // (1) add `getchar()`
scanf("%c", &c1);
scanf(" %c", &c1); // (2) add whitespace before %c
The other is using fgets() to instead scanf(). Note: gets() is unsafe, see why gets is dangerous
By contrast, I would prefer to recommend the second way. Because it's more readable and maintainable. For example, in first way, you must think a while before adding/moving some scanf().
/*Take char input using scanf after int input using scanf just use fflush(stdin) function after int input */
#include<stdio.h>
#include<conio.h>
void main()
{
int x;
char y;
clrscr();
printf(" enter an int ");
scanf("%d",&x);
fflush(stdin);
printf("\n Now enter a char");
scanf("%c",&y);
printf("\n X=%d and Y=%c",x,y);
getch();
}

Facing a problem with the scanf function in C [duplicate]

I have the following program:
int main(int argc, char *argv[])
{
int a, b;
char c1, c2;
printf("Enter something: ");
scanf("%d", &a); // line 1
printf("Enter other something: ");
scanf("%d", &b); // line 2
printf("Enter a char: ");
scanf("%c", &c1); // line 3
printf("Enter another char: ");
scanf("%c", &c2); // line 4
printf("Done"); // line 5
system("PAUSE");
return 0;
}
As I read in the C book, the author says that scanf() left a newline character in the buffer, therefore, the program does not stop at line 4 for user to enter the data, rather it stores the new line character in c2 and moves to line 5.
Is that right?
However, does this only happen with char data types? Because I did not see this problem with int data types as in line 1, 2, 3. Is it right?
The scanf() function skips leading whitespace automatically before trying to parse conversions other than characters. The character formats (primarily %c; also scan sets %[…] — and %n) are the exception; they don't skip whitespace.
Use " %c" with a leading blank to skip optional white space. Do not use a trailing blank in a scanf() format string.
Note that this still doesn't consume any trailing whitespace left in the input stream, not even to the end of a line, so beware of that if also using getchar() or fgets() on the same input stream. We're just getting scanf to skip over whitespace before conversions, like it does for %d and other non-character conversions.
Note that non-whitespace "directives" (to use POSIX scanf terminology) other than conversions, like the literal text in scanf("order = %d", &order); doesn't skip whitespace either. The literal order has to match the next character to be read.
So you probably want " order = %d" there if you want to skip a newline from the previous line but still require a literal match on a fixed string, like this question.
Use scanf(" %c", &c2);. This will solve your problem.
Another option (that I got from here) is to read and discard the newline by using the assignment-supression option. To do that, we just put a format to read a character with an asterisk between % and c:
scanf("%d%*c",&a); // line 1
scanf("%c%*c",&c1); // line 3
scanf will then read the next char (that is, the newline) but not assign it to any pointer.
In the end, however, I would second the FAQ's last option:
Or, depending on your requirements, you could also forget about scanf()/getchar(), use fgets() to get a line of text from the user and parse it yourself.
To echo what I have posted in another answer about C++: I suggest to toss scanf() away, to never use it, and to instead use fgets() and sscanf().
The reason for this is, that at least in Unix-like systems by default, the terminal your CLI program runs on does some processing of the user input before your program sees it. It buffers input until a newline is entered, and allows for some rudimentary line editing, like making backspace work.
So, you can never get a single character at a time, or a few single characters, just a full line. But that's not what e.g. scanf("%d") processes, instead it processes just the digits, and stops there, leaving the rest buffered in the C library, for a future stdio function to use. If your program has e.g.
printf("Enter a number: ");
scanf("%d", &a);
printf("Enter a word: ");
scanf("%s", word);
and you enter the line 123 abcd, it completes both scanf()s at once, but only after a newline is given. The first scanf() doesn't return when a user has hit space, even though that's where the number ends (because at that point the line is still in the terminal's line buffer); and the second scanf() doesn't wait for you to enter another line (because the input buffer already contains enough to fill the %s conversion).
This isn't what users usually expect!
Instead, they expect that hitting enter completes the input, and if you hit enter, you either get a default value, or an error, with possibly a suggestion to please really just give the answer.
You can't really do that with scanf("%d"). If the user just hits enter, nothing happens. Because scanf() is still waiting for the number. The terminal sends the line onward, but your program doesn't see it, because scanf() eats it. You don't get a chance to react to the user's mistake.
That's also not very useful.
Hence, I suggest using fgets() or getline() to read a full line of input at a time. This exactly matches what the terminal gives, and always gives your program control after the user has entered a line. What you do with the input line is up to you, if you want a number, you can use atoi(), strtol(), or even sscanf(buf, "%d", &a) to parse the number. sscanf() doesn't have the same mismatch as scanf(), because the buffer it reads from is limited in size, and when it ends, it ends -- the function can't wait for more.
(fscanf() on a regular file can also be fine if the file format is one that supports how it skims over newlines like any whitespace. For line-oriented data, I'd still use fgets() and sscanf().)
So, instead of what I had above, use something like this:
printf("Enter a number: ");
fgets(buf, bufsize, stdin);
sscanf(buf, "%d", &a);
or, actually, check the return value of sscanf() too, so you can detect empty lines and otherwise invalid data:
#include <stdio.h>
int main(void)
{
const int bufsize = 100;
char buf[bufsize];
int a;
int ret;
char word[bufsize];
printf("Enter a number: ");
fgets(buf, bufsize, stdin);
ret = sscanf(buf, "%d", &a);
if (ret != 1) {
fprintf(stderr, "Ok, you don't have to.\n");
return 1;
}
printf("Enter a word: ");
fgets(buf, bufsize, stdin);
ret = sscanf(buf, "%s", word);
if (ret != 1) {
fprintf(stderr, "You make me sad.\n");
return 1;
}
printf("You entered %d and %s\n", a, word);
}
Of course, if you want the program to insist, you can create a simple function to loop over the fgets() and sscanf() until the user deigns to do what they're told; or to just exit with an error immediately. Depends on what you think your program should do if the user doesn't want to play ball.
You could do something similar e.g. by looping over getchar() to read characters until a newline after scanf("%d") returned, thus clearing up any garbage left in the buffer, but that doesn't do anything about the case where the user just hits enter on an empty line. Anyway, fgets() would read until a newline, so you don't have to do it yourself.
Use getchar() before calling second scanf().
scanf("%c", &c1);
getchar(); // <== remove newline
scanf("%c", &c2);
Two workarounds. One is catch the extra whitespace trickly.
getchar(); // (1) add `getchar()`
scanf("%c", &c1);
scanf(" %c", &c1); // (2) add whitespace before %c
The other is using fgets() to instead scanf(). Note: gets() is unsafe, see why gets is dangerous
By contrast, I would prefer to recommend the second way. Because it's more readable and maintainable. For example, in first way, you must think a while before adding/moving some scanf().
/*Take char input using scanf after int input using scanf just use fflush(stdin) function after int input */
#include<stdio.h>
#include<conio.h>
void main()
{
int x;
char y;
clrscr();
printf(" enter an int ");
scanf("%d",&x);
fflush(stdin);
printf("\n Now enter a char");
scanf("%c",&y);
printf("\n X=%d and Y=%c",x,y);
getch();
}

Resources