What does an asterisk in a scanf format specifier mean? [duplicate] - c

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.

Related

why printf with %d specifier giving wrong result?

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

Why this C scanf is automatically skipped? [duplicate]

This question already has answers here:
How to read / parse input in C? The FAQ
(1 answer)
scanf() leaves the newline character in the buffer
(7 answers)
Closed 6 years ago.
I am facing problem regarding scanf in C. When I run this:
char c;
int a, b;
scanf("%d", &a);
scanf("%c", &c);
scanf("%d", &b);
Then first two scanf were working properly but 3rd one is skipped completely. I searched different posts in this forum about this problem and found a lot of information, but want to know something else.
I already found that the easiest solution would be:
scanf("%d %c %d", &a, &c, &b);
And another solution could be using:
getchar();
And I also found that the reason behind my problem is it writes an extra new line character \n to the buffer, that's why the 3rd one was skipped. But for further researching I found that when I use another scanf of char type after 2nd scanf then it works. That means, in my case the problem occurs if I take input of any integer type after char type. Again I have seen many others were problem having opposite case, they couldn't take input of char after integer. Now I want to be clarified about the exact schemes those are supported in C for scanf that is when I will face similar problems and why char can be scanned after char but integer can't. Thanks to all.
The "%d" format specifier includes skipping leading white-space. The "%c" format doesn't have that, it reads the next character in the input buffer no matter what kind of character it is.
If you want to skip leading white-space using the "%c" format, you need to tell scanf explicitly to do so with a space in the format string, like e.g. " %c".
This is the same problem as "not able to take char after an int", with a small twist.
Recall that when you read an int from an input using scanf with %d format specifier, the characters representing the number are consumed, but the separator following it is not. Consider a buffer that looks like this (I use underscores to show spaces):
char 9 8 _ x _ 7 6
- - - - - - -
position 0 1 2 3 4 5 6
Before the first scanf call your buffer is positioned at zero.
After the first call your buffer is positioned at 2.
After the second call your buffer is positioned at 3, because space is read for your char
Now the problem becomes clear: the third scanf tries to read an int, but the buffer is at x, so the read is not possible.

What is really happening on removing and adding white space characters?

I'm new in programming and learning basics of C programming. I'm learning about how scanf() works but I think now I'm very much confused and really don't know how and what to ask. But I will try my best to put my question clear.
Questions
I'm really not able to understand the whole concept of whitespace. I mean when they are skip by the scanf and when they are not and biggest question: How they are skipped?
Along with the whitespace concept I'm not able to understand the working of scanf function also? I had read about it in many books and websites and also in this site but it confuse me more since each person has their own way of telling any concept and it vary from one to another.
Have a look at this short program:
#include<stdio.h>
int main()
{
int num;
char ch;
printf("enter the value of num and ch:\n");
scanf("%d",&num);
scanf("%c",&ch);
printf("num = %d and ch = %c",num,ch);
return 0;
}
I know that in this program user will be allowed to enter the value of num only, because of the new line character that stays back in the input buffer and next time scanf will input that new line character but can be solved if we add extra space before %c in the second scanf function.
But when I replace the char ch variable with int ch, scanf skips the new line. Why?
Why scanf do not skip non-white space character just like whitespace For example - a, b, c, d, #) # etc?
What is the difference between space and newline character in scanf? I mean there will some exceptions right?
First Question
I mean when they are skip by the scanf and when they are not
White-space characters are skipped unless the format specifier is %c, %n or %[. Relevant quote from the C11 standard:
7.21.6.2 The fscanf function
[...]
Input white-space characters (as specified by the isspace function) are skipped, unless the specification includes a [, c, or n specifier. 284)
How they are skipped?
Just read and discard them.
Second Question
I'm not able to understand the working of scanf function also?
scanf is a variadic function meaning that it can take any number of arguments with a minimum of one. scanf parses the first argument which is a string literal and accordingly, takes input.
Third Question
But when I replace the char ch variable with int ch, scanf skips the new line. Why?
First part of the first answer explains it. %d will skip whitespace characters.
Fourth Question
Why scanf do not skip non-white space character just like whitespace?
For some conversion specifiers like %c, non-whitespace characters are valid inputs. It doesn't make sense why they should skip them. For other like %d, characters ( not numbers ) are invalid inputs. scanf stops scanning and returns when it sees invalid input. It is designed this way.
Fifth Question
What is the difference between space and newline character in scanf?
There is no difference when any of them are placed in the format string in scanf. Both of them are considered as whitespace characters, although they are different characters. They skip any number of whitespace characters, including none, until the first non-whitespace character when they are used in the format string of scanf. Relevant quote from the C11 standard:
7.21.6.2 The fscanf function
[...]
A directive composed of white-space character(s) is executed by reading input up to the first non-white-space character (which remains unread), or until no more characters can be read. The directive never fails.

warning: multi-character character constant [-Wmultichar]| [duplicate]

This question already has answers here:
Multi-character constant warnings
(6 answers)
Closed 8 years ago.
/* Beginning 2.0 */
#include<stdio.h>
main()
{
printf(" %d signifies the %c of %f",9,'rise',17.0);
return 0;
}
Hello people
When I compile this, the compiler giving the following warning:
warning: multi-character character constant [-Wmultichar]|
And the output only prints e instead of rise.
Are multiple characters not allowed in C?
How can I print the whole word (rise)?
Please help me out.
Try: printf(" %d signifies the %s of %f",9,"rise",17.0);.
C distinguishes between a character (which is one character) and a character string (which can contain an arbitrary number of characters). You use single quotes ('') to signify a character literal, but double quotes to signify a character string literal.
Likewise, you specify %c to convert a single character, but %s to convert a string.
Use %s and "" for a character string:
printf(" %d signifies the %s of %f",9,"rise",17.0);
^^ ^ ^
For 'rise', this is valid ISO 9899:1999 C. It compiles without warning under gcc with -Wall, and a “multi-character character constant” warning with -pedantic.
According to the standard (§6.4.4.4.10),
The value of an integer character constant containing more than one character (e.g., 'ab'), [...] is implementation-defined.

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