(C) Scanf - input gets 0 every time - c

Each time i set a value in b after a, the value is reset to 0 in a.
In other words, as the code goes, no matter what i input in a it will be always 0 after the second scanf function.
EDIT: I need to use b as char type for the essay, for memory efficiency, so i can't set b to int, but i need to input integer in there.
EDIT2: I need to input an integer in b, example for an input:
1
2
from that point if i
printf("%d",a);
i get 0.
unsigned short a;
char b;
scanf("%hu",&a);
scanf("%d",&b);

You are using the wrong format specifier with
scanf("%d", &b);
It should be
scanf("%c", &b);
However since there is a previous scanf statement there is a newline still in the buffer, and to filter that out you can use
scanf(" %c", &b);
Most format specifiers automatically filter out leading whitespace but %c and %[] and %n do not.
It is unclear from the mistake whether the format specifier is at fault, or the variable type.

%d requires an int:
int b;
Then, you should check the return value of your scanf() calls. Do both calls return 1?
(scanf() returns the number of input items assigned. Because both your calls have one %..., you must return 1 in both cases.)

with char b; and scanf("%d",&b);, scanf will write sizeof (int) bytes to b.
This will corrupt other memory.
scanf("%hhd",&b); will only write one byte to b.

Related

Why in C does taking input using int format to a char change the value of another char variable?

I took input in %d format into a character using scanf() because I didn't want more than 8 bits. But doing so changed the value of another char variable.
Code:
#include <stdio.h>
int main() {
char a;
char b;
printf("Enter a: ");
scanf("%c", &a);
printf("a = %c\n", a);
printf("Enter b: ");
scanf("%d", &b);
printf("\na = %d\n", a);
printf("b = %d\n", b);
}
Output:
Enter a: c
a = c
Enter b: 56
a = 0
b = 56
Screenshot
scanf reads data from stdin and stores them according to the parameter format into the locations pointed by the additional arguments.
scanf("%d", &b);
With %d you are storing an integer into the char variable that can not hold an integer.
the Variable now grows into the other variable in stack above it.
if you compile with the flag "-fstack-protector-all" you should get the
*** stack smashing detected *** error on execution.
The formatting directives in a scanf format string indicate not just how to match the input, but also the type of the corresponding variable in which the resulting value is to be stored. If you pass a pointer to an object of a different type than the corresponding directive expects then you reap undefined behavior.
That's true even for a simple signedness mismatch, but in your case you have a size mismatch. For a %d directive without a size modifier, scanf expects to write the scanned integer value in an object of type [signed] int. If the pointer you pass instead points to a char, and if, as is the case in most implementations, int is larger than char, then it is particularly likely that the resulting undefined behavior manifests in unwanted ways, such as by producing changes in the values of other variables.
If you want to scan a number as a char-sized integer, then you should
Declare the variable as either signed char or unsigned char, not default char, and
Use the correct conversion specifier and size modifier for the chosen data type.
For example,
unsigned char b;
scanf("%hhu", &b);
%u is the format directive for an unsigned integer, and the hh modifier instructs scanf that the destination variable is the size of a char / signed char / unsigned char.
If you want a signed integer then it would be similar, but with the %d formatting directive:
signed char b;
scanf("%hhd", &b);
As a matter of style, do not use default char for numeric data, even if you are confident that the range of values you need to support is a subset of the intersection of the ranges of signed char and unsigned char. Especially so if you plan to use it with formatted I/O functions, because it is implementation-specific whether %hhd or %hhu is the correct directive for a default char.
I agree with the side effect you indicated. This happens when the compiler loads variables in memory one after the other. For example, I examined the change in variable a when a sufficiently large number is typed in variable b. I changed the code as follows.
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
char a, b;
printf( "Address (a): %p\tAddress(b): %p\n", &a, &b);
printf( "Enter the values (a, b): " );
scanf( "%c, %d", &a, &b);
printf( "Value (a): %d\tValue (b): %d\n", a, b);
return EXIT_SUCCESS;
}
Then, when I tested the code, I realized the consequences of this side effect.
The tested code is interpreted in the image below.

Weird code interaction when scanning and printing chars in C

When you declare two variables char a,b; and then you use first 'a' and then 'b',it prints only b, but if you declare it 'b' then 'a', it has no problem printing both in ASCII,the point of the program is to read 121 and 120 and to print yx. the problem - https://prnt.sc/pr5nww
and if you swap them -https://prnt.sc/pr5mt5
#include <stdio.h>
#include <stdlib.h>
int main(){
char a,b;
scanf("%d",&a);
scanf("%d",&b);
printf("%c",a);
printf("%c",b);
}
This is kind of a confusing situation. When it comes to mixing char and int values (as you might do when investigating the numeric values of characters in a character set), it turns out the rules for scanf and printf are almost completely different.
First let's look at the scanf lines:
char a,b;
scanf("%d",&a);
scanf("%d",&b);
This is, in a word, wrong. The %d format in scanf is for scanning int values only. You cannot use %d to input a value of type char. If you want to input a character, the format for that is %c (although it'll input it as a character, not a number).
So you'd need to change this to
char a,b;
scanf("%c",&a);
scanf("%c",&b);
Now you can type characters like A and $ and 3 and have them read into your char variables a and b. (Actually, you're going to have additional problems if you hit the Return key between typing the characters for a and b, but that's a different story.)
When it comes to printing the characters out, you have a little more freedom. Your lines
printf("%c",a);
printf("%c",b);
are fine. And if you wanted to see the integer character-set values associated with the characters, you could have typed
printf("%d",a);
printf("%d",b);
and that would have worked, too. This is because when you call printf (and other functions ike it), there are some automatic conversions that take place: types char and short int are automatically promoted to (passed as) int, and type float is promoted to double. But these automatic conversions happen only for values of those types (as when calling printf). There a=is no such conversion when you're passing pointers to these types, as when calling scanf.
What if you wanted to read numbers, not characters? That is, what if you wanted to input the number 65 and see it get printed as capital A? There are several possible ways to do that.
The first way would be to continue to use %d in your scanf call, but change the type of your variables to int:
int a,b;
scanf("%d",&a);
scanf("%d",&b);
Now you can print a and b out using either %c or %d, and it'll work fine.
You could also use a temporary int variable, before reassigning to char, like this:
char a,b;
int tmp
scanf("%d",&tmp);
a = tmp;
scanf("%d",&tmp);
b = tmp;
The final, lesser-known and somewhat more obscure way, is to use the h modifier. If you say
char a,b;
scanf("%hhd",&a);
scanf("%hhd",&b);
now you're telling scanf, "I want to read decimal digits, but the target variable is a char, not an int."
And, again, you can print a and b out using either %c or %d, and it'll work fine.
the point of the program is to read 121 and 120 and to print yx
Do
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char a, b;
/* Scan into the half of the half of an int (the leading blank
makes scanf() eat whitespaces): */
scanf(" %hhd", &a);
scanf(" %hhd", &b);
/* Print the half of the half of an int: */
printf("%hhd", a);
printf("%hhd", b);
}
To print the characters literally do the printing part like this:
...
printf("%c", a);
printf("%c", b);
}

Improper scanning in C

I want to scan a character immediately after scanning a long type in C.But it fails when I use this code.It scans properly only if I define a separate scanning function for character.Can anyone tell me why it is so?
Code:
#include <stdio.h>
int main()
{
int a;
long b;
char c;
float d;
double e;
scanf("%d%ld%c", &a, &b, &c);
scanf("%f%lf", &d, &e);
printf("%d\n%ld", a, b);
printf("\n%c\n%.3f\n%.9lf", c, d, e);
return 0;
}
Input:
3 12345678912345 a 334.23 14049.30493
Output:
3
12345678912345
0.000
0.000000000
Why is it so?
c Matches a sequence of characters whose length is specified by
the maximum field width (default 1); the next pointer must be a
pointer to char, and there must be enough room for all the char‐
acters (no terminating null byte is added). The usual skip of
leading white space is suppressed. To skip white space first,
use an explicit space in the format.
3 12345678912345 a 334.23 14049.30493
^
The %c in your code matches the first space character following "12345678912345". That leaves the "a" to match with %f. It is not a match so the second scanf() call fails (and returns 0 for no matches).
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.
As pointed out in the comments above, your problem goes away if you add a space to your format string before the %c - it will then skip the whitespace and match on the 'a'. Then the pointer will move past the 'a' and the second scanf will work correctly.
int number_matched;
number_matched = scanf("%d%ld %c", &a, &b, &c)

What is the correct specifier for char, double and float?

#include <stdio.h>
int main()
{
int i;
long int l;
long long int ll;
char a;
float F;
double D;
scanf("%i%li%lli%c%f%lf",&i,&l,&ll,&a,&F,&D);
printf("%i\n%li\n%lli\n%c\n%f\n%lf\n",i,l,ll,a,F,D);
return 0;
}
When I tried to print the value of a,F and D in the above program, it is printing 'h' for 'char' and 0.000000 and 0.000000 for float and double every time .
input: 3
444
12345678912345
a
334.23
14049.30493
output:3
444
12345678912345
0.000000
-0.000000
printf
There's no way to pass a char or a float to printf. They'll be promoted to int and double respectively in the processing of being passed.
When you pass a double, you can use %f or %lf (the latter was added in C99 though, so some older compilers don't support it).
If you want your int printed as a character, you can use the %c conversion. If you want it printed as a number, you can use the %d or %i conversion.
scanf
For scanf you don't want to pass any of the above--you want to pass a pointer to a (char | float | double).
As for the conversion to use, for a pointer to char you can use either %c or %s.
%s reads a "word"--it skips white-space characters, then reads a group of non-white-space characters.
%c does more like "raw" reading--for example, if you specify %15c it reads the next 15 characters, regardless of whether they're white-space or not.
With both %c and %s, you always want to pass a with (like %15s instead of just %s) to assure that the user can't enter too much data and overflow the buffer you've provide. scanf("%s", whatever); is pretty much equivalent to using gets.
With scanf, you pass %f to read a float and %lf to read a double.
Use %c for char .
Note - You should check return of scanf .
Demo
When you read your input, the character you read is the white-space between 12345678912345 and a. That means that the next format, the floating point, will try to read the letter a as a floating pointer value which will not work, and the scanf function will return without being able to correctly read and parse all input, leading to your output not matching the input. Many standard and system function returns a value saying if it succeeded or failed, the same with the scanf function, and if it doesn't fail completely it will return the number of successfully scanned and parsed items, which would be less than expected in your case.
The scanf reference in one of my comments will tell you that most formats skip leading white-space, but "%c" does not. If you want to skip leading space before attempting to parse a character, you need to tell scanf to do that, by inserting an actual space in the format string, like this:
scanf("%i%li%lli %c%f%lf",&i,&l,&ll,&a,&F,&D);
// ^
// Notice space here

Using Scanf after getchar?

I am taking C programming course. I did not understand these codes.
#include <stdio.h>
int main()
{
int c;
int ival;
printf("type : ");
c = getchar();
scanf("%d", &ival);
printf("c = %d\n", c); //65
printf("ival = %d\n", ival); //127
return 0;
}
For example whenever I type Abc, I am getting c = 65; ival = 1.
why ival is 1?
ival is never initialized, so it can have any value. The reason is that, c is receiving 'A' (through getchar()) and then scanf fails to read a number (since the next character in the input, 'b', is not a decimal number), so it never touches ival.
You can check the return value of scanf to see if it fails or succeeds:
if (scanf("%d", &ival) != 1)
printf("you need to enter a number\n");
else
printf("entered: %d\n", ival);
Note that scanf returns the number of items it successfully read and assigned. For example scanf("%d %f %c", ...) would return 3 if all three items were correctly read.1
1Note that assigned means that ignored input (such as those with the assignment-suppresion modifier (*)) doesn't count towards the return value of scanf (C11, 7.21.6.2.10,16). Furthermore, %n doesn't affect the return value of scanf (C11, 7.21.6.2.12).
With Abc, getchar() will read A, thus, c will hold the character code for A, which happens to be 65 on your machine (this is the ascii code for A).
For ival, you can get anything: since %d on scanf() expects to read an integer, and you didn't provide one, scanf() returned prematurely, leaving bc in the input buffer, so the value you read from ival when you call printf() is undefined: it can print anything.
The reason is that your program invokes undefined behavior.A is read by getchar while bc is left unread by scanf because %d expects to read an integer and hence on encountering the character it stop reading immediately and leave ival uninitialized.

Resources