Scanf reads numbers wrong in certain formats - c

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

Related

Using scanf to read an integer with nothing else but a newline character

Is there a way to use scanf (without using any other I/O function) to check whether the user input exists only of a single integer with nothing following it?
For example:
int g;
while(scanf("%d", &g)!=1){
printf("\nincorrect input, try again");
}
This works fine for input like "/" or "-" but when you input "54.32" then it will read until the ".", the read count of scanf will be 1 and 54 will be stored in g. Is there a way to check if the input consists solely of a single integer followed by nothing but a newline character?
I would like to know if there exists a solution without using fgets or any other IO function?
to check solely of a single integer followed by nothing but a newline character
Use "%n" to record number of characters scanned, if it gets that far.
int n = 0;
scanf("%d*1[\n]%n", &g, &n);
if (n > 0) puts("input consists solely of a single integer followed by a newline");
If the result is not as hoped, additional code needed to cope with the errant input.
I recommend using fgets() to solve the larger problem.
Edit because I misunderstood the question: what about this?
#include <stdio.h>
int main() {
int n;
char c;
scanf("%d", &n);
scanf(" %c", &c) ? printf("incorrect input, try again\n") : printf("%d\n", n);
return 0;
}
You can use the assignment-suppressing format operator to extract everything (anything) after the integer, and the number-of-characters-read format specifier to see whether that matched anything, without having to store it anywhere.
See your documentation.
Eg,
int g, gchars, xchars;
scanf("%d%n%*s%n", &g, &gchars, &xchars);
if (xchars > gchars)
printf("%d extra characters discarded after integer %d\n", xchars-gchars, g);

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);
}

Scanf won't notice '\n' char in a program loading only numbers

I have been searching for a few days and I have found only one solution that didn't look perfect to me. Our teacher asked us to create a function that would calculate total lenght of distances in between points provided by user.
My idea was to write code this way, using an array of specific type.
The issue is that, I can't come up with any ideas for how to solve the issue with input: He asked us to make the program end once the user doesn't type anything, so I take it for enter - \n sign.
I could use fgets to get the first variable but:
First, I feel like I don't know any other way beside an array for keeping a long decimal number(in a form of a char array with elements making up the number), that the user could put on the input. I don't know if his script doesn't put some "rofl" number in there.
Second, in this case I think that stripping that array off one X would totally break the total structure of this program. I would rather take both X and Y and accept them as char type, but then the function like atof would probably understand only the X and would stop working after the \n sign.
So Y would be left not given. The accepted input numbers should be of double type. Like:
2 2
3 3
-2 4.5
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
double lenght(struct point *coordinates, int n);
struct point {
double x;
double y;
};
int main()
{
double x,y,TwiceAsBig=3;
int i=0,l=0;
struct point *coordinates;
coordinates = (struct point*)malloc(sizeof(*coordinates)*3);
//allocation of memory for pointtype array with a pointer
while(scanf("%lg %lg",&x,&y)==2)
{
coordinates[i].x=x;
coordinates[i].y=y;
i++;
if(i==TwiceAsBig)
{
coordinates = (struct point*)realloc(coordinates, 2*i*sizeof(*coordinates));
TwiceAsBig=2*TwiceAsBig;
}
}
printf("\n");
for(l;l<i;l++)
{
printf("%lg %lg\n", coordinates[l].x,coordinates[l].y);
}
//checking on the array if the values were loaded correctly
printf("%lg",lenght(coordinates,i));
}
//function for dinstace in between the points
double lenght(struct point*coordinates,int n)
{
int l=0;
for(l;l<n;l++)
{
printf("%lg %lg\n", coordinates[l].x,coordinates[l].y);
}
int pair=0;
double lenght,distance;
for(int AoP;AoP<n-1;AoP++)
{
distance=sqrt(pow(coordinates[pair+1].x-coordinates[pair].x,2)+pow(coordinates[pair+1].y-coordinates[pair].y,2));
pair++;
printf("%lg: ", distance);
lenght=lenght+distance;
}
return lenght;
}
As for your problem, using fgets to read a whole line, and the possibly use sscanf to parse out the two numbers might work.
The problem with using only scanf is that all the numeric format specifiers reads and skips leading white-space automatically, and newline is a white-space character. That means your scanf call in the loop condition will wait until there's some actual non-space characters being input (followed by a newline of course, which leads to the cycle starting over again).
What about using scanf("%[^\n]%*c", test); to read a full string.
Then parsing the result using sscanf?
Something like this:
char* userinput = (char*) malloc(sizeof(char) * 100);
scanf("%[^\n]%*c", userinput);
double a, b;
sscanf(userinput, "%lg %lg", &a, &b);
printf("sum %lg\n", a+b);
With input "-5.5 3.2" the code produces "sum -2.3".
%[^\n]%*c is a "scanset" which tells scanf to read everything excluding '\n' and once it reaches a newline it reads the newline character and disregards it.
You could even use scansets to check the input to some degree by specifying which type of characters you expect to read.
%[0-9 .\\-] // would read digits from 0-9, 'space', '.' and '-'

C - how to read input from text file to 2D array [duplicate]

Suppose,"5181 2710 9900 0012"- is a string of digits.I need to take one single digit at a time as input from the string of number without space to make arithmatic operations . So, i write that,
int a[20];
for(int i=0;i<16;i++)
{
scanf("%d",&a[i]);
}
but it didn't give me expected result. But when i use "%1d"instead of "%d",it gave me the expected result. so, how it works?
Since scanf is the inverse of printf, you could verify this by printing any number with the modifier (just a little tip).*
In general, the number before the format is a 'width' modifier. In this case it means you're only reading one byte into a number. If you specify %d, it may be a number of arbitrary length.
Example:
#include <stdio.h>
int main() {
int a;
sscanf("1234", "%d", &a);
printf("%d\n", a); // prints 1234
sscanf("1234", "%1d", &a);
printf("%d\n"m a); // prints 1
}
*) this appears to be false for this particular case. Makes sense that numbers are not truncated when specifiying a %d format, though, since that would change the meaning of the number. However, for many cases you could try what printf would do to predict scanf's behavior. But of course, reading the manual or docs on it is always the more helpful approach :)

How to take one character at a time as input from a string of characters without space in c?

Suppose,"5181 2710 9900 0012"- is a string of digits.I need to take one single digit at a time as input from the string of number without space to make arithmatic operations . So, i write that,
int a[20];
for(int i=0;i<16;i++)
{
scanf("%d",&a[i]);
}
but it didn't give me expected result. But when i use "%1d"instead of "%d",it gave me the expected result. so, how it works?
Since scanf is the inverse of printf, you could verify this by printing any number with the modifier (just a little tip).*
In general, the number before the format is a 'width' modifier. In this case it means you're only reading one byte into a number. If you specify %d, it may be a number of arbitrary length.
Example:
#include <stdio.h>
int main() {
int a;
sscanf("1234", "%d", &a);
printf("%d\n", a); // prints 1234
sscanf("1234", "%1d", &a);
printf("%d\n"m a); // prints 1
}
*) this appears to be false for this particular case. Makes sense that numbers are not truncated when specifiying a %d format, though, since that would change the meaning of the number. However, for many cases you could try what printf would do to predict scanf's behavior. But of course, reading the manual or docs on it is always the more helpful approach :)

Resources