how field specifier works in C - 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.

Related

Ambigious nature of scanf taking input before it is asked to enter from user?

#include<stdio.h>
void main(){
int num1,num2;
printf("\n Enter number 1 \t "); // Ask for input one. >>>>>>>> line 1.
scanf("%d ",&num1);
printf("\n Entered number is %d \n",num1);
printf("\n Enter number 2 \t "); // Ask for input Two. >>>>>>>>> line 2.
scanf("%d ",&num2);
printf("\n Entered number is %d \n",num2);
return;
}
I wish to know REASON.Please do provide it.
The code above accepts two inputs,first input is asked(By executing line 1) then user enter one number then terminal should ask to enter second input but instead it is taking other number(before executing line2 ) and then asking to enter second input(i.e after executing line 2).
In the End is is displaying the two input that are taken before executing line two but after executing line 1.
I am confused.I am interested to know reason.
I am using GCC 4.8.2 on ubuntu 14.04 64 bit machine.
Remove spaces between the scanf of access specifier.
scanf("%d ",&num1);
to
scanf("%d",&num1);
Because the scanf get the another value due to that spaces.
And kept in the buffer. After the memory has got it get assigned.
It is for all scanf function.
if I input like
Enter Number1 1
2
Entered number is 1
Enter number2 3
Entered number is 2.
It is better to use int main() and in the end write return 0;
use fflush(stdout); to flush your buffer.
After editing here is the final code
#include<stdio.h>
int main(){
int num1,num2;
printf("\n Enter number 1 \t "); // Ask for input one. >>>>>>>> line 1.
scanf("%d ",&num1);
printf("\n Entered number is %d \n",num1);
printf("\n Enter number 2 \t "); // Ask for input Two. >>>>>>>>> line 2.
fflush(stdout);
scanf("%d ",&num2);
printf("\n Entered number is %d \n",num2);
return 0;
}
Here is the Demo.
You need to put
fflush(stdout);
before the scanf
This will flush your buffer
(also a good idea to check the return value of scanf)
You have given a space in scanf for %d. If you remove that space after %d the program will run
Let's take this apart slowly
#include <stdio.h>
// void main(){
int main(void) {
int num1, num2;
printf("\n Enter number 1 \t ");
scanf("%d ",&num1);
printf("\n Entered number is %d \n",num1);
...
Use a proper function signature for main() - but that is not the main issue.
Code prints "\n Enter number 1 \t "
"%d" directs scanf() to scan for text convertible to an int in 3 steps:
A: Scan for optional leading white-space like '\n', '\t', ' '. Throw them away.
B: Scan for text representing an integer like "+1234567890". If any digits found, save the converted result to the address &num1.
C: Scanning continues in step B until a char that does not belong to the int is found. That char is "un-read" and returned to stdin.
(This is where you get in trouble as suggested by #Chandru) " " directs scanf() to scan for any number (0 or more) white spaces including '\n', '\t', ' ' and others. Then they are thrown away - not saved.
B: Scanning continues!! until a non-white-space is found. That char is "un-read" and returned to stdin.
Lastly scanf() return the value of 1 as that is how many field specifiers were converted. Code sadly did not check this value.
Recall stdin is usually line buffered, which means input is not available to user IO until Enter is hit.
User enters 1 2 3 Enter and scanf() scans the "123" and saves 123 to &num1. Then it scans "\n" as that is a white-space in step 4. and it continues waiting for more white-space.
User enters 4 5 6 Enter and the first scanf() which is not yet done, scans '4', sees it is not a white space and puts '4' back in stdin. scanf() finally returns after 2 lines are entered. At this point "456\n" are waiting in stdio for subsequent scanf().
The second scanf() then perpetuates the issue.
Recommend use fgets() only for all user input, at least until your are very skilled in C.
printf("\n Enter number 1 \t ");
char buf[100];
fgets(buf, sizeof buf, stdin);
if (sscanf(buf, "%d", &num1) != 1) Handle_BadInput();
else printf("\n Entered number is %d \n",num1);

Fgets skipping input and printing next line?

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

how to read enter input on c

This function will be called by the menu.
void exponentiation()
{
int i, result = 0, first, second;
printf("\n%s\n%s\n\n%s",
"1) Exponentiation",
"------------------",
"Enter 1st integer: ");
scanf("%d", &first);
printf("Enter 2nd integer: ");
scanf("%d", &second);
printf("%d raised to %d equals %d\n", first, second, result);
main();
}
From this function I need to read the user input, if the user input is "enter" without any integer, it should be going back to the menu which is calling the main().
I already tried to get the input.
For example:
if(first == '\n')
{main();}
or
if(first == 10) /**which is 10 is ASCII code for enter**/
{main()}
Both ways it didn't work at all, any suggestions?
both ways it didn't work at all, any suggestion
The function scanf returns the number of items it successfully scanned. You should check its return and go back if it doesn't matches your expectations.
Also you should know %d ignores whitespace. So if the user hits return without entering an integer, scanf simply skips over it and waits for something else.
If you insist on not ignoring whitespace this way, you should avoid scanf and use other input methods such as fgets. Get input from the user line by line and use sscanf, strtoul and strtok to make sense of it.

having trouble with a "\n" and scanf

Here is the code
printf("\n");
printf("Enter a integer vaule:");
scanf("%d" , &num3);
printf("You entered: %015d", num3);
printf("Enter a float value:");
scanf("%f", &deci3);
printf("You entered: %15.2f", deci3);
printf("\n");
the output is
Enter a integer vaule:4.4
You entered: 000000000000004
Enter a float value:You entered: 0.40
The problem is this code is not stopping at
printf("Enter a float value:");
and this scanf
scanf("%f", &deci3);
seems to be getting its value from the previous scanf
The %d conversion stops wherever the integer stops, which is a decimal point. If you want to discard the input there, do so explicitly… getc in a loop, fgets, or such. This also allows you to validate the input. The program should probably complain about 4.4.
The scanf function works this way per the specification:
An input item shall be defined as the longest sequence of input bytes (up to any specified maximum field width, which may be measured in characters or bytes dependent on the conversion specifier) which is an initial subsequence of a matching sequence. [Emphasis added.]
In your example, the following C string represents the contents of stdin when the first scanf call requests input: "4.4\n".
For this initial call, your format string consists of a single specifier, %d, which represents an integer. That means that the function will read as many bytes as possible from stdin which satisfy the definition of an integer. In your example, that's just 4, leaving stdin to contain ".4\n" (if this is confusing for you, you might want to check out what an integer is).
The second call to scanf does not request any additional input from the user because stdin already contains ".4\n" as shown above. Using the format string %f attempts to read a floating-point number from the current value of stdin. The number it reads is .4 (per the specification, scanf disregards whitespace like \n in most cases).
To fully answer your question, the problem is not that you're misusing scanf, but rather that there's a mismatch between what you're inputting and how you're expecting scanf to behave.
If you want to guarantee that people can't mess up the input like that, I would recommend using strtol and strtod in conjunction with fgets instead.
This works, but it dont complains if you type 4.4 for the int
#include <stdio.h>
int main() {
char buffer[256];
int i;
float f;
printf("enter an integer : ");
fgets(buffer,256,stdin);
sscanf(buffer, "%d", &i);
printf("you entered : %d\n", i);
printf("enter a float : ");
fgets(buffer,256,stdin);
sscanf(buffer, "%f", &f);
printf("you entered : %f\n", f) ;
return 0;
}
use a fflush(stdin) function after the fist scanf(), this will flush the input buffer.

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.

Resources