why first gets() function is not working? - c

Here first gets() is not working. if I add one more gets() function then from the two last one goes to work. how can I fix it?
CODE
#include<stdio.h>
#include<string.h>
int main(void)
{
short int choice;
char number[15];
do{
printf("\n\nAnswer: ");
scanf("%hd",&choice);
printf("\n");
if(choice==1)
{
printf("Enter the decimal number: ");
gets(number);
}
else
{
printf("Wrong input!.");
system("pause");
system("cls");
}
}while(choice!=1);
return 0;
}

Because the when the user pressed the enter key to give you the input for the scanf call, the enter key added a newline in the input buffer. And the gets call read that newline as an empty line.
One way to solve it is to use fgets to read the first input too, and use sscanf to parse it to a number:
...
printf("\n\nAnswer: ");
char input[64];
fgets(input, sizeof(input), stdin);
sscanf(input, "%hd", &choice);
printf("\n");
...
This make sure that the newline after the input is read and skipped.
Another way is to read one character at a time in a loop after the scanf call, until you have read the newline:
scanf("%hd", &choice);
int ch;
while ((ch = fgetc(stdin)) != EOF && ch != '\n')
{
// Empty
}
And a third way is to simply ask the scanf call to read and ignore white-space after the input:
scanf("%hd ", &choice);
// ^
// |
// Note space here
All of these methods have both pros and cons. You can try them all and use the one that works for you.

You need to skip the whitespace (i.e. the newline) following the number in the input buffer. This can be done by modifying the scanf to:
scanf("%hd ",&choice);
And use fgets(), since gets() is prone to buffer overflows.

Related

Issues with scanf() and accepting user input

I am trying to take in user input with spaces and store it in an array of characters.
After, I want to take in a single character value and store it as a char.
However, when I run my code, the prompt for the character gets ignored and a space is populated instead. How can I take in an array of chars and still be allowed to prompt for a single character after?
void main()
{
char userIn[30];
char findChar;
printf("Please enter a string: ");
scanf("%[^\n]s", userIn);
printf("Please enter a character to search for: ");
scanf("%c", &findChar);
//this was put here to see why my single char wasnt working in a function I had
printf("%c", findChar);
}
scanf("%c", &findChar); reads the next character pending in the input stream. This character will be the newline entered by the user that stopped the previous conversion, so findChar will be set to the value '\n', without waiting for any user input and printf will output this newline without any other visible effect.
Modify the call as scanf(" %c", &findChar) to ignore pending white space and get the next character from the user, or more reliably write a loop to read the read and ignore of the input line.
Note also that scanf("%[^\n]s", userIn); is incorrect:
scanf() may store bytes beyond the end of userIn if the user types more than 29 bytes of input.
the s after the ] is a bug, the conversion format for character classes is not a variation of the %s conversion.
Other problems:
void is not a proper type for the return value of the main() function.
the <stdio.h> header is required for this code.
Here is a modified version:
#include <stdio.h>
int main() {
char userIn[30];
int c;
char findChar;
int i, found;
printf("Please enter a string: ");
if (scanf("%29[^\n]", userIn) != 1) {
fprintf(stderr, "Input failure\n");
return 1;
}
/* read and ignore the rest of input line */
while ((c = getchar()) != EOF && c != '\n')
continue;
printf("Please enter a character to search for: ");
if (scanf("%c", &findChar) != 1) {
fprintf(stderr, "Input failure\n");
return 1;
}
printf("Searching for '%c'\n", findChar);
found = 0;
for (i = 0; userIn[i] != '\0'; i++) {
if (userIn[i] == findChar) {
found++;
printf("found '%c' at offset %d\n", c, i);
}
}
if (!found) {
printf("character '%c' not found\n", c);
}
return 0;
}
scanf("%[^\n]s", userIn); is a bit weird. The s is guaranteed not to match, since that character will always be \n. Also, you should use a width modifier to avoid a buffer overflow. Use scanf("%29[^\n]", userIn); That alone will not solve the problem, since the next scanf is going to consume the newline. There are a few options. You could consume the newline in the first scanf with:
scanf("%29[^\n]%*c", userIn);
or discard all whitespace in the next call with
scanf(" %c", &findChar);
The behavior will differ on lines of input that exceed 29 characters in length or when the user attempts to assign whitespace to findChar, so which solution you use will depend on how you want to handle those situations.

2D character array in C [duplicate]

This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 3 years ago.
In C:
I'm trying to get char from the user with scanf and when I run it the program don't wait for the user to type anything...
This is the code:
char ch;
printf("Enter one char");
scanf("%c", &ch);
printf("%c\n",ch);
Why is not working?
The %c conversion specifier won't automatically skip any leading whitespace, so if there's a stray newline in the input stream (from a previous entry, for example) the scanf call will consume it immediately.
One way around the problem is to put a blank space before the conversion specifier in the format string:
scanf(" %c", &c);
The blank in the format string tells scanf to skip leading whitespace, and the first non-whitespace character will be read with the %c conversion specifier.
First of all, avoid scanf(). Using it is not worth the pain.
See: Why does everyone say not to use scanf? What should I use instead?
Using a whitespace character in scanf() would ignore any number of whitespace characters left in the input stream, what if you need to read more inputs? Consider:
#include <stdio.h>
int main(void)
{
char ch1, ch2;
scanf("%c", &ch1); /* Leaves the newline in the input */
scanf(" %c", &ch2); /* The leading whitespace ensures it's the
previous newline is ignored */
printf("ch1: %c, ch2: %c\n", ch1, ch2);
/* All good so far */
char ch3;
scanf("%c", &ch3); /* Doesn't read input due to the same problem */
printf("ch3: %c\n", ch3);
return 0;
}
While the 3rd scanf() can be fixed in the same way using a leading whitespace, it's not always going to that simple as above.
Another major problem is, scanf() will not discard any input in the input stream if it doesn't match the format. For example, if you input abc for an int such as: scanf("%d", &int_var); then abc will have to read and discarded. Consider:
#include <stdio.h>
int main(void)
{
int i;
while(1) {
if (scanf("%d", &i) != 1) { /* Input "abc" */
printf("Invalid input. Try again\n");
} else {
break;
}
}
printf("Int read: %d\n", i);
return 0;
}
Another common problem is mixing scanf() and fgets(). Consider:
#include <stdio.h>
int main(void)
{
int age;
char name[256];
printf("Input your age:");
scanf("%d", &age); /* Input 10 */
printf("Input your full name [firstname lastname]");
fgets(name, sizeof name, stdin); /* Doesn't read! */
return 0;
}
The call to fgets() doesn't wait for input because the newline left by the previous scanf() call is read and fgets() terminates input reading when it encounters a newline.
There are many other similar problems associated with scanf(). That's why it's generally recommended to avoid it.
So, what's the alternative? Use fgets() function instead in the following fashion to read a single character:
#include <stdio.h>
int main(void)
{
char line[256];
char ch;
if (fgets(line, sizeof line, stdin) == NULL) {
printf("Input error.\n");
exit(1);
}
ch = line[0];
printf("Character read: %c\n", ch);
return 0;
}
One detail to be aware of when using fgets() will read in the newline character if there's enough room in the inut buffer. If it's not desirable then you can remove it:
char line[256];
if (fgets(line, sizeof line, stdin) == NULL) {
printf("Input error.\n");
exit(1);
}
line[strcpsn(line, "\n")] = 0; /* removes the trailing newline, if present */
This works for me try it out
int main(){
char c;
scanf(" %c",&c);
printf("%c",c);
return 0;
}
Here is a similiar thing that I would like to share,
while you're working on Visual Studio you could get an error like:
'scanf': function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS
To prevent this, you should write it in the following format
A single character may be read as follows:
char c;
scanf_s("%c", &c, 1);
When multiple characters for non-null terminated strings are read, integers are used as the width specification and the buffer size.
char c[4];
scanf_s("%4c", &c, _countof(c));
neither fgets nor getchar works to solve the problem.
the only workaround is keeping a space before %c while using scanf
scanf(" %c",ch); // will only work
In the follwing fgets also not work..
char line[256];
char ch;
int i;
printf("Enter a num : ");
scanf("%d",&i);
printf("Enter a char : ");
if (fgets(line, sizeof line, stdin) == NULL) {
printf("Input error.\n");
exit(1);
}
ch = line[0];
printf("Character read: %c\n", ch);
try using getchar(); instead
syntax:
void main() {
char ch;
ch = getchar();
}
Before the scanf put fflush(stdin); to clear buffer.
The only code that worked for me is:
scanf(" %c",&c);
I was having the same problem, and only with single characters. After an hour of random testing I can not report an issue yet. One would think that C would have by now a bullet-proof function to retrieve single characters from the keyboard, and not an array of possible hackarounds... Just saying...
Use string instead of char
like
char c[10];
scanf ("%s", c);
I belive it works nice.
Provides a space before %c conversion specifier so that compiler will ignore white spaces. The program may be written as below:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char ch;
printf("Enter one char");
scanf(" %c", &ch); /*Space is given before %c*/
printf("%c\n",ch);
return 0;
}
You have to use a valid variable. ch is not a valid variable for this program. Use char Aaa;
char aaa;
scanf("%c",&Aaa);
Tested and it works.

scanf skipped after loop in C [duplicate]

This question already has answers here:
fgets doesn't work after scanf [duplicate]
(7 answers)
Closed 2 years ago.
#define len 100
char sourceString[len];
char command;
int main(void)
{
while (1)
{
printf("\nEnter source: ");
fgets(sourceString, len, stdin); // this gets skipped on second loop.
printf("\nEnter command: ");
scanf(" %c", command)
switch (command)
{
case 'A':
printf("%s", sourceString);
break;
case 'B':
printf("filler");
break;
default:
break;
}
}
return 0;
}
Whether im using fgets or scanf the string always gets skipped on the second loop.
I tried adding a space to the second scanf " %c" but it still skips the string input, yes im trying to read a line and then a character.
After the call of scanf insert the following calls
scanf( "%*[^\n]" );
scanf( "%*c" );
to remove the new line character '\n' from the input buffer.
Use fgets() for both and just derefernce the array holding command to get the first character -- ensures a complete line is read.
Your problem is scanf() is leaving the '\n' in your input stream which on your next iteration is taken by fgets() (since fgets() reads up to and including the next '\n' in the input stream). This makes it appear like fgets() was skipped -- it wasn't it just read the '\n' left by scanf().
#define len 100
int main(void)
{
char sourceString[len]; /* don't use global variables */
char command[len];
while (1)
{
printf ("\nEnter source: ");
fgets (sourceString, len, stdin); // this no longer skipped in loop.
printf("\nEnter command: ");
fgets (command, len, stdin);
switch (*command)
{
case 'A':
printf("%s", sourceString);
break;
case 'B':
printf("filler");
break;
default:
break;
}
}
return 0;
}
(note: you must always check the return of EVERY input function call -- that is left to you. See Henry Spencer's 10 Commandments for C Programmers - No. 6 "Ye be warned...")
Let me know if you have further questions.
The problem is that the fgets() function in the second loop captures '\n', which is when you press enter after you type input to the scanf() of the first loop.
There is a solution to overcome this problem which is to add a getchar() function after scanf() so that it captures the '\n' instead of the fgets() of the second loop and the following loops. Here is a sample program :
while (1)
{
printf("\nEnter source: ");
fgets(sourceString, len, stdin);
printf("\nEnter command: ");
scanf(" %c", &command);
getchar();
/* Rest of the program would follow */
}
Here are the steps that explain the observed behavior:
printf("\nEnter source: "); : the prompt is printed.
fgets(sourceString, len, stdin); an input line is read, you should test the return value to ensure fgets() succeeded.
printf("\nEnter command: "); a line is skipped and a new prompt is output.
scanf(" %c", command) any initial white space is skipped (including pending newlines) and a single character is read. Note however that the user must type enter for this character to be made available to the program because the terminal is most likely in cooked mode, ie: line buffered. Also note that you must pass the address of charvariable command or undefined behavior will ensue.
the switch selects what gets done and the loop skips to the next iteration
printf("\nEnter source: "); : the prompt is printed.
fgets(sourceString, len, stdin); fgets() returns immediately with an empty line because the newline typed above is still pending in the input buffer. This is the problem.
You can fix this behavior by discarding the rest of the pending line after the character is read with:
scanf("%*[^\n]"); // read any characters except newline
scanf("%*1[\n]"); // read at most 1 newline character
You must use 2 separate calls to scanf() because the first conversion would fail if there are no characters before the newline.
#incude <stdio.h>
#define LEN 100
int main(void) {
char sourceString[LEN];
char command;
for (;;) {
printf("\nEnter source: ");
if (!fgets(sourceString, len, stdin))
break;
printf("\nEnter command: ");
/* read a single non blank character and discard the rest of the line */
if (scanf(" %c%*[^\n]", &command) != 1)
break;
/* discard the pending newline if any */
scanf("%*1[\n]"); // of just getchar()
switch (command) {
case 'A':
printf("%s", sourceString);
break;
case 'B':
printf("filler");
break;
default:
break;
}
}
return 0;
}

Calling scanf() after another string input function creates phantom input

Here's a small program:
#include <stdio.h>
int main() {
char str[21], choice[21]; int size;
while(1){
printf("$ ");
fgets(str, 20, stdin);
printf("Entered string: %s", str);
if(str[0] == 'q') {
printf("You sure? (y/n) ");
scanf("%s", choice);
if(choice[0] == 'y' || choice[0] == 'Y')
break;
}
}
return 0;
}
It reads a string using fgets(). If the string starts with a q, it confirms if the user wants to quit, and exits if the user types y.
When I run it and type q, this happens:
$ q
Entered string: q
You sure? (y/n) n
$ Entered string:
$
Note the $ Entered string:. Clearly, fgets() got an empty character or something as input, even though I didn't type anything.
What's going on?
As described in other answer scanf call leaves the newline in the input buffer you can also use getchar() after scanf like this :
scanf("%20s", choice);// always remember( & good) to include field width
// in scanf while reading
Strings otherwise it will overwrite buffer in case of large strings `
getchar(); //this will eat up the newline
Besides , you should also use fgets like this :
fgets(str,sizeof str, stdin); //Its better
It because the scanf call reads a character, but leaves the newline in the buffer. So when you next time call fgets is finds that one newline character and reads it resulting in an empty line being read.
The solution is deceptively simple: Put a space after the format in the scanf call:
scanf("%s ", choice);
/* ^ */
/* | */
/* Note space */
This will cause scanf to read and discard all training whitespace, including newlines.
Use a 'char' of a specific size char choice [1]
OR
char c[1];
c = getchar();
if(c[0] == 'y' || c[1] == 'y'){
// DO SOMETHING
}

read char from console

I write console application which performs several scanf for int
And after it ,I performs getchar :
int x,y;
char c;
printf("x:\n");
scanf("%d",&x);
printf("y:\n");
scanf("%d",&y);
c = getchar();
as a result of this I get c = '\n',despite the input is:
1
2
a
How this problem can be solved?
This is because scanf leaves the newline you type in the input stream. Try
do
c = getchar();
while (isspace(c));
instead of
c = getchar();
Call fflush(stdin); after scanf to discard any unnecessary chars (like \r \n) from input buffer that were left by scanf.
Edit: As guys in comments mentioned fflush solution could have portability issue, so here is my second proposal. Do not use scanf at all and do this work using combination of fgets and sscanf. This is much safer and simpler approach, because allow handling wrong input situations.
int x,y;
char c;
char buffer[80];
printf("x:\n");
if (NULL == fgets(buffer, 80, stdin) || 1 != sscanf(buffer, "%d", &x))
{
printf("wrong input");
}
printf("y:\n");
if (NULL == fgets(buffer, 80, stdin) || 1 != sscanf(buffer, "%d", &y))
{
printf("wrong input");
}
c = getchar();
You can use the fflush function to clear anything left in buffer as a consquence of previous comand line inputs:
fflush(stdin);
A way to clean up anyspace before your desired char and just ignore the remaining chars is
do {
c = getchar();
} while (isspace(c));
while (getchar() != '\n');
For a start the scanf should read scanf("%d\n", &x); or y. That should do the trick.
man scanf

Resources