I was trying to figure out whether my input is numeric or not and I found this example:
while ( (scanf ("%d", &number) ) == 0) {
printf("Entered value is not integer");
}
I searched online but I did not find any explanation about this. Why it means not a integer (Does this mean your input contains alphabets?)if you scanf() a integer and equal to 0?
There probably wasn't any explanation for the code:
while ( (scanf ("%d", &number) ) == 0) {
printf("Entered value is not integer");
}
because there isn't a good explanation for it. It is bad code on multiple grounds, some of which have been covered by other answers, but some of which have not been mentioned.
The novel problems are:
If the scanf() reports 0, the program goes into an infinite loop. The character that was rejected as 'not part of a number' still isn't part of a number on the next cycle, so scanf() will consistently return 0 until the program is interrupted in some way.
You can work around this by eating (at minimum) the first character of the remaining input. It is probably better to eat up all the characters until the next newline is read. After all, if the user mistyped the number, whatever else is on the line is not reliably what they wanted to type.
The diagnostic message doesn't end with a newline, so it may not appear until enough copies of the message have been generated to fill the standard output buffer, whereupon a number of copies of the message will appear. There's a chance that you won't see this behaviour because the standard input and standard output stream might be synchronized so that any pending output is flushed before an input operation, but it is not reliable.
Then there's the boring stuff everyone else mentioned:
The scanf() function might return EOF, or 0, or 1 (because there is only one conversion specification). If it returns EOF, you have another cause for an infinite loop: it will return EOF each time it is called, but the code doesn't react to the information.
Most often, the correct way to detect that scanf() worked is to check that the return value is the number of values you expected should be returned (the number of active conversion specifications — you don't count %*d or %n or %% in the number of active conversion specifications, and maybe active isn't the best word, but it suffices for now).
Putting fixes for these issues together, you might arrive at:
int rc;
while ((rc = scanf("%d", &number)) != 1)
{
if (rc == EOF)
{
printf("EOF detected without a number\n");
break; // return, exit, ...
}
printf("Entered value is not an integer: ");
int c;
while ((c = getchar()) != EOF && c != '\n')
putchar(c);
putchar('\n');
// Optionally fflush(stdout);
}
See Using fflush(stdin) for why I didn't use fflush(stdin) instead of the loop. You may prefer not to echo the invalid entry, in which case you can replace the putchar(c); with just the semicolon (and adjust the error message before, and the putchar('\n'); after too), but it often helps people to understand what they did wrong if they see what the program thinks they typed. You might want to think about whether error messages should be written to standard error instead of standard output. If getchar() returns EOF, the next iteration of scanf() will also return EOF, so that case will be handled. Note the use of int c; — getchar() returns an int, not a character.
As mentioned in the man page, in case the matching is failure, scanf() retunes 0. IN other words, scanf() returns the number of successful matches.
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.
In case for a %d format specifier, the entered value is a char (i.e., not a match for an int) matching fails and scanf() returns 0.
So, the bottom line is, a return value of 0 here indicates, the input was improper and the scanning has failed. That also mentioned, the assignment of the value expected of scanf() has failed, leaving the possibility of usage of indeterminate value for the supplied argument.
If user gives integer then scanf will return 1 [the no of successfully scanned variable(s)] else return 0.
ALREADY AVAILABLE HERE :
Value returned by scanf function in c
Btw the code is not proper as if EOF reached then also it will show ".. not inte..." as scanf will return -1 [also != 0] .
See Value returned by scanf function in c
On success, the function returns the number of items successfully
read. This count can match the expected number of readings or fewer,
even zero, if a matching failure happens. In the case of an input
failure before any data could be successfully read, EOF is returned.
If it successfully reads the number, it returns 1. The loop will end.
If it fails to read anything (probably due to EOF), it returns EOF, which is -1. The loop will end.
If it reads something, but unable to convert it to integer, it returns 0, the loop continues.
From the man page for scanf:
Upon successful completion, these functions shall return the number of successfully matched and assigned input items
and
An input item shall be defined as the longest sequence of input bytes (up to any specified maximum field width, which may be measured in characters or bytes dependent on the conversion specifier) which is an initial subsequence of a matching sequence. The first byte, if any, after the input item shall remain unread. If the length of the input item is 0, the execution of the conversion specification shall fail; this condition is a matching failure, unless end-of-file, an encoding error, or a read error prevented input from the stream, in which case it is an input failure.
In your case, the input specifier is "%d", which Matches an optionally signed decimal integer.... So if the first character (after skipping any white space) is a numeric digit (or a +/- sign), this will convert the number (one or more digits), stopping when it sees any non-digit characters. The return value is the number of converted values, which will be 1 if it found a valid decimal number, or 0 if it didn't.
Beware that the result may not be what you expect, for example:
4-hydroxytoluene
would convert the number 4 and return 1, even though it doesn't appear to be the intent of the input. Similary 1337age, for "leetage", would convert the number 1337. I often use a code snippet like the following to avoid such cases:
char dummy;
int conversions = scanf("%d%c", &number, &dummy);
if ((conversions != 1) && ((conversion != 2) || !isspace(dummy)))
printf("Entered value is not an integer.\n");
Related
I am using the following code to scan for integers input from the user until end of line occurs.
while (scanf(" %d", &num) != EOF) {
printf("Do something")
}
This works as expected until the user inputs a string instead of an integer. The program would then endlessly keep printing Do something. Why is that happening?
How can I stop the loop only when End of line occurs, but ignore string inputs and only perform my logic if integer inputs have occured?
scanf() returns the number of input items successfully assigned. That is, in your example, 1 if a number is entered, or 0 otherwise. (Unless an input error occurs prior to the first input item, in which case it returns EOF.)
In case a string is entered, this fails to match %d, scanf() returns zero, the loop is entered, "Do something" is printed, and scanf() is called again.
But the string has not been consumed by any input function.
So the string fails to match, "Do something" is printed... you get the idea.
Be happy you do not access num, because if you haven't initialized that beforehand, accessing it would be undefined behaviour (as it still isn't initialized)...
Generally speaking, do not use scanf() on potentially malformed (user) input. By preference, read whole lines of user input with fgets() and then parse them in-memory with e.g. strtol(), strtof(), strtok() or whatever is appropriate -- this allows you to backtrack, identify exactly the point where the input failed to meet your expectations, and print meaningful error messages including the full input.
How can I stop the loop only when End of line occurs, but ignore string inputs and only perform my logic if integer inputs have occured?
When scanf(" %d", &num) returns 0, read a single character and toss it.
int count;
while ((count = scanf("%d", &num)) != EOF) {
if (count > 0) printf("Do something with %d\n", num);
else getchar();
}
I've just started to learn c programming. I don't know weather this question is silly or not.
Where do i use
while(getchar()! ='\n') ;
When using scanf function in some program the above mentioned while loop is used whereas some other program doesn't use the while loop after the scanf function.
So, where should i use this while loop and where not to?
Use the loop to clean up the rest of a line after an error
You use code similar to the loop in the question when you think there is debris left on a line of input after you (attempted to) read some data from standard input but the operation failed.
For example, if you have:
int n;
if (scanf("%d", &n) != 1)
…recover from error here?…
The error recovery should check for EOF (it is correct to use feof() here — but see while (!feof(file)) is always wrong for how not to use feof()), and if you didn't get EOF, then you probably got a letter or punctuation character instead of a digit, and the loop might be appropriate.
Note that you should always check that the scanf() operations — or any other input operation — succeeded, and the correct check for the scanf() family of functions is to ensure you got the expected number of successful conversions. It is not correct to check whether scanf() returned EOF; you can can get 0 returned when there's a letter in the input queue and you ask for a number.
Beware EOF
Incidentally, the loop in the question is not safe. It should be:
int c;
while ((c = getchar()) != EOF && c != '\n')
;
If the loop in the question gets EOF, it continues to get EOF, and isn't going to do anything useful. Always remember to deal with it. Note the use of int c; too — getchar() returns an int and not a char, despite its name. It has to return an int since it returns every valid character code and also returns a distinct value EOF, and you can't fit 257 values into an 8-bit quantity.
While loop syntax :
while (condition test)
{
// C- statements, which requires repetition.
// Increment (++) or Decrement (--) Operation.
}
while(getchar()! ='\n') ;
Here your condition is getchar()!='\n'.
First getchar() will execute . It will ask input from user. This function returns the character read as an unsigned char cast to an int or EOF on end of file or error. While loop keep continue executing until return value will not match with '\n'
scanf() example : scanf("%s", &str1);
With scanf you can ask user for enter input one time only For more than one input you have to place scanf in loop.
Where as you ask to enter input to user in while loop condition So It will keep asking input from user until EOF signal occur.
When the scanf() format string does not cause it to read the newline from the input buffer.
Most simple format specifiers will not read the newline. However if you use %c, any character may be read, including newline, in which case the loop will need modification:
while( ch != '\n' && getchar() != '\n' ) ;
Where ch is the variable receiving the %c input.
Because console input is normally line-buffered, failing to consume the newline will cause subsequent stdin reading functions to return immediately without waiting for further input, which is seldom what is intended.
You would not use such a loop in cases where multiple fields are entered in a single line but processed in separate scanf() (or other stdin function) calls.
Trying to understand the behavior of my code. I'm expecting Ctrl-D to lead to the program printing the array and exiting, however it takes 3 presses, and it enters the while loop after the second press.
#include <stdio.h>
#include <stdlib.h>
void unyon(int p, int q);
int connected(int p, int q);
int main(int argc, char *argv[]) {
int c, p, q, i, size, *ptr;
scanf("%d", &size);
ptr = malloc(size * sizeof(int));
while((c = getchar()) != EOF){
scanf("%d", &p);
scanf("%d", &q);
printf("p = %d, q = %d\n", p, q);
}
for(i = 0; i < size; ++i)
printf("%d\n", *ptr + i);
free(ptr);
return 0;
}
I read the post here, but I don't quite understand it.
How to end scanf by entering only one EOF
After reading that, I'm expecting the first Ctrl-D to clear the buffer, and then I'm expecting c = getchar() to pick up the second Ctrl-D and jump out. Instead the second Ctrl-D enters the loop and prints p and q, and it takes a third Ctrl-D to drop out.
This is made more confusing by the fact that the code below drops out on the first Ctrl-D-
#include <stdio.h>
main() {
int c, nl;
nl = 0;
while((c = getchar()) != EOF)
if (c == '\n')
++nl;
printf("%d\n", nl);
}
Let's just strip the program down to the calls which do input:
scanf("%d", &size); // Statement 1
while((c = getchar()) != EOF){ // 2
scanf("%d", &p); // 3
scanf("%d", &q); // 4
}
That is definitely not the way to go; we'll get to the correct usage in a bit. For now, let's just analyze what happens. It's important to understand precisely how scanf works. The %d format code causes it to first skip over any whitespace characters, and then read characters as long as the characters can be made into a decimal integer. Eventually some character will be read which is not part of a decimal integer; most likely a newline character. Because the format string is now finished, the unused character which has just been read will be reinserted into the stream.
So when the call to getchar is made, getchar will read and return the newline character which terminated the integer. Inside the loop, there are then two calls to scanf("%d"), each of which will behave as indicated above: skip whitespace if any, read a decimal integer, and reinsert the unused character back into the input stream.
Now, let's suppose that you run the program, and enter the number 42 followed by the enter key, and then Ctrl-D to close the input stream.
The 42 will be read by statement 1, and (as mentioned above) the newline will be read by statement 2. So when statement 3 is executed, there is no more data to be read. Because end-of-file is signaled before any digit is read, scanf will return EOF. However, the code does not test the return value of scanf; it goes on to statement 4.
What should happen at this point is that the scanf in statement 4 should immediately return EOF without attempting to read more input. That's what the C standard says should happen, and it is what Posix says should happen. Once end-of-file has been signaled on a stream, any input request should immediately return EOF until the end-of-file indicator is manually cleared. (See below for standards quotes.)
But glibc, for reasons we won't go into just yet, does not conform to the standard. It attempts another read. And so the user must enter another Ctrl-D, which will cause the scanf at statement 4 to return EOF. Again, the code does not check the return code, so it continues with the while loop and calls getchar again at statement 2. Because of the same bug, getchar does not immediately return EOF, but instead attempts to read a character from the terminal. So the user must now type a third Ctrl-D to cause getchar to return EOF. Finally, the code checks a return code, and the while loop terminates.
So that is the explanation of what is happening. Now, it is easy to see at least one mistake in the code: the return value of scanf is never checked. Not only does this mean that EOF is missed, it also means that input errors are ignored. (scanf would have returned 0 if the input could not be parsed as an integer.) That's serious, because if scanf cannot succesfully match the format code, the value of the corresponding argument is undefined and must not be used.
In short: Always check return values from *scanf. (And other I/O library functions.)
But there is a more subtle mistake as well, which makes little difference in this case but could, in general, be serious. The character read by getchar in statement 2 is simply discarded, regardless of what it was. Normally it will be whitespace, so it doesn't matter that it is discarded, but you don't actually know that because the character is discarded. Maybe it was a comma. Maybe it was a letter. Maybe it matters what it was.
It is bad style to rely on the assumption that whatever character is read by the getchar at statement 2 is unimportant. If you really need to peek at the next character, you should reinsert it into the input stream, just as scanf does:
while ((c = getchar()) != EOF) {
ungetc(c, stdin); /* Put c back into the input stream */
...
}
But actually, that test is not what you want at all. As we have already seen, it is extremely unlikely that getchar will return EOF at this point. (It's possible, but it's very unlikely). Much more more probable is that getchar will read a newline character, even though the next scanf will encounter the end-of-file. So there was absolutely no point peeking at the next character; the correct solution is to check the return code of scanf, as indicated above.
Putting that together, what you really want here is something more like:
/* No reason to use two scanf calls to read two consecutive numbers */
while ((count = scanf("%d%d", &p, &q)) == 2) {
/* Do something with p and q */
}
if (count != EOF) {
/* Invalid format. Issue an error message, at least */
}
/* Do whatever needs to be done at the end of input. */
Finally, let's examine glibc's behaviour. There is a very long-standing bug report linked to by an answer to the question cited in the OP. If you take the trouble to read through to the most recent post in the bugzilla thread, you'll find a link to a discussion on the glibc developer mailing list.
Let me give the TL;DR version, and save you the trouble of digital archaeology. Since C99, the standard has been clear that EOF is "sticky". §7.21.3/11 states that all input is performed as though successive bytes were read by fgetc:
...The byte input functions read characters from the stream as if by successive calls to the fgetc function.
And §7.21.7.1/3 states that fgetc returns EOF immediately if the stream's end-of-file indicator is set:
If the end-of-file indicator for the stream is set, or if the stream is at end-of-file, the end-of-file indicator for the stream is set and the fgetc function returns EOF. Otherwise, the fgetc function returns the next character from the input stream pointed to by stream. If a read error occurs, the error indicator for the stream is set and the fgetc function
returns EOF.
So once the end-of-file indicator is set, because either end of file was detected or some read error occurred, subsequent input operations must immediately return EOF without attempting to read from the stream. Various things can clear the end-of-file indicator, including clearerr, seek, and ungetc; once the end-of-file indicator has been cleared, the next input function call will again attempt to read from the stream.
However, it wasn't always like that. Before C99, the result of reading from a stream which had already returned EOF was unspecified. And different standard libraries chose to handle it in different ways.
So a decision was made to not change glibc to conform to the (then) new standard, but rather to maintain compatibility with certain other C libraries, notably Solaris. (A comment in the glibc source is quoted in the bug report.)
Although there is a compelling argument (at least, compelling to me) that fixing the bug is not likely to break anything important, there is still a certain reluctance to do anything about it. And so, here we are, ten years later, with a still-open bug report, and a non-conforming implementation.
If you run it through the debugger you will get a clearer picture. Here is the sequence of events.
scanf("%d", &size); is called.
A number is input followed by ENTER. The key here is that scanf does not consume the \n that results from the ENTER.
getchar is called. This consumes the \n.
scanf("%d", &p); is called. This consumes the first ctrl-D. If the return value were checked then it would be apparent that an error occured.
scanf("%d", &q); is called. This consumes the second ctrl-D.
Loop goes back to the top and calls getchar. The third ctrl-D then causes EOF to be returned by getchar and hence the loop breaks out at that point.
I'll leave it as an exercise for you to explain why the second program functions as expected.
There are different things messing here.
First of all, when you type Ctrl-D to the input terminal, the tty driver is processing your input, adding each character in a buffer and processing special characters. One of these special characters (Ctrl-D) means take up to the last char and make them all available to the system. This makes two things to happen: first, the Ctrl-D character is eliminated from the data stream and; second, all the characters typed up so far are made available to be read(2) by the process syscall. getchar() is a buffered library call that avoids making one read per character, allowing to store previously read characters in the buffer.
Other thing messing here is the way the system signals the end of file in posix systems (and all unix systems). When you make a read(2) system call, the return value is the actual number of characters read (or -1 in case of failure, but this has nothing to do with EOF, as will be explained soon). And the system marks the end of file condition by returning 0 characters. So, the operating system marks the end of file making read(2) return 0 bytes as a result (if you only hit the return key, that will make a \n to appear in the data stream).
The third thing messing up here is the type of return value from getchar(3) function. It doesn't return a char value. As all possible byte values are posible to be returned for getchar(3), there's no possibility to reserve a special value for signalling a EOF. The solution adopted a long, long, time ago (when getchar(3) was designed, that is in the first version of the C language, (see The C programming language by Brian Kernighan and Denis Ritchie, first ed.) was to use an int as return value to be able to return all the possible byte values (0..255) plus one extra value, called EOF. The exact value of EOF is implementation dependant, but normally defined as -1 (I think even the standard specifies now it must be defined as -1, but not sure)
So, making all things work together, EOF is an int constant defined to allow programers to write while ((c = getchar()) != EOF). You will never get -1 as a data value from the terminal. The system always marks the end of file condition by making read(2) to return 0. And the terminal driver on receiving Ctrl-D just eliminates it from the stream and makes data up to, but not including (as different from Ctrl-J or Ctrl-M, line feed and carry return, respectivelly, that are also interpreted and are input as \n in the data stream)
So, next the question is: Why there are needed normally two (or more) Ctrl-D chars to signal eof?
Right, as I've said, one only makes all thata up to the Ctrl-D (but not including it) available to the kernel, so the result from read(2) can be a number different than 0 for the first time. But what is sure is that if you enter the Ctrl-D char twice in sequence, after the first there were not be more chars in between the two chars, assuring a read() of zero chars. Normally, programs are in a loop, doing multiple reads
while ((n_read = read(fd, buffer, sizeof buffer)) > 0) {
/* NORMAL INPUT PROCESSING GOES HERE, for up to n_read bytes
* stored in buffer */
} /* while */
if (n_read < 0) {
/* ERROR PROCESSING GOES HERE */
} else {
/* EOF PROCESSING GOES HERE */
} /* if */
In the case of files, the behaviour is different, as Ctrl-D is not interpreted by any driver (it's stored in the disk file) so you'll get Ctrl-D as a normal character (it's value is \004)
When you read a file, normally this deals to reading a lot of complete buffers, then make a partial read (with less than the buffer size bytes input) and a final read of zero bytes, signalling that the file has ended.
Note
Depending on the configuration of the tty driver in some unices, the eof character can be changed and have different mean. Also happens to the return character and linefeed character. Se termios(3) manual page for a detailed documentation on this.
I am working on a code, and I tried to enter a char instead of integer, and the result was '2' regardless of the character I entered, is it undefined behaviour or some thing else ?
The code:
#include <stdio.h>
int f1(int n);
int f2(void);
int main(void)
{
int t;
printf("Enter a number: ");
scanf("%d", &t);
/* print proper message */
t ? f1(t) + f2() : printf("zero entered.\n");
return 0;
}
int f1(int n)
{
printf("%d ", n);
return 0;
}
int f2(void)
{
printf("entered.\n");
return 0;
}
when I entered a, the result was "2 entered", and when I entered g the result was "2 entered" and when I entered i,h,k,..... the result was the same. What is that?
If scanf() encounters something it cannot parse based on the specified format string, it simply stops and returns early. So it never writes anything to t (you're just seeing whatever indeterminate value t had before the call).
To handle this, you should always examine the return value of scanf.
It is because scanf failed to parse you input. It expects you to enter a decimal digits since you used %d.
You have to check the return value of scanf to avoid this kind of behavior :
On success, the function returns the number of items of the argument list successfully filled. This count can match the expected number of items or be less (even zero) due to a matching failure, a reading error, or the reach of the end-of-file.
So :
int items_matched;
// ...
items_matched = scanf("%d", &t); // Get the return value
if ( items_matched != 1 ) // Check it
{
printf("Matching failure with scanf.\n");
return 0;
}
else
{
if ( t == 0 )
printf("zero entered\n");
else
printf("%d entered\n", t);
}
You don't need your f1(t) + f2() who is quite confusing...
The problem is, as you say, that scanf using %d format is expecting you to enter one or more ascii digits. It stops scanning the input at a non-digit character, so it never reads what you type and t has whatever value it had before the scant was called.
You need to check the return code of scanf. Have a look at the manpage:
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.
In other words, scanf does not write anything into t, it's uninitialized the whole time.
So, instead of this:
scanf("%d", &t);
try this:
int items_matched = scanf("%d", &t);
if (items_matched != 1) {
printf("bad number entered\n");
exit(1);
}
From the Linux man page
The format string consists of a sequence of directives which describe
how to process the sequence of input characters. If processing of a
directive fails, no further input is read, and scanf() returns. A
"failure" can be either of the following: input failure, meaning that
input characters were unavailable, or matching failure, meaning that
the input was inappropriate.
In the C11 standard description of scanf (7.21.6.4 The scanf function) section 3:
The scanf function returns the value of the macro EOF if an input
failure occurs before the first conversion (if any) has completed.
Otherwise, the scanf 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.
Emphasis is mine . So as #oli charlesworth said you should check the return value of scanf when in doubt :)
I want to confirm if a value returned from the scanf() function is a floating number or not. How can I do that? My code is not running as it should if the wrong data types are supplied to the scanf() function. Similarly, how would I confirm if a value returned is a character string or not?
scanf() et al return the number of successful conversions.
If you have:
scanf("%f", &f);
you should test:
if (scanf("%f", &f) == 1)
...all OK...
else
...EOF or conversion failure...
If you have several conversions, check that they all completed. If you're using %n 'conversions', they aren't counted.
Although scanf() does return EOF on EOF, you should not test for that — you should always check primarily that you got the number of conversions you expected. For example, consider the buggy code:
while (scanf("%f %d %s", &f, &i, s) != EOF) // Here be BUGS!
...loop body...
If you type 3.14 x23 yes, then you will have an infinite loop because scanf() will return 1 on the first iteration (it successfully converted 3.14), and 0 thereafter (not EOF).
You might be OK with:
while ((rc = scanf("%f %d %s", &f, &i, s)) != EOF)
{
if (rc != 3)
...oops data problems...
else
...all OK...
}
Judging from previous questions, you should be looking at using fgets() (or possibly POSIX getline()) to read lines of data, and then using sscanf() or even functions like strtol() and strtod() to read particular values from the line. If you use sscanf(), the comments made above about checking the number of successful conversions still apply.
I don't use scanf() in production code; it is just too damn hard to control properly. I regard it as almost suitable for beginning programs — except that it causes lots of confusion. On the whole, the best advice is 'stay clear of scanf() and fscanf()'. Note that that does not mean you have to stay clear of sscanf(), though some caution is needed even with sscanf().
The return value of scanf indicates the number of items successfully read and assigned to your variables, or EOF:
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.
If the int returned by scanf has a value less than the amount of input specifiers (or at least the specifiers which require an argument to be passed) in the format string, then you can assume something went wrong.
However, if you want to perform a more thorough validation of your floating point number, then you should consider using strtod(). ie. for the input "1.23abc", scanf would store 1.23 into your variable and tell you that everything went well, but with strtod you can check if the last character converted is actually the end of the string being parsed.