scanf skipped after loop in C [duplicate] - c

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;
}

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.

Don't Know where i am going wrong while flushing the stdin buffer in below code [duplicate]

This question already has answers here:
How to clear input buffer in C?
(18 answers)
Closed 5 years ago.
I have attached output image of my program. you can see the problem i am facing by clicking here
Below code is my program to read an input from an user as character and check whether it is an alphabet or an number using my_isalpha() and my_isalnum() functions of my own versions of built in function isalpha() and isalnum().
Not working for second iteration of while loop
#include <stdio.h>
#define NUM 1
#define ALPHA 2
#define ASCII 3
#define BLANK 4
int main()
{
char option;
do
{
//declaration of function
char character;
int user_option, status;
//get the character from the user
printf("Enter the Character:");
//clears both buffers to read the character
fflush(stdin);
fflush(stdout);
//reads one character at a time
character = getchar();
//prompt the user for the option to check
printf("Choice Below Option\n");
printf("1.isalnum\n2.isalpha\n");
printf("Enter your Option:");
scanf("%d", &user_option);
//validation of the user_option
switch(user_option)
{
case 1:
status = my_isalnum(character);
if(status == NUM)
{
printf("Character '%c' is an number", character);
}
else
{
printf("Character '%c' is not a number", character);
}
break;
case 2:
status = my_isalpha(character);
if(status == ALPHA)
{
printf("Character '%c' is an Alphabet", character);
}
else
{
printf("Character '%c' is not Alphabet",character);
}
break;
default:
puts("Invalid Choice.....");
}
printf("\nDo you want to continue?[Y/N]:");
scanf(" %c", &option);
}while (option == 'Y' || option == 'y');
fflush(stdin);
fflush(stdout);
return 0;
}
//Function chaecks for the Number
int my_isalnum(char character)
{
return (character >= '0' && character <= '9')? NUM : -1;
}
//functionn checks for the alphabets
int my_isalpha(char character)
{
return (character >= 'a' && character <= 'z' || character >= 'A' && character <= 'Z') ? ALPHA: -1;
}
above code works properly for the first time but during second iteration of while loop. when I give "Y" as an input code dirrectly jumps to user_option part of scanf .rather then waiting for "getchar()"- function.
Even after filushing the buffer using fflush() function i am not able to prompt the program for the character input.
Flushing stdin is undefined behavior. Flushing is meant for output stream not input stream.
As per standard ยง7.21.5.2
If stream points to an output stream or an update stream in which the
most recent operation was not input, the fflush function causes any
unwritten data for that stream to be delivered to the host environment
to be written to the file; otherwise, the behavior is undefined.
Also int getchar(void) : get char() returns an int.
Quickfix: Remove fflush(stdin) from code.
printf("\nDo you want to continue?[Y/N]:");
scanf(" %c", &option);
getchar(); // this dummy getchar() will consume the `\n` from stdin.
}while (option == 'Y')
Note:
Also as other solutions suggest to use fpurge() is an option but again it is non-standard and non-portable.
Here
//clears both buffers to read the character
fflush(stdin);
fflush() doesn't clear stdin buffer as you expected. fflush() is for flushing output stream like stdout not input stream stdin.
To resolve this issue one way is to use extra getchar() to consume \n character. for example
scanf(" %c", &option);
getchar(); /* dummy getchar */
Also here
char character; /* change the type of character to int */
character = getchar();
getchar() return type is of int not char, you need to change the type of character. From the manual page of getchar()
int getchar(void);

why first gets() function is not working?

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.

scanf and no switch case is executed

New bee in C. This is my code (It replaces a character from a string):
#include <stdio.h>
#include <string.h>
#include <conio.h>
void main()
{
char str[100], r, ra;
printf("enter string");
gets(str);
int length;
length= strlen(str);
printf("length of string is %d",length);
printf("\nenter the the character that will replace");
scanf("%c",&r);
printf("where to replace\n b...begning\ne....ending\np....position");
scanf("%c",&ra);
int pos;
switch(ra)
{
case 'b' : str[1]=r; break;
case 'e' : str[length-1] = r; break;
case 'p' : printf("enter position");
scanf("%d",pos);
if(pos<1 || pos>length-1)
printf("please enter a position between 1 and %d",length-1);
else
str[pos]= r;
break;
}
printf("\n after replacing string is %s", str);
getche();
}
The problem is that the IDE is not compiling this part of the program, I know that I am doing some thing wrong, but can't figure out what? Need help please.
scanf("%c",&ra);
int pos;
switch(ra)
{
case 'b' : str[1]=r; break;
case 'e' : str[length-1] = r; break;
case 'p' : printf("enter position");
scanf("%d",pos);
if(pos<1 || pos>length-1)
printf("please enter a position between 1 and %d",length-1);
else
str[pos]= r;
break;
}
use scanf(" %c",&ra) insted of "%c". Because reading with "%c" give you a garbage value in ra.And that value is new line.
When you enter value in a you press something like p and then Enter key. This Enter key still remains in stdin stream.
Next time when you read in ra then the Enter key in stdin stream is returned in ra.
So for removing that Enter key you need to read like " %c".
scanf(" %c", &ra); // space before %c
Unlike most conversions, %c does not skip whitespace before converting a character. After the user enters the number, a carriage return/new-line is left in the input buffer waiting to be read -- so that's what the %c reads.. SO POST
And for the same reason your switch case is not working, since ra does not have the expected value
the problem is that the ide is not compiling this part of the program
Well, that's a strong accusation. Rather than assume that the compiler does decide not to compile part of the code (on a whim), it's a safer bet that your program's execution flow just does not enter that part as you expected.
In particular, scanf does not behave as you think it does. It reads from stdin, which is a buffered input stream. "Buffered" means that it does not provide your program with input until a newline in read, i.e. until the user presses return. But the scanf family of functions doesn't look for new lines, it treats the new-line character as a normal character. In your case, scanning "%c" tries to read any character from the input. The subsequent "%c" then reads the new line, so &ra really is '\n' in your switch statement.
I usually find working with direct input from the user difficult in C, but if you must prompt the user interactively, I suggest that you read in a whole line of input first with fgets and then analyse that line with sscanf. That gets rid of the seemingly out-of-sync input and also allows you to scan a line several times, perhaps for alternative input syntaxes.
So, here's a version of your code that uses this technique:
#include <stdio.h>
#include <string.h>
int main()
{
char str[100], r, ra;
char line[20];
int length;
int pos;
printf("enter string");
fgets(str, 100, stdin); // note: str includes trailing newline
length = strlen(str);
printf("length of string is %d\n", length);
printf("enter the the character that will replace:\n");
fgets(line, 20, stdin);
sscanf(line, " %c ",&r);
printf("where to replace\n");
printf("b...begning\ne....ending\np....position\n");
fgets(line, 20, stdin);
sscanf(line, " %c ", &ra);
switch (ra)
{
case 'b': str[1] = r;
break;
case 'e': str[length - 1] = r;
break;
case 'p': printf("enter position");
fgets(line, 20, stdin);
sscanf(line, "%d ", &pos);
if(pos < 1 || pos > length-1)
printf("please enter a position between 1 and %d",
length-1);
else
str[pos]= r; break;
}
printf("after replacing string is %s", str);
return 0;
}
There are still problems with your code, mainly to do with zero-based array indexing in C. I leave it to you to sort those out. Also, prefer the safer fgets(buf, len, stdin) over gets(str), which does not prevent buffer overflow. And your query for a position should take a pointer to the address of pos, not just pos. And please make a habit of putting the new-line character last in your printf strings. It makes for cleaner reading and matches the way that the buffered output stream works.
The program doesn't compile, the most likely reason is that you are using a compiler that supports C89 only (I guess it's Visual Studio), or you are using C89 mode.
In this code:
scanf("%c",&ra);
int pos;
switch(ra)
{
the variable pos is defined in the middle of a block, which is supported only since C99. The solution is to move all definitions up to the beginning of a block:
int main()
{
char str[100], r, ra;
int pos;
printf("enter string");
Use fgets() to replace gets(), use int main to replace void main. And fix the problem with using scanf that is covered by the other answers.

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
}

Resources