What happens if C tries to scan character in integer variable [duplicate] - c

This question already has answers here:
Why does scanf fail with floats?
(3 answers)
Closed 8 years ago.
So I was wondering what happens if the user enters characters in integer variables for example:
main()
{
int number;
printf("Print a number:");
scanf(" %d", &number);
printf("The result is:%d", number);
return 0;
}
I typed in characters and the result is: 1986895412
is this 1986895412 a place in the ram ??

In this case, scanf directive just fails. Quoting this answer (which essentially rephrases the spec's definition):
The %d conversion specifier expects the input text to be formatted as
a decimal integer. If it isn't, the conversion fails and the character
that caused the conversion to fail is left in the input stream.
So, number remains with the same value it had before the directive. As you didn't initialize it with some defined value (like int number = 0), it'll be just some random garbage value. In your case that happened to be equal to 1986895412.

Check the return of scanf(). When you type in characters, the correspond result will occur.
if (1 == scanf("%d", &number)) {
printf("The result is:%d", number);
}
else {
printf("Invalid data entered. `number` not changed\n");
}
Note: Code's int number; is not initialized, so its value could be any int. With invalid input, number was not changed and code printed the uninitialized number which just happeded to have the value of "1986895412". It may differ tomorrow.
Note: leading space in " %d" is not needed as %d itself consume leading whitespace.

As number had not been initialized and scanf() failed the printf() provokes undefined behaviour reading the uninitialised variable number. Anything could happen.
So there are two lessons to learn here:
Initialise variables when they are defined. (If you do not know to what to initialise them you most probably do not need them, at least not where you are trying to define them)
Perform error checking on calls which would return garbage if failed.

Related

Reading ASCII character causes an infinite loop

If you enter integer value the loop works just fine but if you enter some ASCII character or float type value the program goes into an infinite loop. Any fix for this issue?
Technically, char is one type of int so this shouldn't be a problem.
#include <stdio.h>
int main(void)
{
int num;
scanf("%d",&num);
while (num < 40)
{
printf("Number is small\n");
scanf("%d",&num);
}
return 0;
}
The function scanf will try to read a decimal integer from stdin. It uses the definition of a decimal integer from strtol:
The valid integer value consists of the following parts:
(optional) plus or minus sign
(optional) prefix (0) indicating octal base (applies only when the base is 8 or ​0​)
(optional) prefix (0x or 0X) indicating hexadecimal base (applies only when the base is 16 or ​0​)
a sequence of digits
In other words, scanf will try to interpret a sequence of characters on stdin as a decimal integer. It will not do a character to integer conversion based on the ASCII table.
The solution to your problem lies in checking the return value of scanf, which is:
Number of receiving arguments successfully assigned (which may be zero in case a matching failure occurred before the first receiving argument was assigned), or EOF if input failure occurs before the first receiving argument was assigned.
So, check if scanf did not return 1. In this case, it has not read a decimal integer and num has not been assigned a value and should not be used.
In the given program, if num has never been assigned a value, its value is indeterminate. This could be a value <40, explaining the infinite loop as scanf repeatedly tries to read a non-integer from stdin, fails and leaves the non-integer on stdin as is. If num has been assigned a value before, it will still hold that value after a failed scanf call.

Very basic scanf programs not working in c, not understanding why [duplicate]

This question already has answers here:
Why does division result in zero instead of a decimal?
(5 answers)
Division result is always zero [duplicate]
(4 answers)
How to print using scanf() function in C programming? [closed]
(2 answers)
Closed 2 years ago.
I'm new to c and im trying to learn how to use the scanf function to pass in data and then the printf function to show me the printed results.
This seems like it should be eas,y but my expected outputs do not match what gets returned. My IDE is vscode
#include <stdio.h>
#define pi 3.14159
int main()
{
float size;
float radius;
scanf("this is the value : %f",&radius);
size = (2/3)*pi*(radius*radius*radius);
printf("%f",size);
return 0;
}
here you can see what i inpute and what gets printed
After that I went to make an easier program to understand the concept and I'm getting a similar but different issue. instead of returning 0 every time now it prints the same constant
#include <stdio.h>
int main()
{
int a;
scanf("This is the value %d", &a);
printf("Input value read : a = %d", a);
return 0;
}
Here you can see the output i get for the second program
Any ideas for whats going wrong and how i could fix it?
You seem to expect scanf to print a message and then to acquire a value:
scanf("this is the value : %f",&radius);
No. This obtained just by printing the message and then aquiring the value with scanf:
printf("Please insert the value :\n");
if (scanf ("%f",&radius) == 1)
{
/* ... */
}
Please note the check on scanf return value, that is the number of variables succesfully aquired. In this case we expect it to be 1, as the only format specifier is %f.
That message before %f made scanf actually expect exactly that string (whitespaces included) before the float number. Inserting just the input number (5, in your example) made scanf discard the input as it wasn't matching the given string, and no value was stored, so that radius remained uninitialized and the execution resulted in undefined behavior. Additionally, that leading 2/3 is calculated with integer arithmetics and the result is 0; use 2.0/3.0 to force the use of float arithmetics.
The issue with the test involving %d is quite similar; you just see the random uninitialized value of a that is not written by scanf for the reasons explained above.

While loop never stops when I enter a character in a place [duplicate]

This question already has answers here:
Why is scanf() causing infinite loop in this code?
(16 answers)
Closed 5 years ago.
I have a problem with this loop when I enter a character for ˋscanfˋ. The loop will never stop. But when I enter a number all works good.
This Is The Code:
#include <stdio.h>
#include <stdlib.h>
int main() {
int x;
printf("Enter 1 Or 2\n");
scanf("%i",&x);
while (x!=1 && x!=2) {
printf("Please Enter A Right Value \n");
scanf("%i",&x);
}
printf("Finish");
}
Well when you input character, scanf actually tries to get those wrong character inputs from the stdin but as it is not as per the conversion specification provided it fails. And then it keeps those wrong input in the stdin. And next time the scanf fails again due to those wrong inputs. So you need to clear it before you attempt to get the input again using scanf. Also check the return value of scanf and in case it failed clear the stdin.
The provided code checks for EOF and also return value of scanf the standard says explicitly about the return value of scanf :-
7.21.6.2p16
The fscanf function returns the value of the macro EOF if an
input failure occurs before the first conversion (if any) has
completed. Otherwise, the function returns the number of input
items assigned, which can be fewer than provided for, or even
zero, in the event of an early matching failure.
The code will be something like this. (This is using scanf).
Better even use fgets. you can easily and more better way control the erro neous inputs. With fgets you will read the entire line and then parse the integer input from it using strtol or strtoul. Yes in case of integer input there will be a case there also - you need to check if the parsed long or unsigned long is of proper size so that they can be kept in int variable.

why my c program doesn't crash when i entered the wrong data type

I'm new to c and I'm writing a basic program that ask the user for input
#include <stdio.h>
int main(void){
float weight;
printf("enter your weight in kg:\n");
fflush(stdout);
scanf("%f", &weight);
printf("your weight is %f kg\n", weight);
return 0;
}
Everything works as expected when I under a number when asked for input. But when I accidentally entered words, the program doesn't crash and instead print out your weight is 0.00000 kg.
I was just wondering, why doesn't my program crash when it expect numbers but I have entered words? and why did it printed out 0.00000?
why my c program doesn't crash when i entered the wrong data type
When a user of your program enters some input that can't be converted by scanf to a float, the variable weight will not be initialized. So when the program prints the variable, it will read an uninitialized float. According to the c standard, that has undefined behavior.
However, undefined behavior does not guarantee a program crash. It may crash or it may continue execution. We can't know as it is undefined what will happen. On your system execution just continued but on another system a program may happen.
On many systems the memory allocated to a program as startup is initialized to all zeros. Therefore variables in main is (often) an all zero binary pattern when left uninitialized. For floats that translate to the value 0.0
So even if you don't initialize weight it seems as if it was initialized to zero and your program runs fine even with input like abc and prints the weight as 0.0
However, from a standard point of view it is still undefined behavior to read an uninitialized float variable
If you did the same inside a function that you called a number of times (with other function calls in between), you would see strange behavior sooner or later.
Typically just a print of strange values but on some systems, you might see a crash (but that is more rare).
You should do:
if (scanf("%f", &weight) == 1)
printf("your weight is %f kg\n", weight);
else
printf("Illegal input\n");
Every input the user gives in C is treated as a string, though the input you provide is in numbers. After getting the input from the user, it is converted in to numeric data using atoi (ascii to integer) function (man atoi). The return value of this function is the converted value. Upon successfully converting the given string to an integer it returns the converted integer value and it returns zero when the resultant value is a non-integer. This is the reason why it is not showing any error when you input different data.
Try the same code with different format specifiers, so that you can have a clear understanding.
The MAN page of scanf :
Return Value
These functions return the number of input items successfully matched
and assigned, which can be fewer than provided for, or even zero in
the event of an early matching failure.
So, scanf return the number of arguments successfully scanned. that's why your program not crashing.
the program does not crash because the input does nothing to cause a crash.
However, the posted code does have a major flaw. This line:
scanf("%f", &weight);
should be:
if( 1 != scanf("%f", &weight) )
{
perror( "scanf failed" );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
In other words, always check system functions for errors, especially those that are performing input.

C - error: ignoring return value of scanf?

I'm only a few days into C programming, so I am not quite sure what's wrong with this code:
#include <stdio.h>
int main(int argc, char * argv[]) {
int sides;
printf("Please enter length of three sides :\n");
scanf("%d", &sides);
return 0;
}
The error message I receive is as follows:
ignoring return value of scanf
What am I doing wrong here, and what can I do to fix it?
You might code
if (scanf("%d", &sides) >0) {
printf("you want %d sides.\n", sides);
}
else printf("You did not enter any number.\n");
The scanf function (please follow the link) has several roles
it is expecting some input and could modify the variables you passed by address to it
it is returning the number of successfully input items
It's a warning that stops your compiler from performing it's task (too strict settings). Check the return value of the scanf() function for errors and the warning should disappear.
Return Value
On success, the function returns the number of items
successfully read. This count can match the expected number of
readings or fewer, even zero, if a matching failure happens. In the
case of an input failure before any data could be successfully read,
EOF is returned.
scanf returns the number of "items", i.e. values passed both in the format string (a single item is e.g. %d, %c and so on), and in the subsequent arguments to scanf, for example, to read two integers separated by comma and space, you would use:
int x, y;
int items = scanf("%d, %d", &x, &y);
assert(items == 2);
I've already spoiled what my suggestion will be above - instead of adding unused variables, if you just want to read it, add an assertion:
#include <assert.h>
/* ... */
assert(scanf("%d", &sides) > 0);
/* ... */
Unfortunately, assert(scanf("%d", &sides)); is not enough, because of EOF (this will return -1). It would be really elegant.
I think this is the way to go, if you don't want to continue your program with an uninitialized variable (sides) in this case.
Alternatively, you can capture scanf's result to a variable, and handle it gracefully like in the other answers.
You don't capture the return value of scanf in a variable. It's a count (as an integer) of how many characters were read, so if that's important to you, then it may be good to capture it.

Resources