What does “~scanf” mean? - c

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)

Related

Why does scanf return a positive value even when the input is larger than the numercial type given?

Given the following code :
int x;
int r = scanf("%d", &x);
why is scanf returning 1 when the user inputs a number larger than INT_MAX or even larger than LONG_MAX?
From the documentation:
Number of receiving arguments successfully assigned.
Why is x considered successfully assigned? What does it mean exactly in this context? When the user gives numbers between INT_MAX and LONG_MAX, x appears to be the lower half of the result. I know scanf uses strtol internally but scanf could determine that the type int is too small to contain the result. Further, when passing a giant number, larger than LONG_MAX, the value of x is -1 and the return value is still 1 and I have to rely on errno to check that something went wrong (errno == ERANGE).
What does "successfully assigned" mean and why does scanf return 1 given that it could so easily tell that the result is, in fact, garbage?
Unfortunately you cannot rely on errno == ERANGE or such in portable C programs.
fscanf is not documented authoritatively on cppreference.com, but in the ISO C standard. Firstly, the standard states that
The fscanf function returns the value of the macro EOF if an input failure occurs before the first conversion (if any) has completed. Otherwise, the function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the event of an early matching failure.
I.e. nowhere does it contain the word "successful".
On the contrary, it says:
[...] if the result of the conversion cannot be represented in the object, the behavior is undefined.
I.e. unfortunately there are no guarantees of behaviour in this case. In particular the standard never states that the result would be the largest number, or that errno would contain ERANGE or any other such thing.
why is scanf returning 1 when the user inputs a number larger then INT_MAX or even larger than LONG_MAX?
It is undefined behavior (UB) when the input text converts to outside the int range for "%d". It is a specification weakness of scanf().
Anything may happen.
Robust code separates input from conversion. Look to fgets() and strtol().
"scanf" is a function that reads data with specified format from a given string stream source. It allows the programmer to accept input from the standard input device (keyboard) and stores them in variables.
"scanf" stands for 'scan format', because it scans the input for valid tokens and parses them according to a specified format.
Reads a real number that (by default) the user has typed in into the variable miles
Each variable must be preceded by the ampersand (&) address-of operator.
We can read values into multiple variables with a single scanf as long as we have corresponding format strings for each variable.
"scanf" successfully accomplishing the 'scan format' function. It's not the function of "scanf" to check for the range for corresponding datatype.
Remember that scanf (and its brothers and sisters) is a variadic function. There's value in telling the caller how many arguments were successfully assigned, where "successfully" might mean less than you think it does. It's the responsibility of the caller to make sure the arguments agree.

what does while(~scanf mean in C?

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".

Why char value assignment to float is not working

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.

What should scanf return on EOF after partial match?

Consider the following scanf conversion specifiers and inputs:
"%4c" and "abc"
"%x" and "0x"
"%f" and "1.0e+"
That is, cases where the input is an initial subsequence of a match, but not a match. Assuming EOF is reached after the incomplete match, is scanf supposed to return EOF or 0? The text in C99 reads:
The fscanf function returns the value of the macro EOF if an input failure occurs before any conversion. Otherwise, the function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the event of an early matching failure.
And in POSIX 2008, it reads:
Upon successful completion, these functions shall return the number of successfully matched and assigned input items; this number can be zero in the event of an early matching failure. If the input ends before the first matching failure or conversion, EOF shall be returned. If any error occurs, EOF shall be returned, [CX] and errno shall be set to indicate the error. If a read error occurs, the error indicator for the stream shall be set.
What's unclear to me is whether the partial but incomplete match constitutes an "early matching failure". I would find the return value of 0 in this case a lot more useful (it distinguishes the cases of plain EOF versus invalid truncated data) but what I'm looking for is just help interpreting the standard.
Note that glibc's scanf is completely incorrect on all of these inputs and returns 1, treating the invalid input as a match. I'm pretty sure this issue has been reported and marked WONTFIX. :-(
I'm expecting 0.
7.16.6.2/4:
Failures are described as input failures (due to the occurence of an encoding error or the unavailability of inout characters), or matching failures (due to inappropriate input).

Is EOF always negative?

Is EOF always negative?
I'm thinking of writing a function that reads the next word in the input and returns the line number the word was found in or EOF if the end of the input has been reached. If EOF is not necessarily negative, the function would be incorrect.
EOF is always == EOF. Don't assume anything else.
On a second reading of the standard (and as per some other comments here) it seems EOF is always negative - and for the use specified in this question (line number or EOF) it would work. What I meant to warn against (and still do) is assuming characters are positive and EOF is negative.
Remember that it's possible for a standard conforming C implementation to have negative character values - this is even mentioned in 'The C programming language' (K&R). Printing characters are always positive, but on some architectures (probably all ancient), control characters are negative. The C standard does not specify whether the char type is signed or unsigned, and the only character constant guaranteed to have the same value across platforms, is '\0'.
Yes, EOF is always negative.
The Standard says:
7.19 Input/output
7.19.1 Introduction
3 The macros are [...] EOF which
expands to an integer constant
expression, with type int and a
negative value, that is returned by
several functions to indicate
end-of-file, that is, no more input
from a stream;
Note that there's no problem with "plain" char being signed. The <stdio.h> functions which deal with chars, specifically cast the characters to unsigned char and then to int, so that all valid characters have a positive value. For example:
int fgetc(FILE *stream)
7.19.7.1
... the fgetc function obtains that character as an unsigned char converted to an int ...
Have that function return
the line number the word was found in
or -1 in case the end of the input has been reached
Problem solved, without a need for relying on any EOF values. The caller can easily test for greater-or-equal-to-zero for a successful call, and assume EOF/IO-error otherwise.
From the online draft n1256, 17.9.1.3:
EOF
which expands to an integer constant expression, with type int and a negative value,
that is returned by several functions to indicate end-of-file, that is, no more input
from a stream;
EOF is always negative, though it may not always be -1.
For issues like this, I prefer separating error conditions from data by returning an error code (SUCCESS, END_OF_FILE, READ_ERROR, etc.) as the function's return value, and then writing the data of interest to separate parameters, such as
int getNextWord (FILE *stream, char *buffer, size_t bufferSize, int *lineNumber)
{
if (!fgets(buffer, bufferSize, stream))
{
if (feof(stream)) return END_OF_FILE; else return READ_ERROR;
}
else
{
// figure out the line number
*lineNumber = ...;
}
return SUCCESS;
}
EOF is a condition, rather than a value. The exact value of this sentinel is implementation defined. In a lot of cases, it is a negative number.
From wikipedia :
The actual value of EOF is a
system-dependent negative number,
commonly -1, which is guaranteed to be
unequal to any valid character code.
But no references ...
From Secure Coding : Detect and handle input and output errors
EOF is negative but only when sizeof(int) > sizeof(char).

Resources