Inputting float into a program that only deals with ints - c

I have a program, but when I input float numbers whenever the program asks for inputs, the program abruptly skips a step and moves onto the end output. The program is below:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a,b,c;
int i;
printf("Please enter a number: ");
scanf("%d", &a);
printf("Please enter a number: ");
scanf("%d", &b);
c = 0;
for(i=0; i < b; i++)
{
c = c + a;
}
printf("%d x %d = %d\n", a, b, c);
return 0;
}
When I input an int for a, and a float for b, the program will output the product as expected if the numbers after the decimal point for b is truncated. However when I input a float for a, the program doesn't take the value for the second number b and instead skips that step and outputs the integer version of a x -858993460 = 0.
For example:
a = int, b = float
Please enter a number: 3
Please enter a number: 5.6
3 x 5 = 15
a = float, b = skipped
Please enter a number 3.9
Please enter a number: 3 x -858993460 = 0
All the flaws in the code are deliberate, but I just wanted to know why it behaves the way I explained above. I know it's because of something to do with trying to input a float into a signed integer but I'm not sure what exactly is causing it to skip the second scanf("%d", &b). Can anyone explain why this happens?
Thanks.

It looks like scanf() is reading your "3" in the second case, and ignoring the "9".
Then when the second scanf() is called, there is already text in the input buffer (the ".9").
I can't tell exactly what it's doing with the ".9". It may have found the dot and just aborted there with b uninitialized. It should be a simple matter to determine what is happening by stepping through with the debugger.
But, basically, not all the input is being processed by the first call to scanf() and so that's what the second call is trying to read. And that's why it's not waiting for you to input any data for the second call.

Console input is line buffered; when you enter 3.9 into a %d format specifier, only the 3 is consumed, the remaining data remains buffered, so the second scanf() call attempts to convert it according to its specifier, it finds a '.' and aborts the conversion leaving b undefined.
scanf() will continue to "fall-through" until the '\n' at the end of the input data is consumed. You can do this thus:
printf("Please enter a number: ");
scanf("%d", &a);
while( getchar() != '\n' ) { /* do nothing */ }
printf("Please enter a number: ");
scanf("%d", &b);
while( getchar() != '\n' ) { /* do nothing */ }
Note that if the format specifier is %c, a modification of the "flush" code is required, because the converted character may already be '\n' :
scanf("%c", &c);
while( c != '\n' && getchar() != '\n' ) { /* do nothing */ }

If the next character that is to be read cannot be converted under the current format as specified by the Format Specifier, scanf stops scanning and storing the current field and it moves to the next input field (if any).
And that particular character is treated as unread and used as the first character of next input field or any subsequent read operation.
In the example given above, it is scanning 3 and then cannot resolve . to the format specifier "%d". Hence it stores 3 in variable a leaving .9 as unread. The control when passes to the next scanf statement, it scans ., but again as it cannot resolve . to format specifier "%d", it skips the input scanning for that field.
Now as variable b was not assigned, it contains some garbage value. And any arithmetic operation with garbage values result into garbage values.

Related

Why my program doesn't allow me to input b?

I want to input valors for a and b, being a an int and b a str. When I run my program I can input a valor, but then it ingnores printf() and gets() for b.
#include<stdio.h>>
int main()
{
int a;
char b[5];
printf("Write a:\n");
scanf("%i", &a);
printf("Write b:\n");
gets(b);
printf("a = %i, b = %s", a, b);
return 0;
}
In the end, it just prints:
a = (valor written), b =
I don't know what's wrong with this, neither if it's a different way to get this working. I'm pretty new with C. Thank you in advance. ;)
The function gets is unsafe and is not supported by the C Standard. Instead use either scanf or fgets.
As for your problem then after this call of scanf
scanf("%i", &a);
the input buffer contains the new line character '\n' that corresponds to the pressed key Enter. And the following call of gets reads an empty string by encountering the new line character.
Instead of using gets write
scanf( " %4[^\n]", b );
Pay attention to the leading space in the format string. It allows to skip white space characters as for example the new line character '\n'. And the call of scanf can read a string with maximum length equal to 4. If you want to read a larger string then enlarge the array b and the field width specifier in the format string.

why the below code is taking two input on single execution of scanf funcion

#include<stdio.h>
#include<conio.h>
int main()
{
int Dividend,divisor;
printf("Checking Divisiblity of 1st number with 2nd number \n\n") ;
printf("Enter Number \n") ;
scanf("%d",&Dividend);
printf("Enter Divisor = ");
scanf("%d",&divisor) ;
if(Dividend % divisor == 0)
{
printf("Number %d is divisible by %d",Dividend,divisor) ;
}
else
{
printf("Number %d is not divisible by %d",Dividend,divisor) ;
}
getch();
return 0;
}
Above is my code that i have written in C ;
on running this program . Only on first execution of scanf function if i give two input space seperated , the second input is going on right variable . and on hitting enter i am getting result . I am not understanding how is this happing .
When space is pressed, scanf doesn't see anything yet. Something happens only after enter is pressed. It then takes everything to the left of the space character and assigns it to the first variable, and everything to the right of the space character and assigns it to the second variable.
If you don't press the spacebar, scanf will interpret everything you type as a single number and will assign it to the first variable.
Instead what you may want to do is use the %c format specifier to read a single character at a time. You can then check if the character is a space character and if it is, you can break out of the loop. Otherwise, you can keep reading characters until you reach a space character.
stdin is line based by default. Your program gets nothing until you press enter. Then your program has the entire line of text available.
Result of this is, that scanf, getchar, fgets, etc calls will not return until you press enter. After enter press, entire line is available and the function starts to process it.
scanf is kinda special, that if you have int parsed_count = scanf("%d%d", &a, &b);, it will read two integers, no matter how many times you press enter, so you can either do
1 2<enter>
Or you can do
<enter>
1<enter>
<enter>
2<enter>
and scanf will still read these two integers (it returns early if there is parse error, which is why you need to check the return value!).
And vice versa, if there is already input available, then scanf may return immediately, so if you have this code
scanf("%d",&Dividend);
printf("Enter Divisor = ");
scanf("%d",&divisor) ;
and enter text
1 2<enter>
Then first scanf will wait for enter press, then consume the first integer, leaving 2<enter> still unread. Then there's print, and then 2nd scanf starts reading, skipping the whitespace and immediately getting 2nd integer. So you see
1 2 <- this is your typing echoed, not print from your program
Enter Divisor = <- printf printed this
If you want to take only one input per enter press, you can simply read characters until newline, because scanf leaves them there. Example loop to read until newline, or exit program at end of file/error:
while(true) {
int ch = getchar();
if (ch == EOF) exit(1);
if (ch == '\n') break;
}

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.

Why doesn't scanf() wait for the next input if I previously entered a certain input

below is my simple code to enter a number and print it. it is inside a while(1) loop so i need to "Enter the number infinite number of time- each time it will print the number and again wait for the input".
#include<stdio.h>
int main()
{
int i;
while(1){
printf("\nenter i \n");
scanf("%d", &i);
if(i==1)
{
printf("%d \n", i);
}
}
return 0;
}
it was working fine. but suddenly i noticed that IF i ENTER a character(eg: "w") instead of number , from there it won't ask for input!!!**
it continuesly prints,
enter i
1
enter i
1
......
when i debug using GDB, i noticed that after i enter "w", that value of character "w" is not stored in &i . before i enter "w" it had 0x00000001 so that "1" is printed through out the process.
Why it doesn't ask for another input? According to my knowledge, when I enter "w" the ascii value of "w" should be stored in &i. But it doesn't happen.
If I put, "int i; " inside while loop it works fine! Why?
Please test my code in following way:
Copy and paste and run it
When "enter i" prompt will come enter 1
Second time enter "w". See what happens...
scanf with %d format specifier will read everything that "looks like a number", i.e. what satisfies the strictly defined format for a decimal representation of an integer: some optional whitespace followed by an optional sign followed by a sequence of digits. Once it encounters a character that cannot possibly be a part of a decimal representation, scanf stops reading and leaves the rest of the input data in the input stream untouched (to wait for the next scanf). If you enter just w, your scanf will find nothing that "looks like a number". It will read nothing. Instead it will report failure through its return value. Meanwhile your w will remain in the input stream, unread. The next time you try your scanf, exactly the same thing will happen again. And again, and again, and again... That w will sit in the input stream forever, causing each of your scanf calls to fail immediately and your loop to run forever (unless your uninitialized variable i by pure chance happens to start its life with the value of 1 in it).
Your assumption that entering w should make scanf to read ASCII code of w is completely incorrect. This sounds close to what %c format specifier would do, but this is not even close to what %d format specifier does. %d does not read arbitrary characters as ASCII codes.
Note also that every time you attempt to call that scanf with w sitting in the input stream, your scanf fails and leaves the value of i unchanged. If you declare your i inside the loop, the value of i will remain uninitialized and unpredictable after each unsuccessful scanf attempt. In that case the behavior of your program is undefined. It might even produce an illusion of "working fine" (whatever you might understand under that in this case).
You need to check the return value of scanf as well, as it will return the number of successfully scanned and parsed values. If it returns zero (or EOF) then you should exit the loop.
What happens when you enter e.g. the character 'w' instead of a number is that the scanf function will fail with the scanning and parsing, and return zero. But the input will not be removed from the input buffer (because it was not read), so in the next loop scanf will again read the non-numeric input and fail, and it will do this infinitely.
You can try this workaround:
int main()
{
int i;
char c;
while (1)
{
printf("enter i: ");
if (scanf("%d",&i) == 0)
scanf("%c",&c); // catch an erroneous input
else
printf("%d\n",i);
}
return 0;
}
BTW, when were you planning to break out of that (currently infinite) loop?
You need to read up on scanf(), since you seem to be basing your program around some assumptions which are wrong.
It won't parse the character since the conversion format specifier %d means "decimal integer".
Also, note that you must check the return value since I/O can fail. When you enter something which doesn't match the conversion specifier, scanf() fails to parse it.
You would probably be better of reading whole lines using fgets(), then using e.g. sscanf() to parse the line. It's much easier to get robust input-reading that way.
scanf return type can be checked and based on that inputs can be consumed using getchar to solve your problem.
Example code
int main()
{
int i;
int ch;
while(1){
printf("\nenter i \n");
if ( scanf("%d", &i) !=1 )
{
/*consume the non-numeric characters*/
for (; (ch = getchar()) != EOF && ch != '\n'; ) { }
}
if(i==1)
{
printf("%d \n", i);
}
}
return 0;
}
Description:
When scanf("%d", &i) encounters the character, it will not read it. The character will still remains in the input stream. So to consume those characters, getchar() can used. Then scanf will wait for the next input in further iteration.

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.

Resources