scanf() gets skipped in for loop - c

In Windows i used flushall() function to flush all the buffers but this doesnt work in Linux, my scanf() function skips without scanning:
for(i=0;i<n;i++)
{
printf("\nEnter alphabet :");
scanf("%c",&x);
printf("\nEnter frequency :");
scanf("%f",&probability);
/* create a new tree and insert it in
the priority linked list */
p=(treenode*)malloc(sizeof(treenode));
p->left=p->right=NULL;
p->data=x;
p->freq=(float)probability;
head=insert(head,p);
}
Output :
mayur#mayur-laptop:~$ ./a.out
Enter alphabet :a
Enter frequency :2
Enter alphabet :
Enter frequency :a
Enter alphabet :
Enter frequency :2
Enter alphabet :
Enter frequency :a
Enter alphabet :

You should add a space on the beginning of the scanf, and fflush(stdin) before every scanf just to clear the standard input buffer (keyboard by default), like this:
for(i=0;i<n;i++){
printf("\nEnter alphabet :");
fflush(stdin);
scanf(" %c",&x);
printf("\nEnter frequency :");
fflush(stdin);
scanf(" %f",&probability);
/* create a new tree and insert it in
the priority linked list */
p=(treenode*)malloc(sizeof(treenode));
p->left=p->right=NULL;
p->data=x;
p->freq=(float)probability;
head=insert(head,p);
}
EDIT: check if you have char x and float probability

Update: The OP changed the "%d"in the first scanf to "%c" which lets the error, I think, occur later; but franky, I don't feel investing any more time here.--
Original answer: The input is never processed beyond the 'a' because you try reading it with the conversion specification %d for integer numbers which it doesn't satisfy. (In order to read a char you would specify %c.) Scanf puts the offending character back in the input and tries to read the next number which fails again, and so on ad eternum.
It's worth checking scanf's return value which will always be 0 here, indicating that no successful conversion has taken place.

Related

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.

fgets printing two lines before input

So I am trying to write a program that will let me read a user input for data on an MP3 file using a doubly linked list data structure. I got most of the methods and functions to work, but when I am prompting the user to put in input it prints out two lines before the user can input for the first line. So for example
int main()
{
int user_input = 0;
while(!(user_input >= 4))
{
struct MP3_data_node* MP3_data;
MP3_data = (struct MP3_data_node*)malloc(sizeof(struct MP3_data_node));
printf("\nPlease select a number for one of the following instructions:\n");
printf("0: add to list\n1: delete from list\n2: print the list from beginning to end\n3: print the list from end to beginning\n4: exit\n");
scanf("%d", &user_input);
if(user_input == 0)
{
printf("Please provide the artist:");
fgets(MP3_data->artist,50,stdin);
printf("Please provide the album:");
fgets(MP3_data->artist,50,stdin);
printf("Please provide the song title:");
fgets(MP3_data->artist,50,stdin);
printf("Please provide the year the song was released: ");
scanf("%d", &MP3_data->yearReleased);
printf("Please provide the length of the song in seconds: ");
scanf("%d", &MP3_data->runTime);
addToList(MP3_data);
}
...
So it prints out "Please provide the artist:Please provide the album:" and then let's me put the input in, so my question is how do I make it so that it prints:
Please provide the artist: (user input)
Please provide the album: (user input)
etc.
You're doing the right thing (fgets) int the first few prompts, then you switch to scanf which is the source of your problem. Use fgets (and strtol) instead of scanf and you will be fine. (And, the first scanf which causes the problem described in your question.)
The problem is that scanf only reads the digit part of whatever you enter. That means if you type 12Enter, then the scanf reads the 1 and 2 but leaves the Enter in the input buffer for the next call to fgets or scanf. On the other hand, fgets reads everything you type including the Enter, avoiding this problem.

Why scanf is behaving weird for char input?

/* Write macro for the following :
1. Arithmetic Mean of two no.
2. Absolute value of a no.
3. To convert a Uppercase letter to lower case.
4. To obtain bigger of two numbers.
*/
#include<stdio.h>
#define am(a,b) ((a+b)/2)
#define abs(a) (a>=0?a:-a)
#define ul(ch) (ch>=65 && ch<=96 ? ch+32 : ch)
#define bigger(a,b) (a>=b?a:b)
int main () {
int x,y;
char c;
printf("\nEnter two numbers:");
scanf("%d%d",&x,&y);
printf("\nThe arithmetic mean of two numbers is %f",(float)am(x,y));
printf("\nEnter the number:");
scanf("%d",&x);
printf("\nThe absolute value of the number is %d",abs(x));
printf("\nEnter the character:");
scanf("%c",&c);
printf("\nThe letter in lower case is %c",ul(c));
printf("\nEnter two numbers:");
scanf("%d%d",&x,&y);
printf("\nThe bigger of two numbers is %d",bigger(x,y));
return 0;
}
Everything is working fine except that program does not stop for taking character input.
Here is the snapshot of the output ....
Enter two numbers:4
5
The arithmetic mean of two numbers is 4.000000
Enter the number:-7 **/*After hitting enter here it reaches line no. 7 */**
The absolute value of the number is 7
Enter the character:
The letter in lower case is
Enter two numbers:4 **/*line no. 7*/**
6
The bigger of two numbers is 6
It is because the %d skips white space, but %c does not -- or in other words.
The %d will skip any proceeding white space in your input stream, and the input pointer will be then just after the last digit -- which is most likely you newline. So when you come to ask for the %c you will actually already have input data -- that is your newline -- and that is what you will read.
change your scanf to ask it to skip white space by just inserting a space before the %c, so
scanf(" %c",&c);
I believe the problem here is that your scanf("%c",&c) is grabbing the carriage return entered when you hit enter to put in the -7.
Put a getchar (or another scanf("%c",&c)) right before the scanf and you shouldn't have that problem.
%c reads any character including whitescape, so it will "eat" the newline character.
Use: scanf(" %c",&c);
A common issue with scanf is that it doesn't consume the newline caused by pressing enter. I usually get around it by using the following macro after a call to scanf
#define consumeBuffer() while (getchar() != '\n');
Of course this is not always what you want, but for most cases it will do the trick.
That's because after your first scanf, the enter key is still in the input buffer, and the next scanf will store the enter value in x. Then your next printf will print it - effectively moving to a new line.
To fix this you can just add a getchar() call after each scanf.

Question about input with scanf

When I execute the following program it get the user input for account details and then prints it correctly, but it cannot read the opt value (y/n). It automatically calls again. How can I get the program to exit when the user inputs "n"?
char opt;
do
{
//Getting user input
printf("\n Enter the Account Number:\n ");
scanf("%d",&gAccNo_i);
printf("\n Enter the Account Holder's Name:\n ");
scanf("%s",gCustName_c);
printf("\n Enter the Balance Amount:\n ");
scanf("%f",&gBlncAmt_f);
//Printing the input data.
printf("\n Account Number : %d",gAccNo_i);
printf("\n Customer Name : %s",gCustName_c);
printf("\n Balance Amount : %f",gBlncAmt_f);
printf("\n Do u want to wish to continue?(y/n)");
scanf("%c",&opt);
}while(opt!='n');
use opt=getch(); inplace of scanf("%c",&opt);
OR
scanf reads the whitespace that is left in the buffer by previous line. To skip whitespace, add a space to the "%c":
scanf(" %c", &opt);
scanf("%c",&opt);
Will actually read in a space/newline character. Which obviously will not be equal to 'n'.
You may like to take the input as a string and then verify if the first character is a 'n'.
char opts[5];
scanf("%s",opts);
while(opts[0] !='n');

Resources