Weird code interaction when scanning and printing chars in C - 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);
}

Related

Scanf reads numbers wrong in certain formats

I have noticed that this code reads wrong values in certain situations.
#include <stdio.h>
int main()
{
int a, b;
printf("Enter 2 numbers:");
scanf("%2d:%2d", &a, &b);
printf("\n\n %d:%d", a, b);
}
The code should read two 2 digit numbers, it works fine if the input is something like "15:33", however, when the input is "151:33" the output should again be "15:33" but instead, its "15:32764".
What happens here?
You tell scanf() that there will be two digits, a ":" and two digits.
Which in case of the described failure is not true.
Scanf tells you this (in the return value; I am sure) - but you ignore it.
What you tell us, is "there are two digits, then anything, possibly repeatedly, then a ':', then another pair of digits, then possibly more", let me know if I misread your explanations.
You can tell scanf() the same if you read the documentation.
( https://en.cppreference.com/w/c/io/fscanf )
Look out for the ^ specifier. It allows you to define "anything but a ':'". Other features of scanf will allow you to ignore that part. Then you can expect the ":" and then the second pair of digits, like in your shown code.
You might want to expect and ignore another unwanted/ignorable set of input characters at the end, which would be important if you try to do this in a loop.
For example, this basic version gets you output 12:45 for input 123:456 and output ´Oops.` for anything even weirder.
#include <stdio.h>
int main()
{
int a, b;
printf("Enter 2 numbers:");
if(2!=scanf("%2d%*[^:]:%2d", &a, &b))
{
printf("Oops.\n");
} else
{
printf("\n\n %d:%d", a, b);
}
}
E.g. here https://www.onlinegdb.com/online_c_compiler

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.

global and local variable

#include<>
int calc(int,int,char);
void main()
{
int a,b;
char c;
printf("enter 2 nos");
scanf("%d%d",&a,&b);
printf("enter op");
scanf("%s",&c);
printf("the ans is %d\n",calc(a,b,c));
}
int calc(int a,int b,char c)
{
int ans;
switch(c)
{
case'+':ans=a+b;break;
case'-':ans=a-b;break;
}
return ans;
}
why does this program give the output as b...it works when i give a, b and c as global variables...what change should i do if i want them as local variables...using functions
scanf("%s",&c); causes undefined behavior. You are storing at least two characters ['+', '\0'] and you have only allocated space for one.
You might consider scanf(" %c", &c);. Note that I intentionally added a space in the format string to eat any whitespace that the user might include.
char c;
...
scanf("%s",&c);
Is plain wrong, even if c is a global variable.
Your scanf will take input from the keyboard and store the string you type at the address given as second parameter (in your case the address of c). But c has only space for a single character, and your string inputted with scan will take at least 2 characters (the one you type and th terminating zero).
In your case you get undefined behaviour, which means that your program may
appear to work
crash each time you run it
appear to work with a certain string you type, and crash with another
or any other odd behaviour
You need this:
char c[10];
...
scanf("%9s",c);
...
printf("the ans is %d\n",calc(a,b,c[0]));
which lets allows you to input a string of length 9 (9 characters + terminating zero = 10).

query regarding sprintf() and scanf()

Take for example
int i=10,j;
float b=3.14,c;
char str[30];
sprintf(str,"%d%f",i,b);
sscanf(str,"%d%f",&j,&c);
printf("%d ----- %f\n",j,c);
OUTPUT :- 103 ----- 0.1400000
As you can see, initially i=10 and b=3.14.
I want that j=10 and c=3.14 by using sprint() and sscanf().
The problem I am facing is that the compiler assigns j=103 and c=0.140000.
Is there any way to get rid of this problem in sscanf()?
Add one space to sprintf. Change:
sprintf(str,"%d%f",i,b)
to
sprintf(str,"%d %f",i,b)
Aside: It would be also safer to use snprintf here:
snprintf(str, sizeof str, "%d %f", i, b)
The best way will be to separate the numbers, using a different sign, but if you know that the first int is 2 chars long you can specify it:
sscanf(str,"%2d%f",&j,&c);
// ^^
You are missing a space
Change
sprintf(str,"%d%f",i,b);
to
sprintf(str,"%d %f",i,b);
#include <stdio.h>
int main()
{
int i=10,j;
float b=3.14,c;
char str[30];
sprintf(str,"%d %f",i,b);
sscanf(str,"%d%f",&j,&c);
printf("%d ----- %f\n",j,c);
return 0;
}
output
~ > ./a.out
10 ----- 3.140000
The %d conversion specifier in sscanf will match any number of contiguous numeric characters in the buffer pointed to by str till it encounters a non-numeric character which it can't match. This will cause the integral part of the float to be read as part of the int value. Therefore you must have a way to separate where you integer ends and float starts in the string str. You can put any non-numeric character as a sentinel to separate int value from the float value.
int i = 10, j;
float b = 3.14, c;
char str[30];
// a # to separate the two values, can be any non-numeric char so that it
// is not mistaken for a digit in the int or float value
sprintf(str,"%d#%f", i, b);
// match the separator character to read int and then float
sscanf(str, "%d#%f", &j, &c);

how to convert char to int

I'm trying to write a short program were:
#include <stdio.h>
void main()
{
char=a,b,c;
printf("please place 3 numbers:\n");
scanf("%c%c%c", &a,&b,&c);
}
The exercise I'm trying to solve is how to change the char to int so if I write in a the number 3, I will get the number 3 Printed.
at this point I'm only getting the value.
I would appreciate any help.
The answer depends somewhat on what you can assume about the character set. If it's something like ASCII (or really, any character set that includes the digits in sequential order), you just need to offset the character value by the value of the character 0:
int aValue = a - '0';
I'm sure that C# provides better ways to do what you're trying to do, though. For example, see this question for some examples of converting strings to integer values.
First of all your syntax need some checking
You should know that you declare a variable this way (a char in this example):
char a;
If you want to declare multiple variables of the same type in a row you do :
char a, b, c;
If you want to assign a value to a declared variable :
a = '3';
Now to print a char using printf (man printf is a must read, more infos are in coreutils) :
printf("%c", a);
If you want to get the char from the command line, I recommand you to use getchar() (man getchar) instead of scanf because if suits better what you are trying to achieve and doesn't require you to use a syntax in scanf that I am sure you don't fully understand yet.
Your question is incredibly light on details, so here are several options:
#include <stdio.h>
int main()
{
char a,b,c;
printf("please place 3 numbers:\n");
scanf("%c%c%c", &a,&b,&c);
printf("Printing ints (auto-promotion): %d %d %d\n", a, b, c);
printf("Printing ints (explicit-promotion): %d %d %d\n", (int)a, (int)b, (int)c);
printf("Printing digits: %d %d %d\n", a-0x30, b-0x30, c-0x30);
return 0;
}
If the input is 123,
I expect the output to be:
Printing ints (auto-promotion): 49 50 51
Printing ints (explicit-promotion): 49 50 51
Printing digits: 1 2 3
Some things I fixed along the way.
main should return an int, not be void.
char=a,b,c; is a syntax error. You meant char a,b,c;
added a return 0; at the end of main.
You question is not quite understandable. Still I'll try to help. I think that what you want is to store an integer value in the char variable. You can do so by using the following code:
#include<stdio.h>
void main()
{
char a,b,c;
printf("Enter three numbers:\n");
scanf(" %c %c %c",&a,&b,&c); //notice the spaces between %c
}
Or if you want to enter a character and print its ASCII value, you can use the following code:
#include<stdio.h>
#include<conio.h>
void main()
{
char a,b,c;
printf("Enter three characters:\n");
scanf(" %c %c %c",&a,&b,&c);
printf("Entered values: %d %d %d",a,b,c);
getch();
}

Resources