Formatted string in scanf() in C - c

Just like printf(), I was trying to use optional specifiers in scanf() format string. I tried to use the width and precision specifier. Now in printf() it simply reserves the columns and print according to these specifiers but what happens with scanf()? Like what is meaning of %3d and %3.3f here? Is this even relevant in case of scanf()? I have a little idea that width in this case represents the number of characters that are to be read for some particular format but not sure. Below code explains this further:
#include<stdio.h>
int main()
{
int a;
float b;
printf("Enter Numbers:\n");
scanf("%3d %3.3f",&a,&b);
printf("Entered Numbers are\n");
printf("%d %f",a,b);
return 0;
}

Since you specified in the comments that what you really want to know is 'what if i forcefully try to do it' ... Here are the results (with Clang)
warning: invalid conversion specifier '.'
and
warning: data argument not used by format string
The program compiles , however, since these are just warnings.
Upon executing the binary, and entering the variables asked for:
The "%d" for a gets stored properly.
Regardless of what value is entered, the " %3.3f " for b always stores 0.000000
In short, the it does what almost any other code that compiles with warnings does - not behave as intended. This is neither undefined, nor unspecified behaviour, but it is wrong.
Suggestion : Refrain from asking questions that are of the nature ' what happens if I try to compile this '. Just try and see for yourself !

Related

Code::Blocks does not recognise double identifier (%lf) in a simple C program

Today I decided to recap a bit the C programming language fundamentals and I have encountered this small issue within my Code::Blocks IDE: when I had used the %f format identifier to read and write a decimal number everything went well, but when I had switched to the %lf format identifier, it did not read or write the number properly.
This is my code:
#include <stdio.h>
int main()
{
double x;
scanf("%lf", &x);
printf("x = %lf", x);
return 0;
}
This is the output:
These are the compiler settings from the Code::Blocks menu:
I have searched for a solution online, including the Code::Blocks forums, but I haven't found anything relevant. I am not sure whether is a compiler problem or an IDE problem. If you know a fix or you have an explanation for this issue, please help me. I am preety sure other people encountered this as well.
It is unclear what Code::Blocks is warning about. The lf in the scanf format string is also underlined but is definitely correct as the destination variable has type double.
For printf, the l modifier is unnecessary but should be ignored by printf. float values are converted to double when passed to vararg functions such as printf, so %f accepts both float and double values, while long double values require an L modifier.
The suggested corrections seem to indicate that Code::Block tries to apply some sort of spelling checker to string constant contents, regardless of conversion specifiers in printf and scanf format strings.
I suggest you change the printf format string to printf("x = %f\n", x); for full conformity.
You should also configure the compiler for higher warning levels (-Wall -W or -Weverything) to enable printf and scanf format string validation.
The issue is described in more detail inside this thread for those who are interested:
Correct format specifier for double in printf

Integer taken with scanf() does not get its intended value in C

Here is my C code:
#include "stdio.h"
int main()
{
int minx, x;
printf("Enter two ints: ");
scanf( "%d-%d", &minx, &x);
printf("You wrote: minx is %d x is %d", minx, x);
}
When the input is 5-3 or 5- 3 the output is You wrote: minx is 5 x is 3 which makes sense. However, when the input is 5 -3 or 5 - 3 or 6 -4 the output is You wrote: minx is 5 x is 8. I expected - to skip white spaces, so I expected minx to be 5 and x to be 3,6 and 4 for the other input. This also happens when - in %d-%d changed to ?, *, + even with the same inputs. I know it is probably because of that space after the first int. Here it says only three format specifiers do not skip white space — Whitespace before %c specification in the format specifier of scanf function in C. Did I get this wrong? Why - does not skip leading space here? What is the actual problem here and what is the cause of it? Why is it 8? What other operators or chars can lead to similar problems?
Let's look at your scanf format specifier "%d-%d" in detail:
%d skip whitespace if necessary, then read an integer
- match a literal '-' character
%d skip whitespace if necessary, then read an integer
So the inputs 5-3 and 5- 3 both work just fine. But when the input is 5 -3 (or anything else with a space before the -) the parse fails, because scanf does not immediately see the - it expects.
If that's not what you expected, or not what you want, or if that doesn't make sense, or if that's not how you'd like scanf to work, I'm afraid that's too bad: scanf works the way it works.
How can you fix this? That depends in part on why you included the - character in your format string in the first place.
You can use %d%d or %d %d, which will simply read two integers (separated by at least one whitespace character). If there's a - character preceding the second integer, that integer will be read as negative.
You can use %d -%d, which will skip (arbitrary) whitespace before it tries to match the - character.
You can use two separate scanf calls.
If you do continue to use scanf, you really need to check its return value so that your program can detect the case that the expected inputs were not matched.
Finally, you can use something other than scanf.
My recommendation to you depends on the ultimate purpose of this program.
If it's just for learning, then minimize the amount of time you spend fussing with the way your program does input at all. For example, if you need to read an integer, use one %d. As long as you can get the numbers you need into your program (so that you can test the rest of your program), you're fine. If there are things you can type that cause scanf to get confused, just don't worry about it, just don't type those things. Don't try to do anything fancy — that's not what scanf is for.
If this is a "real" program, that does have to accept arbitrary user input, or input with a specific syntax (like with that - in the right place), and if you need to deal gracefully with incorrect input, printing appropriate errors, and not reading the wrong values or getting confused — then run, do not walk, away from scanf, and never use it again. It is effectively impossible to write a program that performs high-quality input using scanf. Not even a C expert can do it. It's simply not worth it. You will spend five times as long, and get an inferior result, than if you simply abandoned scanf and read your input a line at a time using fgets or the like, then parsed the input line (perhaps even using sscanf — but again, check its return value).
Addendum: It's true, all format specifiers — with three exceptions (%c, %[…] scan sets, and %n) — skip whitespace before beginning their work. But format specifiers are things that begin with %. Literal characters in the format string must match exactly, and there's no implicit whitespace skipping for them. If you want to skip whitespace at spots in the input other than before the % format specifiers that do it, you can include a literal whitespace character (usually a single space) in your format string.
You need to check the return value of scanf. You should be doing this, in general, for every library function you call that has a return value.
In your case, scanf would return 2 (meaning two output parameters were set) for valid input. If you get any other return value, the input does not match the format you specified, and you should ignore the contents of your output parameters minx and x.

Double, Integer, Long double

I apologies in advance if there is a stupid error in this code, but I can't seem to trouble shoot it. My problem is this, I compile with GCC-8 (installed on Mac via home-brew), then execute in the terminal. When using int do define variables s & a, I get zeros as output using the print statements below. If I declare s & a variables as double I still get zeros for the first two print statements, and 1024 for the last print statement. I'm just lost as to what is going on. Appreciate any help!
/* square code */
#include <stdio.h>
int main() {
int s, a;
printf("enter the length of your square \n");
scanf("%f", &s);
a= s * s;
printf("the area of your square is %f cm using f placeholder \n", a);
printf("the area of your square is %lf cm uning fl placeholder\n", a);
printf("the area of your square is %d cm using d placeholder \n", a);
return(0);
}
int s;
scanf("%f", &s);
If s is an int then you need to scan it in like an int using "%d" instead of "%f". What you are doing is undefined behavior, both in scanf() and printf(). An integer needs to be scanned and printed as an integer.
I think the misunderstanding is that you treat the conversion specifiers %d and %f as defining only the output formatting, regardless of the type of value passed.
Actually each conversion specifier is tightly coupled with a particular type of argument it will accept; For example, %d is defined for integral types only, and all other types like floating point or string used together with %d will yield undefined behaviour (cf, for example, cpp-reference of printf for a more detailed explanation).
So double f=1.2;printf("%d",f) will not format a floating point value 1.2 as integral (someone might expect 1 being the output); It rather yields undefined behaviour, having any output (even no output), a crash, a... whatever.
Same applies to scanf-format specifiers, of course.
So if data type is int, use %d; if data type is double, use %f.
In your code you use s as an int, and when you use scanf you are using %f instead of %d. That's the reason why you are getting the first two outputs as a zero.
As for the third output, you will get the expected value, because in that case you are correctly using %d. See the code below:
int s;
printf("enter the value");
scanf("%d", &s);
printf("the area of square is=", s*s);
Hey guys thanks so much for the help. Before checking back this morning I tried one more thing, and alas it was a stupid error.
When declaring "double s,a", I realized my scanf() function was using scanf("%f",s) as opposed to the correct scanf("%lf", s)".
Also thanks for the help for use of %d when using "int s,a".

C-variables won't be added [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
I have started learning C and I want to make an addition program.
I have written the following code:
#include <stdio.h>
#include <stdlib.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main() {
int a,b,c;
scanf("Give a,b",&a,&b);
c=a + b;
printf("A+b=",c);
printf("\n\n\n");
return 0;
}
It is supposed to take 2 numbers from the users and show their sum.
However the only output I get after the user writes 2 numbers is A+b=
Any ideas?
You failed to include a format specifier for your integer variable c. Without this printf doesn't know what arguments to expect following the format string, what their types are, or how they are to be printed. Change:
printf("A+b=",c);
to:
printf("A+b=%d",c);
Note that a good compiler with warnings enabled (e.g. gcc -Wall ...) would have pointed out this simple mistake for you at compile-time.
Also your scanf usage is wrong - change:
scanf("Give a,b",&a,&b);
to:
printf("Give a,b");
scanf("%d %d",&a,&b);
You're missing the %d conversion specifier in the printf() call:
printf("a+b=%d\n", c);
Without that, printf() doesn't know it's getting a second argument and won't do anything with it.
Of course, that c could just be a + b, there's no need to store the sum in a separate variable just to print it.
Also, you need specifiers in scanf(), it should be:
scanf("%d %d", &a, &b);
The first argument to scanf() is not a prompt that's printed, it's describing the expected input.
Last, you should check the return value of scanf() to make sure it's 2 before relying on a and b having valid values. I/O can fail, you need to make sure your program does the right thing if that happens.
scanf is a function used to take in input from the user. You are expecting it to print something, ain't you? You need printf instead:
printf("Give a,b\n"); //\n at the end is good
Now, use scanf to scan in the input:
scanf("%d %d",&a,&b);
You are also missing the %d format specifier in the last printf as other answers have mentioned.
scanf() is an input C function (scan with formatting) that uses format specifiers (%datatype ex: %d or %i = int, which is what you want, or %c = char) to store a data entry in given format, provided by the stdin (keyboard buffer) up to and including a null (\0) termination char(in the case of a string);
The Ampersand (&) in C is used to designate/return the memory address (where variable is stored), as opposed to the value of the variable.
scanf("Give a,b",&a,&b);
c=a + b;
printf("A+b=",c);
The issue with above first line of code is that you forgot to include the format specifiers (%d or %i would both work in this case, as I assume you are adding integers and not floats/etc).
Thus the solution to your first problem is an easy one:
scanf("%d %d",&a,&b);
Also, it seems that you are attempting to combine an input and output in one line.
Printf, like scanf, can use format specifiers, or it can contain only a string of characters, and prints to the stdout (console).
What you want to do is include a prompt asking the user for input before storing said input. You add the \n "newline" character at the end to ensure to provide spacing between other outputs and inputs, among many other reasons when you get into char arrays[], aka strings. But for now, this should do the trick:
printf("Give a,b\n");
scanf("%d %d",&a,&b);
Hope this helps both with the current assignment and with general/C programming concepts!

Why was type checking not happening on second parameter and only on first parameter?

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

Resources