What does "for each value converted" mean in the following sentence?
Q: Why doesn't the call scanf("%d", i) work?
A: The arguments you pass to scanf must always be pointers: for each
value converted, scanf "returns" it by filling in one of the
locations you've passed pointers to. (See also question 20.1.) To fix
the fragment above, change it to scanf("%d", &i) .
I have found this in the c-faq; it's question 12.12.
If you execute scanf("%d", &i) with input 123, the character sequence 123 is converted to an int value, which is stored in i.
This is not a type conversion as might be specified by a cast, but it's still reasonable to refer to it as a "conversion".
scanf() can scan for more than one value in a single call. e.g.:
int numConverted = scanf("%d %f %d", &myInt1, &myFloat, &myInt2);
Note: you should always inspect the return value to find out how many have actually been converted, though.
Related
This code here gives incorrect value of int num if my input for num is for example 11,the printf function will output 0. However if I add static to int num the output produced by printf is correct. Can someone please explain the reason.Also if I make the format specifier for second scanf as %c , then also int value is printed correctly.
#include<stdio.h>
int main()
{
int num;//making it static gives correct result
char ch;int c;
printf("enter the value of num and ch:\n");
scanf("%d",&num);
scanf("%d",&ch);
printf("num = %d and ch = %c",num,ch);
return 0;
}
It's not specifically with printf(), the issue is caused by the erroenous call to scanf().
Quoting C11, chapter §7.21.6.2
[...] Unless assignment suppression was indicated by a *, the
result of the conversion is placed in the object pointed to by the first argument following
the format argument that has not already received a conversion result. If this object
does not have an appropriate type, or if the result of the conversion cannot be represented
in the object, the behavior is undefined.
For %d conversion specifier, the expected type of argument is
d [....] The corresponding argument shall be a pointer to
signed integer.
But, all you're supplying is a pointer to a char. Mismatch. Undefined behavior.
OTOH, for %c conversion specifier,
c Matches a sequence of characters of exactly the number specified by the field
width (1 if no field width is present in the directive).
If no l length modifier is present, the corresponding argument shall be a
pointer to the initial element of a character array large enough to accept the
sequence. No null character is added.
so using
scanf("%c",&ch);
is correct. Alternatively, you can also use
scanf("%hhd",&ch); //char is signed
scanf("%hhu",&ch); //char is unsigned
This
char ch;
scanf("%d", &ch);
will invoke Undefined Behavior, since you are using the format for an integer, to store it in a character.
What you observe is very likely because second scanf with the wrong (tool large for char) format specifier overwrites the automatic variables memory where num is located.
Making num static moves it to the global variables memory and it (kind of) works, but it's still undefined behaviour, some memory have been overwritten somewhere and you may pay the price later on. So the only option is to specify the correct format specifier, here %c as you noted.
Try to add \n, like scanf("%d\n", &num);. Maybe it could help.
And compiler cannot pass if you use that expression, like scanf("%d", &ch);
Apologizes I am very inexperienced with C. I have the following code:
char * a[BUF_SIZE];
scanf("%d", numberOf);
do {
a[i] = (char *)malloc(MAX_LINE_LEN + 1);
scanf("%s", a[i]);
++i;
} while(i < numberOf);
The idea is simple, read two inputs from stdin using scanf, the first being a single int, followed by some array of strings. Scanf works independently in both cases e.g. scanf("%d", numberOf) will store a digit and scanf("%s", a[i]) will store a set of strings into the array. However in conjunction reading an integer first into numberOf causes a segfault when reading in a set of strings. My question is why? I know its generally bad practice to use scanf, but I fail to see how reading in multiple inputs from stdin can cause a segfault in the resulting code. Much Thanks!
From the code, it looks like numberOf is an int. When using scanf, you want to pass it a pointer, so change scanf("%d", numberOf); to scanf("%d", &numberOf);
What scanf does is take the user input and put it into the memory address specified by the second parameter. When you provide an int as the second parameter, scanf tries to put user input into a memory address (specified by the int) that it may not own, causing the seg-fault.
You are missing & operator in scanf("%d", numberOf); put it as &numberOf
In the below code when I entered 'a' value as 3.4(i.e. float) it is giving me answer garbage value without even allowing me to enter the 'b' value and when I given 'a' value as 3 and 'b' value as 2.3(i.e. float) it is accepted and giving me answer 5 not a garbage.
My question is why type checking was not happening on second parameter ;why only on first parameter?
more clearly if I give 3,3.5 code is working but why cant i give input as 3.5,3 ?
int sum(int k,int l)
{
int s= k+l;
return s;
}
void main()
{
int a,b,k;
printf("enter the numbers");
scanf("%d",&a);
scanf("%d",&b);
k= sum(a,b);
printf("the value of sum is %d", k);
}
PS: I saw this question on quora. I was not happy with the answers provided there. I thought SO is the best place to ask this question.
Type checking is not the issue in your program. Type checking happens at compilation time; the behavior you're seeing occurs at run time. There is an issue with compile-time type checking for printf, scanf, and similar functions, which I discuss below, but that doesn't apply to your program, which does pass arguments of the correct type to both scanf and printf. Nevertheless, I'll discuss that issue below (because I wrote about it before I read your question closely enough).
You call scanf twice to (attempt to) read two int values. The input is 3.4, which would be valid input for a float or double. So what does scanf do with this?
scanf with a "%d" format reads input formatted like an optionally signed integer literal, stopping when it sees anything that doesn't match that format. So the first scanf reads just the 3 and stops at the .. It doesn't consider that the . might be a decimal point because you didn't ask it to read a floating-point value. The . isn't an error, it's just the end of the input that scanf("%d", ...) is looking for.
The second scanf attempts to read another int value, but now the first character in the input stream is the ., which cannot be part of a valid integer literal, so it fails. (Examining the return value of scanf would tell you this; it returns the number of items successfully scanned.)
You should always check the results returned by input functions and write code to handle failure (even if you handle it just by aborting the program with an error message).
A safer way to read numeric input is to read an entire line at a time using fgets(), and then parse the line in memory using sscanf. That can have problems too, but it won't leave invalid input characters waiting to be read by later calls (unless you have a very long input line). Read the documentation of fgets and sscanf for more information -- and again, always check the results they return so you can detect input errors.
Both printf and scanf are variadic functions, meaning that they can accept a variable number and types of arguments.
The declaration of printf, for example, is:
int printf(const char *format, ...);
This means that the first argument in a call to printf is checked against the parameter type, but the zero or more following arguments are not checked at compile time. This gives you tremendous flexibility, but at the cost of compile=time checking. It's almost entirely up to you to ensure that all the following arguments are of the types specified by the format string. If you pass an argument of the wrong type (e.g., printf("%d\n", 1.5)), you won't necessarily get an error message; instead, the behavior is undefined.
scanf is similar, but with different semantics for the format string (most arguments are pointers rather than values to be printed).
Some compilers (gcc in particular) will do additional checking for you if the format string is a string literal, but this is not required and other compilers might not do this.
Incidentally, the code you posted is missing the required
#include <stdio.h>
and void main() should be int main(void). If you're using a book or tutorial that suggests using void main(), it was probably written by someone who doesn't know the C language very well. Find a better one.
When scanf encounters a double for variable 'a' as you noted 3.4. It reads 3 as the integer and stops at the decimal. the .4 will then be read as a double on the next call. It works when the second input is a float because it drops the decimal and is not called again thus ignoring the remaining decimals.
As noted in the comments, read about scanf and make some changes to the code.
I think you should add "getchar()" after scanf method,when you press enter,the '/n' will give
next parameter.
it's just my point.
void main()
{
int a,b,k;
printf("enter the numbers");
scanf("%d",&a);
getchar();/* the /n is last in stdin*/
scanf("%d",&b);
k= sum(a,b);
printf("the value of sum is %d", k);
}
What is wrong with the following code written in c language?
I encountered a segmentation fault. what is it?
int a[2];
for(i=0;i<2;i++)
{
scanf("%d",a[i]);
printf("%d",a[i]);
}
Why couldn't it run? leave about declarations. Does scanf have any delay problems?
This:
scanf("%d",a[i]);
is wrong. The %d format specifier requires a pointer to where the value should be stored after conversion, i.e. it should be:
scanf("%d", &a[i]);
This is required since otherwise you pass the value of a[i] to scanf(), giving it no way to change the value. By passing the address of the value, scanf() can simply write to the provided memory address to change the value that is stored there. With printf(), you don't want your values to be changing, so passing them directly to printf() is fine.
Also, conversions (like many other forms of I/O) can fail, so you should check the return value before relying on the conversion having succeeded:
if( scanf("%d", &a[i]) == 1 )
printf("%d\n", a[i]);
You should probably read the manual page for scanf() a couple more times. :)
Pass the address of a[i] to scanf instead of the value of a[i].
scanf("%d",&a[i]);
I created a very simple progam whith a menu,
that take a value, then memorize it into the
local variable value, and finally with the
second option the progam prints the value.
my question is:
Why does the program work only if I add an "h"
to the scanf parameter?
In other words: what kind of relation there is
between scanf() and my local int value variable?
thanks!
p.S. (I used Dev-C++ (GCC) to compile it.
With Visual Studio it works)
#include <stdio.h>
main () {
int value = 0;
short choice = 0;
do {
printf("\nYour Choice ---> ");
scanf("%d", &choice); /* replace with "%hd" and it works */
switch (choice) {
case 1:
printf("\nEnter a volue to store ");
scanf("%d", &value);
getchar();
printf("\nValue: %d", value);
break;
case 2:
printf("\nValue: %d", value);
break;
}
} while (choice < 3);
getchar();
}
With scanf, the "h" modifier indicates that it's reading a short integer, which your variable choice just happens to be. So the "%hd" is necessary to write only two bytes (on most machines) instead of the 4 bytes that "%d" writes.
For more info, see this reference page on scanf
The variable choice is of type short so that's why you need the %h specifier in scanf to read into it (in fact you don't need the d here). The int type just requires %d. See the notes on conversions here
You're reading into a short. The h is necessary because %d is the size of an int by default. See this reference page on scanf.
It looks like your problem is that choice is a short, which is (generally) 2 bytes long, while %d expects an integer, which is (generally) 4 bytes long… So the scanf clobbers whatever comes after choice on the stack.
choice is a short and %d specifies an int.
When you specify %d, scanf has to assume that the associated argument is a pointer to an int sized block of memory, and will write an int to it. When that happens it will likely be writing to data adjacent to but not part of choice and the results are undefined and probably not good! If it works in one compiler and not another that is simply the nature of undefined behaviour!
In GCC -Wformat should give you a warning when you make this error.
From the comp.lang.c FAQ:
Why doesn't the code short int s; scanf("%d", &s); work?
Someone told me it was wrong to use %lf with printf. How can printf use %f for type double, if scanf requires %lf?
%d is for reading an int, not a short. Your code never really "worked" -- it just appears that in this case you didn't notice any difference between what you wanted and the undefined behavior you got.
The modifier for scanf to input a variable of type short is %hd. Hence you need to specify the correct modifier.
scanf("%d",&integer); // For integer type
scanf("%hd",&short_int); // For short type
Hence it doesnt work.
Depending upon numeric padding, endian-ness, and other such issues, you may be storing either the upper or lower part of the input value into choice; you are storing the rest of the input value into memory that may or may not be being used for anything else.