Testing getchar() == EOF doesn't work as expected - c

I have an assignment to "Write a C program that allows a user to enter up to 20 integers (it will stop accepting numbers based on a sentinel value or based on the 20-integer limit being reached). The program should then display the numbers in the reverse order of entry."
I decided to make my sentinel value "EOF" (or CTRL+D / CRTL+Z). My code has some really erratic behavior:
You have to press the EOF keys twice (which also creates a blank entry that is counted int the array.
The first digit from the first entry gets truncated.
Everything else seems to work OK but, this is clearly not the desired results. Below is my code. Can you explain what's wrong?
main() {
int i,iMax;
double dblMean;
int x[MAX];
printf("Please Enter Up to 20 Integers\n");
for (i=0; i<MAX; i++)
{
printf("%d.> ",i+1);
if (getchar() == EOF) /* Check for CTRL+D OR CTRL+Z */
break; /* Exit loop if EOF entered :: Must be pressed twice and eats first character of first entry */
scanf("%d",&x[i]);
iMax=i;
}
printf("\nYou entered %d numbers\n",iMax+1); /* Should be i+1 but EOF had to be entered twice */
printf("\nIndex Item Reverse Item\n");
for (i=0; i<=iMax; i++)
printf("%3d%4c%8d%9c%11d\n",i,' ',x[i],' ',x[iMax-i]);
return 0;
}
EDITED:
Here is my final code, Thank you all for your help:
#include <stdio.h>
#include <stdlib.h>
#define MAX 20
int main()
{
int i,iMax;
int x[MAX];
printf("Please Enter Up to 20 Integers\n");
for (i=0; i<MAX; i++)
{
printf("%d.> ",i+1);
if (scanf("%d",&x[i]) != 1) /* Checks for CTRL+D OR CTRL+Z */
break; /* EOF returns -1 and loop will be exited */
iMax=i; /* iMax must be set for second loop to exit properly */
/* Can sizeof x be used instead for second loop? */
}
printf("\nYou entered %d numbers\n",iMax+1); /* Displays number of items entered... Will be <= MAX*/
printf("\nIndex Item Reverse Item\n");
for (i=0; i<=iMax; i++) /* Why wont 'for (i=0; i<=sizeof x; i++)' work? */
printf("%3d%4c%8d%9c%11d\n",i,' ',x[i],' ',x[iMax-i]);
return 0;
}

The getchar() call reads (and effectively discards) the first digit because it is not EOF.
You don't test that scanf() worked; you should.
for (i = 0; i < MAX; i++)
{
if (scanf("%d", &x[i]) != 1)
break;
}
At this point, there are i integers in the array; you don't really need to set iMax in the loop. You could simply set it when the loop exits.

Also, in addition to checking scanf, here is what you need to know:-
EOF is not a character. The EOF is a macro that getchar() returns when it reaches the end of input or encounters some kind of error. The ^D is not "an EOF character". What's happening under linux when you hit ^D on a line by itself is that it closes the stream, and the getchar() call reaches the end of input and returns the EOF macro. If you type ^D somewhere in the middle of a line, the stream isn't closed, so getchar() returns values that it read and your loop doesn't exit.
see http://www.c-faq.com/stdio/getcharc.html for a nice description.

Related

C lang: Turbo C, DOS, Input = 4. Output =$ $$ $$$ $$$$. Going infinite loop for char input. S

User gives input and accordingly the pattern must be printed. It should encounter negative numbers and char as input. I encounterd the negative value as input but as I try to give char input it goes on ifinite loop. So how can I encounter char value for int data type as an input.
#include<stdio.h>
#include<conio.h>
/*
C program to print the pattern allowing user
to input the no. of lines.
*/
//Declaring method for printing pattern
void printPattern(int numberOfLines);
void main()
{
char userChoice;//User's choice to continue or exit
int numberOfLines;//User's input for number line to be printed
clrscr();
//Logic for printing the pattern
do
{
printf("Enter the number of lines you want to print \n");
scanf("%d",&numberOfLines);
//Countering issue if user enters a char insted of number
/*while()
{
printf("Enter number only \n");
scanf(" %c",&numberOfLines);
}*/
//Countering issue if user enters negative number
while(numberOfLines<=0)
{
printf("Enter positive number \n");
scanf("%d",&numberOfLines);
}
//Calling method to the start printing of method
printPattern(numberOfLines);
//Taking user's choice to continue or not
printf("Press Y to continue else any other key to exit \n");
scanf(" %c",&userChoice);
}
while(userChoice == 'y' || userChoice == 'Y');
}
/*
Method definition for printing the pattern
Argument numberOfLines: User's input for number of lines
*/
void printPattern(int numberOfLines)
{
int i,j;
for(i=0 ; i<numberOfLines ; i++) //for rows
{
for(j=0 ; j<=i ; j++) //for columns
{
printf("$");
}
printf("\n"); //for going to next row after printing one
}
}```
When you do scanf("%d",&numberOfLines); you want to read an integer. If you then enter a letter, like an a, nothing will be read from the input stream. In other words, you'll go into an endless loop where you keep trying to read an integer but the stream contains a letter.
You need to remove that letter from the stream.
You could try:
while(scanf("%d",&numberOfLines) != 1)
{
// Didn't get an integer so remove a char
getchar();
}
However, that will lead to problems if the input stream fails.
The better solution is to use fgets and sscanf
Here is a shorter, simpler version of printPattern
void printPattern(int n)
{
char dollar[n];
memset(dollar, '$', n);
for(int i = 1; i <= n; ++i)
printf("%.*s\n", i, dollar);
}

how to use EOF as prime read in cc

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.

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");
}
}
}

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);
}

The fgets function doesnt save the first letter in the string

I've wrote a program that gets from the user a number, and then gets from the user a name for every number...
for example if the user entered the number 10, it'd take 10 names and put it in an array of structs...
Everything is working great, except that when I print the names, it skip'd the first letter...
like if I put in the name "Amit", it printed "mit"... , also, the last string I've entered didnt save at all..
Here is what I wrote :
const number_candidates; // Getting the number of candidates
#define MAX 256
#define min_candidate 10
#define max_candidate 60000
typedef struct candidate // Getting details for each candidate
{
char name[MAX];
int sing_grade;
int per_grade;
int cam_grade;
int sharmanti_grade;
}candidate;
void get_details_candidates(candidate candidate[MAX])
{
int i = 0;
printf ("\n");
for (i = 0 ; i < number_candidates ; i++)
{
printf ("Please enter the %d name: ", i + 1);
fgets (candidate[i].name, MAX, stdin);
getchar();
}
}
Here is the printing:
for (i = 0 ; i < number_candidates ; i++)
{
printf ("%s\n", candidates[i].name);
}
Thanks for your help!
Why do have the getchar() after the fgets()? I think that is your culprit.
The getchar() after the fgets() is eating the first letter of the following line.
Your problem reading the first name may be caused by a stray newline in the input stream. To flush stdin before your input loop you can use something like this:
while((c = getchar()) != '\n' && c != EOF)
/* discard the character */;
I think fflush(stdin) is undefined behaviour so don't do that.

Resources