how to use EOF as prime read in cc - c

why the while loop starts executing infinite if I enter any alphabet and when I enter any number it executes only once.
Scanf("%d",&a) function returns 1 for any number and 0 for any character or string. As I know EOF is not equal to 1 and 0.
#include<stdio.h>
int main
{
int a;
while(scanf("%d",&a) != EOF)
{
printf("hi devender \n");
}
return 0;
}

// input buffer==> 42foo\n
scanf("%d", &a); // returns 1 (not EOF), a is now 42
// input buffer==> foo\n
scanf("%d", &a); // returns 0 (not EOF), see comments about a
// input buffer==> foo\n // no change
scanf("%d", &a); // returns 0 (not EOF)
// input buffer==> foo\n // no change
scanf("%d", &a); // returns 0 (not EOF)
// input buffer==> foo\n // no change
... ... infinite loop
In short, don't compare the return value from scanf() with EOF; compare with the number of expected assignments.
if (scanf("%d%s%d%d", &a, name, &b, &c) != 4) /* error */;

Per the scanf() man page (bolding mine):
RETURN VALUE
On success, these functions return the number of input items
successfully matched and assigned; this can be fewer than provided
for, or even zero, in the event of an early matching failure.
If you don't enter a number, you get a matching failure and scanf() returns zero.

I don't know what you are trying to do, but to understand that the problem with the infinite loop is that the buffer is not empty, try this code.
include
int main(void)
{
int a,c;
while(scanf("%d",&a) !=EOF)
{
printf("hi devender \n");
while ( ( c = getchar() ) != EOF && c != '\n' ) ; //empty the buffer
}
printf("Finished");
return 0;
}

why the while loop starts executing infinite if I enter any alphabet
scanf("%d",&a) function returns 1 for any number and 0 for any character or string. As I know EOF is not equal to 1 and 0
It appears the key issues for OP is that on a matching failure, the text in stdin is not consumed. So once an "abc\n" is entered. the 'a' and the rest, remain in stdin until some other input function reads it. As code lacks other ways to read data, we have an infinite loop.
A common work-around it to read the offending character
#include<stdio.h>
int main() {
int scan_count;
int a;
while((scan_count = scanf("%d",&a)) != EOF) {
if (scan_count == 0) {
getchar();
}
printf("hi devender \n");
}
return 0;
}
Or as others suggest, consume to the end of the line of input.

Related

Wanted to check if the value entered is a number or else. "isdigit() is not working here as expected

I am stuck with a problem here in C. I am posting the question and the code I have written below. Here I have to enter 10 numbers in an array and then I need to check how many times a number appeared. But to verify that I have entered a number and not anything else, I have used "isdigit()" function. But this is of no use. Can anyone help me to solve it.
/*
(a) Ten numbers are entered from the keyboard into an array. The number to be searched is entered through the
keyboard by the user. Write a program to find if the number to be searched is present in the array and if it is present, display
the number of times it appears in the array.
*/
#include<stdio.h>
#include<ctype.h>
main()
{
int num[10];
int i, j, cnt=0;
char rept;
printf("Enter 10 numbers: \n\n");
for(i=0; i<=9; i++)
{
printf("Number %d = ", i+1);
scanf("%d", &num[i]);
fflush(stdin);
if ( !isdigit(num[i]) )
{
printf("OK\n");
}
else
{
printf("Invalid number. Enter again.\n");
i=i-1;
}
}
do
{
printf("\nEnter the number to be searched in array: ");
scanf(" %d", &j);
for (i=0 ; i<=24; i++)
{
if(num[i]==j)
cnt++;
}
if(cnt>0)
printf("\nNumber %d is present at %d places", j, cnt);
else
printf("\nNumber not present.");
printf("\n\nDo you want to search another number. Press Y to repeat. Any other key to exit");
fflush(stdin);
scanf("%c", &rept);
}while (rept=='y'||rept=='Y');
getch();
}
No you can't do that. isdigit() is supposed to work with characters and you passed a multigit integer variable.
What you can do is simply like this
if( scanf("%d",&a[i])== 1){
// you can be sure number is entered
}
And fflush(stdin) is undefined behavior.
So the use of scanf will be more prominent if you would do this
int clearstdin(){
int c;
while ((c = getchar()) != '\n' && c != EOF);
return (c == EOF);
}
In main()
int earlyend = 0;
for(size_t i=0; i<SIZE; i++){
...
...
int ret = scanf("%d",&a[i]);
while( ret == 0){
if( clearstdin() ){ /* EOF found */earlyend = 1; break; }
fprintf(stderr,"%s\n","Entered something wrong");
ret = scanf("%d",&a[i]);
}
if( earlyend ){ /*EOF found*/ }
if( ret == EOF) { /* Error occured */}
...
}
The %d conversion specifier will cause scanf to skip over any leading whitespace, then read a sequence of decimal digits, stopping at the first non-digit character. If there are no digit characters in the input (for example, you enter something like ”abc”), then nothing is read from the input stream, a[i] is not updated, and scanf will return 0 to indicate a matching failure.
So, you can do a test like
if ( scanf( “%d”, &a[i] ) == 1 )
{
// user entered valid input
}
But...
This doesn’t fully protect you from bad input. Suppose you enter something like ”123abc” - scanf will read, convert, and assign 123 and return a 1 indicating success, leaving ”abc” in the input stream to potentially foul up the next read.
Ideally, you’d like to reject the whole thing outright. Personally, I do this as follows:
char inbuf[SOME_SIZE]; // buffer to store input
if ( fgets( inbuf, sizeof inbuf, stdin ) ) // read input as text
{
char *chk; // use strtol to convert text to integer
int temp = (int) strtol( inbuf, &chk, 10 ); // first non-digit character written to chk
if ( isspace( *chk ) || *chk == 0 ) // if chk is whitespace or 0, input is valid
{
a[i] = temp;
}
else
{
// bad input
}
}
This still isn’t a 100% solution - it doesn’t make sure the user didn’t enter more characters than the buffer can hold, but it’s a step in the right direction.
Input validation in C is, frankly, a pain in the ass.

How to accept ";' semicolon, as input, and not execute the next line of codes?

Here's a small portion of a practice I'm doing preventing erroneous inputs.
while(1) {
printf("Choose From 1 to 7 ");
if( scanf("%d", &nNum ) != 1) {
printf("Please only choose from the numbers 1-7.");
fgets(sErraticInputs, 100 , stdin);
} else if (nNum > 7 || nNum <= 0) {
printf("Please only choose from the numbers 1-7.");
} else {
break;
}
}
I was doing a good job, until I entered "6;p". It executed the 6 portion and ran correctly, but technically speaking it should have taken the whole thing as the input, and proceeded with the error message.
First of all I don't think the posted code can give the said result. The break statement will end the while(1) when 6 has been read so there will not be printed an error message.
If we assume that the break isn't part of your real code this is what happens:
When scanf is told to read an integer, it will continue reading from the input stream as long as the next character (together with the previous read characters) can be converted into an integer. As soon as the next character can not be used as part of an integer, scanf will stop and give you the result of what it has parsed so far.
In your case the input stream contains
6;p\n
So scanf will read the 6 and stop (i.e. return 6). The input stream now contains:
;p\n
Consequently this will be the input for your next scanf and cause the input error, you saw.
One way to solve this would be to flush stdin after all scanf - both on success and on failure:
nNum = 0;
while(nNum != 7) // Just as an example I use input 7 to terminate the loop
{
printf("Choose From 1 to 7 ");
if( scanf("%d", &nNum ) != 1 || nNum > 7 || nNum <= 0)
{
printf("Please only choose from the numbers 1-7.");
}
else
{
printf("Valid input %d\n", nNum);
// **************************** break;
}
fgets(sErraticInputs, 100 , stdin); // Always empty stdin
}
note: Using fgets with size 100 doesn't really ensure a complete flush... you should actually use a loop and continue until a '\n' is read.
With the change above input like 6;p will be taken as a valid input with value 6 and the ;p will be thrown away.
If that's not acceptable, you could drop the use of scanf and do the parsing yourself. There are several options, e.g. fgets or fgetc
The example below uses fgetc
#include <stdio.h>
#include <stdlib.h>
int get_next()
{
int in = fgetc(stdin);
if (in == EOF) exit(1); // Input error
return in;
}
void empty_stdin()
{
while(get_next() != '\n') {};
}
int main(void) {
int in;
int nNum = 0;
while(nNum != 7)
{
printf("Choose From 1 to 7 \n");
in = get_next();
if (in == '\n' || in <= '0' || in > '7') // First input must be 1..7
{
printf("Please only choose from the numbers 1-7.\n");
if (in != '\n') empty_stdin();
}
else
{
nNum = in - '0';
in = get_next();
if (in != '\n') // Second input must be \n
{
printf("Please only choose from the numbers 1-7.\n");
empty_stdin();
}
else
{
printf("Valid input: %d\n", nNum);
}
}
}
return 0;
}
This code will only accept a number (1..7) followed by a newline
Here's why the "whole thing" is not taken as the input. From the man pages:
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...
Here's the full text. Have a look at this as well.
One approach would be to read in the whole input using fgets and check whether the length of the input is greater than 1. For an input of length 1, check if the input is a number and so on...

Error check for character when reading in integers in C

For my programming class I've written a program to calculate the sum of divisors. So I've gotten to my final part which is error checking, which I am having a problem with if I read a character in. I have searched on S.O. earlier,as well as tried to figure something out, and couldn't find a solution that works for endless negative numbers until 100.
When I hit a character it sets it to 0 and just goes to the end, where I want it to exit once it reads it in
int main (void){
int userIN=0;
int i = 0;
int next = 0;
int temp= 105;
int cycle;
puts("Enter up to 10 integers less than or equal to 100");
while(scanf("%d ", &userIN) !=EOF && (i < 10))
{
if(userIN > 100){
printf("Invalid Input\n");
exit(1);
}
else if(userIN < 100)
{
Thanks for the help in advance
EDIT: The program is cycling through correctly, My Issue is error checking for a character being entered not anything with the code itself
scanf() returns a value other than EOF if it cannot read the values specified by the format string (e.g. with %d, it encounters data like foo). You can check for that. The caveat is that it does not read the offending data from stdin, so it will still be there to affect the next call of scanf() - which can result in an infinite loop (scanf() reporting an error, call scanf() again, it encounters the same input so reports the same error).
You are probably better off reading a whole line of input, using fgets(). Then check the input manually or use sscanf() (note the additional s in the name). The advantage of such an approach is that it is easier to avoid an infinite loop on unexpected user input.
You could loop while i is less than 10. The first if will see if scanf failed. If so the input buffer is cleared and the while loop tries again. If EOF is captured, then exit. If scanf is successful, the input is compared to 100 and if in range, the while loop counter is incremented.
Declare int ch = 0;
while ( i < 10) {
printf("Enter %d of 10 integers. (less than or equal to 100)\n", i + 1);
if(scanf(" %d", &userIN) != 1)
{
while ( ( ch = getchar()) != '\n' && ch != EOF) {
//clear input buffer
}
if ( ch == EOF) {
exit ( 1);
}
}
else {
if(userIN > 100){
printf("Invalid Input\n");
}
else
{
i++;// good input advance to the next input
printf("Valid");
}
}
}

C-programming loop wont stop with scanf!=0

What is wrong with this ? Also, I have to use scanf(). It is supposed to read any integers and sum them, the loop is to stop when 0 is entered..
main (void){
int a;
int r=0;
while(scanf(" %d",&a)){
r=r+a;
}
printf("the sum is %d\n",r);
return 0;
}
Quoting from man
These functions return the number of input items assigned. This
can be
fewer than provided for, or even zero, in the event of a matching fail-
ure. Zero indicates that, although there was input available, no conver-
sions were assigned; typically this is due to an invalid input character,
such as an alphabetic character for a `%d' conversion.
The value EOF is
returned if an input failure occurs before any conversion such as an end-
of-file occurs. If an error or end-of-file occurs after conversion has
begun, the number of conversions which were successfully completed is
returned.
So, that pretty much explains what is returned by scanf().
You can solve the problem by adding ( 1 == scanf("%d", &a) && a != 0 ) as the condition in your while loop like
int main (void)
{
int a;
int r=0;
while( 1 == scanf("%d", &a) && a != 0 )
{
r=r+a;
}
printf("the sum is %d\n",r);
return 0;
}
Also note that you have to specify the type of main as int main().
I would also like to add that the loop will end when you enter a character like 'c' ( or a string ) and it will show the sum of all the numbers you entered before entering the character.
scanf() doesn't return what it has written to the variable. It returns the total number of items successfully filled.
EDIT:
You would be much better off using fgets() to read from stdin and then using sscanf() to get the integer, which you can check against 0.
#define BUFF_SIZE 1024
int main (void)
{
int a;
int r = 0;
char buffer[BUFF_SIZE] = {0};
while(1) {
fgets(buffer, sizeof buffer, stdin);
sscanf(buffer, "%d", &a);
if(!a)
break;
r = r + a;
}
printf("the sum is %d\n", r);
return 0;
}

How to allow user to exit while loop from terminal?

For example, if I want to write a code to average an unspecified number of numbers that the user enters, how can I make it so that the user can determine the number of numbers? ie. if the user wants to average just three numbers, he types them in one at a time, and then types in something to signal that this is it.
I wrote something like
while(i!=EOF){
printf("type in a number: \n");
scanf("%f",&i);
array[x]=i;
x++;
}
"and then some code to average the numbers in the array".
The idea was that if the user wants to signal that he finished entering numbers, he types in EOF and then the while loop will stop, however this isn't working. When I type in EOF at the terminal, it just writes "type in a number:" indefinitely.
scanf returns information in two different ways: in the variable i, and as its return value. The content of the variable i is the number that scanf reads, if it is able to return a number. The return value from scanf indicates whether it was able to read a number.
Your test i != EOF is fundamentally a type error: you're comparing the error indicator value EOF to a variable designed to hold a floating-point number. The compiler doesn't complain because that is accidentally valid C code: EOF is encoded as an integer value, and that value is converted to a floating-point value to perform the comparison. In fact, you'll notice that if you enter -1 at the prompt, the loop will terminate. -1 is the value of the EOF constant (on most implementations).
You should store the return value of scanf, and store it into a separate variable. If the return value is EOF, terminate the loop. If the return value is 1, you have successfully read a floating-point value.
If the return value is 0, the user typed something that couldn't be parsed. You need to handle this case appropriately: if you do nothing, the user's input is not discarded and your program will loop forever. Two choices that make sense are to discard one character, or the whole line (I'll do the latter).
double i;
double array[42];
int x = 0;
int r = 0;
while (r != EOF) {
printf("type in a number: \n");
r = scanf("%f", &i);
if (r == 1) {
/* Read a number successfully */
array[x] = i;
x++;
} else if (r == 0) {
printf("Invalid number, try again.\n");
scanf("%*[^\n]"); /* Discard all characters until the next newline */
}
}
You should also check that x doesn't overflow the bounds of the array. I am leaving this as an exercise.
I want to do it by typing in something that's not a number
Then get the input as a string, and exit if it cannot be converted to a number.
char buf[0x80];
do {
fgets(buf, sizeof(buf), stdin);
if (isdigit(buf[0])) {
array[x++] = strtod(buf);
}
} while(isdigit(buf[0]);
In case of no input scanf() does not set i to EOF but rather can return EOF. So you should analyze scanf() return code. By the way you can receive 0 as result which actually means there is no EOF but number cannot be read.
Here is example for you:
#include <stdio.h>
#define MAX_SIZE 5
int main()
{
int array[MAX_SIZE];
int x = 0;
int r = 0;
while (x < MAX_SIZE)
{
int i = 0;
printf("type in a number: \n");
r = scanf("%d",&i);
if (r == 0)
{
printf("ERROR!\n");
break;
}
if (r == EOF)
{
printf("EOF!\n");
break;
}
array[x]=i;
x++;
}
}
You cannot write 'EOF'.. since you are reading into a number...
EOF equals -1.. so if he enterd that, the loop would stop
You can test for the return value of the scanf function. It returns EOF on matching failure or encountering an EOF character.
printf("type in a number:" \n);
while(scanf("%f",&i)!=EOF){
array[x]=i;
x++;
printf("type in a number:" \n);
}

Resources