What is the specifier %[^s] used for?
s is a variable.
In which cases can I use this specifier?
The %[ format specifier to scanf will match a sequence of characters matching those that are listed between [ and ]. If the first character is ^, then it matches characters excluding those characters.
In your case %[^s] means "match any character besides the characters 's'. s is not a variable in this case.
Related
For each of the following pairs of scanf format strings, indicate whether or not the two strings are equivalent. If they're not, show how they can be distinguished:
(b) "%d-%d-%d" versus "%d -%d -%d"
So in this case, my answer was that they were not equivalent. Because non-white-space characters except conversion specifier which start with %, cannot be preceded by spaces, it will not match with the non-white-space character. So in the first case, no spaces will be allowed after the first and second integer, while in the second case, any number of spaces will be allowed after the first 2 integers.
But I saw that the book had a different answer. It said that they were both equivalent to each other.
Is this the mistake of the book? Or am I just wrong with the concept of format string in the scanf function?
The book is wrong. As per the specification of the scanf():
Whitespace character: the function will read and ignore any whitespace characters encountered before the next non-whitespace character (whitespace characters include spaces, newline and tab characters -- see isspace). A single whitespace in the format string validates any quantity of whitespace characters extracted from the stream (including none).
Non-whitespace character, except format specifier (%): Any character that is not either a whitespace character (blank, newline or tab) or part of a format specifier (which begin with a % character) causes the function to read the next character from the stream, compare it to this non-whitespace character and if it matches, it is discarded and the function continues with the next character of format. If the character does not match, the function fails, returning and leaving subsequent characters of the stream unread.
So in first case when scanf arrives to the %d and gets the input, next is the - which means that scanf will expect next in the stream to see the non-whitespae character - and not any other whitespace character. So the legal input is 1- 2, but not 1 -2
In the second case, after first %d, scanf will allow the whitespace and than will arrive to non-whitespace, so it will allow the input 1 - 2 by the above definitions.
"%d-%d-%d" differs from "%d -%d -%d" and the difference has nothing to do with "%d".
Format "-" scans over input "-" and stops on the first space of input " -".
Format " -" scans over inputs "-" and " -" as the " " in the format matches 0 or more white-space characters in the input.
A directive composed of white-space character(s) is executed by reading input up to the first nonwhite-space character (which remains unread), or until no more characters can be read. The directive never fails. C17dr § 7.21.6.2 5
Had the question been: "%d-%d-%d" versus "%d- %d- %d",
These 2 are functionally identical.
We would need to dive input arcane stdin input errors to divine a potential difference.
Why some writers use %[^\n]s specifier instead of %[^\n]? Which one is correct?
If you want to read in a sequence of non-newline characters, %[^\n] is correct.
The %[ format specifier to scanf will accept any following characters until a ] is encountered. If the first given character is ^, then it accepts characters not in this list. The characters that are read are then placed in the given char * parameter.
%[^\n]s is the above format specifier followed by a literal 's'. The s is not part of the %[ format specifier. So this will read characters until it encounters a newline and put those characters in the given char *, then it will attempt to read an s character which it doesn't find because a newline is next.
#include<stdio.h>
void main()
{
char a,b;
printf("enter a,b\n");
scanf("%c %c",&a,&b);
printf("a is %c,b is %c,a,b");
}
1.what does the whitespace in between the two format specifiers tell the computer to do?
2.do format specifiers like %d other than %c clean input buffer before they read from there?
1.what does the whitespace in between the two format specifiers tell the computer to do?
Whitespace in the format string tells scanf to read (and discard) whitespace characters up to the first non-whitespace character (which remains unread)1. So
scanf("%c %c",&a,&b);
reads a single character into a (whitespace or not), then skips over any whitespace and reads the next non-whitespace character into b.
2.do format specifiers like %d other than %c clean input buffer before they read from there?
Not sure quite what you mean here - d will skip over any leading whitespace and start reading from the first non-whitespace character, c will read the next character whether it's whitespace or not. Neither will flush the input stream, nor will they write to the target variable if the directive fails (for example, if the next non-whitespace character in the input stream isn't a digit, the d directive fails, and the argument corresponding to that directive will not be updated).
N1570, §7.21.6.2, para 5:
"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."
Wikipedia says
whitespace: Any whitespace characters trigger a scan for zero or more
whitespace characters. The number and type of whitespace characters do
not need to match in either direction.
"%d" will skip whitespace until it finds an integer.
"%c" reads a single character (and space is a character, so it doesn't skip).
Can anyone suggest what is the meaning of a in the following call to scanf?
scanf("%d a %f",&i,&f)
Characters preceded by a '%' in a call to scanf represent variables.
For instance %d represents an integer variable whereas %f represents a floating-point variable.
Characters which are not preceded by a % (or a \, which indicates an escape sequence) are taken literally, so, in your case, the scanf string "%d a %f" would match "233 a 4.5" but would not match "233 b 4.5".
(To be more accurate, a whitespace character matches any contiguous sequence of whitespace characters.)
scanf("%d a %f",&i,&f)
Means you have to type in data , in this format 25 a 33.3
Then when you print it using
printf("i=%d f=%f",i,f);
and then you get the output as
i = 25 , f = 33.3
You are not getting the value of the variable f because of the & in the line scanf("%d a %f",&i,&f)
The & means you are getting the address of the variable f in the memory. You should remove the '&'s to get the actual value of the variables.
And for the a:
Non-whitespace character, except format specifier (%): Any character that is not either a whitespace character (blank, newline or tab) or part of a format specifier (which begin with a % character) causes the function to read the next character from the stream, compare it to this non-whitespace character and if it matches, it is discarded and the function continues with the next character of format. If the character does not match, the function fails, returning and leaving subsequent characters of the stream unread.
Which means you are formatting the input as so:
type in a decimal integer(%d)
then a space
then the character 'a'
another space
then the floating point number(%f).
Reference: http://www.cplusplus.com/reference/cstdio/scanf/
I found such an example of scanf in C book (this time not K&R):
scanf(" %[-' A-Za-z]s",&variable);
Can anybody provide me with information what does it accept?
I have not found any info about using 'a' or 'z' as conversion characters
From the standard (C11, §7.19.6.2/12):
] Matches a nonempty sequence of characters from a set of expected characters
That means that your format expects a run of of the characters -, space, A, ..., Z, a, ..., z.
The [ conversion specifier has provisions for two special characters: %[^... inverts the matching set, and a hyphen (-) between two characters indicates a range, as is used in your A-Z and a-z.