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);
Related
I am starting out in C and I need to write a program that outputs the ASCII character for a given integer.
This is what I have:
#include <stdio.h>
int main(void)
{
char ch;
printf("Enter an ASCII code: ");
scanf_s("%d", &ch);
printf("The character for %d is %c\n", ch, ch);
}
I am getting a run-time error saying that the variable is corrupted, however, the window pops up allowing me to input an integer, and the program gives the correct output.
How do I fix this run-time error?
The %d format specifier expects an int * as a parameter, but you're passing in a char *. Because a char is smaller than an int, the function will attempt to write more bytes than the variable can hold. This invokes undefined behavior which in your case causes a crash.
Either change the type of ch to int, or use the %hhd format specifier which expects a char *.
ch is a variable of type char, but you're trying to read into it using %d, which is the format specifier for an int. That means your scanf writes over extra memory that it shouldn't. Change your declaration of ch to:
int ch;
And your program should work fine.
This question already has answers here:
What is the difference between %*c%c and %c as a format specifier to scanf?
(3 answers)
Closed 7 years ago.
So I stumbled across this code and I haven't been able to figure out what the purpose of it is, or how it works:
int word_count;
scanf("%d%*c", &word_count);
My first thought was that %*d was referencing a char pointer or disallowing word_count from taking char variables.
Can someone please shed some light on this?
*c means, that a char will be read but won't be assigned, for example for the input "30a" it will assign 30 to word_count, but 'a' will be ignored.
The * in "%*c" stands for assignment-suppressing character *: If this option is present, the function does not assign the result of the conversion to any receiving argument.1 So the character will be read but not assigned to any variable.
Footnotes:
1. fscanf
To quote the C11 standard, chapter §7.21.6.2, fscanf()
[...] Each conversion specification is introduced by the character %.
After the %, the following appear in sequence:
— An optional assignment-suppressing character *.
— [...]
— A conversion specifier character
and regarding the behavior,
[..] 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. [...]
That means, in case of a format specifier like "%*c", a char will be read from the stdin but the scanned value won't get stored or assigned to anything. So, you don't need to supply a corresponding parameter.
So, in this case,
scanf("%d%*c", &word_count);
is a perfectly valid statement.
For example, What it does in a *nix environment is to clear the input buffer from the newline which is stored due to pressing ENTER key after the input.
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.
I intend to modify each other letter of a particular string. But for the purposes of this program none of that occurs. So far I've grabbed a string from the user and stored it in userinput and intend to print it.
#include <stdio.h>
#include <string.h>
int main(void) {
char userinput[256] ="";
printf("Enter somthing to change:\n");
scanf("%s", &userinput);
printf("%s\n", userinput);
int k = 2; // This is just here to do something every time k is even
int j = strlen(userinput);
for (int i = 0; i < j; i++) {
if(k % 2 == 0) {
printf("%s", userinput[i]);
k++;
}
else {
printf("%s", userinput[i]);
k++;
}
}
}
The strlen() function however does not work on the userinput. I figure this is because strlen() is supposed to take the address of the first char of a string and then iterate until reaching a null char but scanf doesn't actually create a null char.
I couldn't figure out a way of adding the '\0' after the string without first knowing the length of the string.
How would I go about accessing the length of a stored character sequence if it's stored in an array?
This:
scanf("%s", &userinput);
should be:
scanf("%s", userinput);
The address of operator & is unrequired, and incorrect. Arrays decay to the address of their first element when passed to a function. scanf("%s") will append a null terminating character so it is unnecessary to explicitly insert one.
To prevent potential buffer overrun specify the maximum number of characters that scanf() should write to userinput. This should be one less than the size of userinput, leaving room for the terminating null character:
scanf("%255s", userinput);
The incorrect format specifier (which is undefined behaviour) is being used to print the characters of userinput: use %c not %s. This:
printf("%s", userinput[i]);
must be:
printf("%c", userinput[i]);
Change
scanf("%s", &userinput);
to
scanf("%s", userinput);
The & operator is not required in the case of String capture. The scanf() automatically appends the null character('\0') to the end of the string so int j = strlen(userinput); should work.
If you still want to calculate the length without this function efficiently here is the link How to calculate the length of a string in C efficiently?
Change this
scanf("%s", &userinput);
with
scanf("%s", userinput);
we have to use addresses for scanf:
If we will scan into an int a then we have to call scanf() with the address of a => &a
If we will scan into a double a then we have to call scanf() with the address of a => &a
But If we will scan data into with pointer (memory address) int *a; or char array char a[50]; then we have to call scanf() with the pointer or with the array without adding &
From the scanf() page
Depending on the format string, the function may expect a sequence of
additional arguments, each containing a pointer to allocated storage
where the interpretation of the extracted characters is stored with
the appropriate type. There should be at least as many of these
arguments as the number of values stored by the format specifiers.
Additional arguments are ignored by the function. These arguments are
expected to be pointers: to store the result of a scanf operation on a
regular variable, its name should be preceded by the reference
operator (&) (see example).
You're confused about types, as others have indicated. Using scanf and printf when you're confused about types is dangerous!
scanf("%s", &userinput);
The type of &userinput is char (*)[256], but scanf expects %s to correspond to a char *. Since the type expected and the type given differ and aren't required to have the same representation, the behaviour is undefined.
I figure this is because strlen is supposed to take the address of the
first char of a string and then iterate until reaching a null char but
scanf doesn't actually create a null char.
Wrong. scanf certainly does assign a null character, when you use the %s format specifier. That is, providing scanf doesn't encounter an error or EOF. On that note, you should probably check for errors from scanf:
if (scanf("%s", userinput) != 1) {
/* Insert error handling here */
}
... as you should with all standard library functions in C.
k is pointless. Your loop already increments i at the same frequency as k.
strlen returns a size_t. Make sure you store return values in the right types. If a function returns size_t, then you store the return value in size_t. If a function returns int, then you store the return value in an int. Got it? Whatever the return type is, is whatever type you use to store the return type. Use the manual to find that out.
printf("%s", userinput[i]);
There's that type confusion again. userinput[i] is a char. %s tells printf to expect a char *. When the argument is invalid, the behaviour is undefined. That may cause your program to malfunction. Consider printf("%c", userinput[i]); or printf("%s", &userinput[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.