i watch some code and i don't know what the meaning of while(~scanf
while(~scanf("%s", word+1) !=EOF)
{
int a= strlen(word+1);
i already search google and found nothing on this. Please help
Analyzing the expression while(~scanf("%s", word+1) != EOF):
Run as long as the bitwise-inverted return value of scanf is not equal to the value of EOF.
Analyzing the equivalent expression while(scanf("%s", word+1) != ~EOF):
Run as long as the return value of scanf is not equal to the bitwise-inverted value of EOF.
Assuming that EOF is typically all 1s, this expression is essentially equivalent to:
while(scanf("%s", word+1) != 0)
Which means:
Run as long as the return value of scanf is not 0.
Or simply:
Run until the return value of scanf is 0.
I'm still scratching my head as to whether or not this analysis is correct.
Good question for a job interview (and a good example for how to not write code).
On success scanf will return the number of input items successfully matched. In this case there is only one input item to match therefore on success scanf will return 1, The code above will bitwise invert 1 which will make it -2. Since -2 != EOF, the loop will not end. Since EOF has a value of -1.
If scanf encounters an error or reaches end of input, for example because the user pressed Ctrl-D, it will return EOF and no new value will be placed in the memory location word+1. The code will bitwise invert EOF, which becomes 0, because ~EOF=0. Since 0 != EOF the loop will not end. The call to strlen will return the length of string that was in memory location word+1 prior to calling scanf.
The loop will only end if scanf returns 0, because ~0 = -1 = EOF. This will only happen if scanf was unable to match the input to a string for the conversion specifier "%s".
Related
I saw it in a code like this
while(~scanf("%d",&a))
I know that scanf() has return value,but I can’t understand what does ~ mean
This is a silly trick that relies on EOF having all its bits set. Since the standard does not guarantee the exact value of EOF, the behavior of this program is platform-dependent.
When scanf detects end-of-input, it returns EOF. Standard requires EOF to be negative. Very often EOF is set to -1. When ~ is applied to -1, you get back a zero, so the loop stops. On platforms with EOF defined as some other negative number the loop will never stop. Code's behavior also depends on the implementation-defined behavior of ~ with signed values.
You should rewrite the loop as follows:
while (scanf("%d", &a) != EOF) {
...
}
There are a few knowledge tidbits that are needed to explain how this works and what it does.
First: ~
~ is the bitwise NOT operator. It inverts the bits in a binary number.
ex:
1010111
0101000
Second: scanf()
If you look at the man pages for scanf():
NAME
scanf, fscanf, sscanf, vscanf, vsscanf, vfscanf
...
RETURN VALUE
These functions return the number of input items successfully matched
and assigned, which can be fewer than provided for, or even zero in the
event of an early matching failure.
The value EOF is returned if the end of input is reached before either
the first successful conversion or a matching failure occurs. EOF is
also returned if a read error occurs, in which case the error indicator
for the stream (see ferror(3)) is set, and errno is set indicate the
error.
We can see that when scanf() is successful, it will return some integer equal to or greater than 0. If it reached EOF or was otherwise unsuccessful, it will return the (integer) value EOF.
Third: the trick
If you NOT most non-zero integers, you will still receive a non-zero value in return.
The exception to this would be a number than when represented in binary would be entirely 1's:
~11111111 = 00000000 = 0
As it turns out in most computer systems this happens to be the value -1 which just so happens to be the value typically assigned to EOF
So
while(~scanf("%d",&a))
Could be re-written as
while(scanf("%d",&a) != -1)
or
while(scanf("%d",&a) != EOF)
This is the loop in my a4.c main method that calls the patternsearch function:
while(!feof(stdin)) {
scanf("%s", &word);
patternSearch(grid, word);
}
For some reason that I can't figure out, this prints the last call to patternsearch twice:
For example, look at my output for test3:
Found "tip" at 0 2, L
Found "pop" at 0 0, D
Found "pop" at 2 0, U
Found "key" at 0 3, D
Found "key" at 2 1, R
"nope" - Not Found
"nope" - Not Found
As you can see, the test result for 'nope' was printed twice. :(
I think my problem is similar to the one stated here:
Last line being printed twice (C++)
but I'm not sure.
Step 1 with any problem involving input: test the return value from the input function.
feof() checks if a prior read resulted in an end-of-file. It does not report about future reads.
Code is having trouble with unexpected results of scanf("%s", &word);, yet code did not check the return value from scanf(). Weak code does not check the return value. Robust code does. Research the proper use of scanf() and its return values.
Do not use "%s" without a width limit.
The & in scanf("%s", &word); is likely not needed. Would need to see word declaration to be sure.
char word[100];
while (scanf("%99s", word) == 1) {
patternSearch(grid, word);
}
The issue here was that feof() only returned true when I actually hit the EOF character.
That means that I was calling scanf(), and hitting the EOF;
that means the loop won't iterate again, but I was already in the middle of it.
But scanf() only actually changes the argument I hand it if it successfully reads what I asked;
since it failed (by hitting EOF),
it won't change the character array, which will still contain whatever it did before (i.e. the previous word).
I checked the return value of scanf(); the number it returns, which is the number of arguments it put a new value into;
if that's less than 1, then I didn't actually get a new string (I think it also explicitly returns EOF if it hits the end-of-file; EOF is a #defined constant that's equal to -1 on most platforms, so the <1 check will work anyway).
This is the code that finally worked:
while(!feof(stdin)) {
if (scanf("%s", &word) < 1)
break;
patternSearch(grid, word);
}
I am using getchar() while writing a program in C (scanf is not allowed yet at this point in the course.) I was wondering if every single time I call it if it moves to the next one; including during assignment operations. For example; I am trying to read in a double from the console; and decide if it has a negative sign on the front. If it does; I want to assign a variable neg to be 1 (so that I can tell if the end result should be returned negative) and then I want to move to the next character to do my actual double calculations and what not.
ex)
int x = getchar();
int neg = 0;
if(x == '-') {
neg = 1;
x = getchar(); // will this make it so the next time I use the x
} // variable it will be past the negative sign and to the
//first actual digit?
Yes, every time you call getchar() it will read the next character (provided there is next character to read).
Quoting C11, chapter §7.21.7.6
The getchar() function returns the next character from the input stream pointed to by
stdin.
In case there is nothing valid to be read,
If the stream is at end-of-file, the end-of-file indicator for the stream is set and
getchar returns EOF. If a read error occurs, the error indicator for the stream is set and
getchar returns EOF.
I am creating a simple Console application where its char *argv[] are expected to be in the form of floating number (such as 5.234, 7.197, and so on)
To ensure that the program only receive user inputs which are truly valid float, I created a function which combines sscanf (ref: character array to floating point conversion) and valid range checks (ref: How can I check if a string can be converted to a float?) results.
//buffer comes from agrv[n]
char MyFloatCheck(char* buffer)
{
float f;
char result;
result = sscanf(buffer, "%f", &f);
result &= isRangeValid(buffer);
return result;
}
Then I tested the the function above with:
Valid input: 12.15
Very large input: 4 x 10^40
Invalid inputs: (a) ab19.114, (b) 19.114ab
The results for my test no 1, 2, and 3(a) are expected:
1
0 (because it is too large)
(a) 0 (because it contains the invalid characters in front of the number)
However the result for 3 (b) is unexepected:
(b) 1 (??)
My questions are:
1. Why is that so?
2. Is there any built-in way to check this kind of input error?
3. Is there any well established workaround?
I am thinking of making my own function which checks the character from the right end to see if it contains invalid characters, but if there is any available built-in way, I would rather use it.
As you noticed, sscanf consumes characters one by one and writes the number that has been read in %f regardless of whether the reading stopped because of the end of the input string, a space, a newline, or a letter.
You would get the same behavior from strtof, a simpler substitute for sscanf(buffer, "%f", &f);:
char *endptr;
f = strtof(buffer, &endptr);
The above two lines give you a simple way to check that the entire string has been consumed after the call to strtof:
if (endptr != buffer && *endptr == 0) …
The condition endptr != buffer means that a floating-point number has been read. Otherwise, f is zero but that doesn't mean anything since no character was consumed. *endptr == 0 means that the entire input buffer was consumed in reading the floating-point number, which appears to be what you are looking for.
Note:This question is very simple but when I am searching in Google I haven't got any clear clarification.
I have following program
int main()
{
float c;
scanf("%f",&c);
printf("%f",c);
}
o/p
when I am giving a int value (e,g - 9) it is showing it as 9.000000
but when I am giving char value like 'a' it is not showing and showing 0.000000.I know the memory representation of float is totally different from int but then how when I am giving int value (9) it is showing but when I am giving char (a) which is also an int (97) is not showing.
How it is happening. What is the memory representation during char assignment.
Note that there are no chars here anywhere in your code.
This is the way scanf is supposed to work. If you check the return value from scanf (like you should be!) you'll probably see that it's returning 0, meaning no items were matched.
When you give scanf() a "%f" format string, that means "I want you to try and get me a floating point number. When you provide input like 'a', it's not going to match anything, because 'a' is not a valid floating-point number.
http://www.cplusplus.com/reference/cstdio/scanf/
First, you usually should end your printf format string with a newline \n or else call fflush.
Then, you should read the documentation on scanf i.e. its man page scanf(3)
It can fail, and it returns the number of successful matches:
Return Value
These functions return the number of input items successfully matched
and assigned, which can be fewer than provided for, or even zero in
the event of an early matching failure.
The value EOF is returned if the end of input is reached before either
the first successful conversion or a matching failure occurs. EOF is
also returned if a read error occurs, in which case the error
indicator for the stream (see ferror(3)) is set, and errno is set
indicate the error.
A failure is happening when you type an input letter a against a %f conversion specification. In your case the c variable is left unchanged (i.e. "uninitialized").
You should test the result of scanf (it is <=0 on failure in your case).
scanf in the form you wrote it will try to find and read numbers (int/float) up to the first non numerical character (newline, space, any letter). Letters are ints, but this is because of the scanf and the way it should behave. Read up the docs.