My program is using while scanf != EOF to input standard inputs from a .in file. as in ./"file" < file.in The problem is that I have to scanf from the terminal after that. Is there a way I can invoke EOF to the stdin so that the file stops scanning from file.in or maybe specify scanf to read from the terminal and not the file. I'm also only allowed to use scanf as this is a college assignment. This is a mock program of my issue. Thanks
int main() {
int arr[100];
int num;
int count = 0;
while( scanf("%d", &arr[count]) != EOF ) {
count++;
}
printf("%d\n", arr[0]);
scanf("%d", &num);
printf("%d\n", num);
}
** Output is just the number of the first list of number, and scanf is completely ignored with no value in print num.
To invoke/simulate EOF in stdin , press CTRL+Z if you are in windows. Else press CTRL+D when running the program.
scanf() return number of read chars.
you need feof() function, or compare returned value from scanf with 0
Related
I need to read all integers until the EOF. I'm trying this code and the problem is that the program doesn't detect the EOF and keeps running. What I need is to receive all the data and proceed to the next line of code automatically (the code works with pressing Ctrl-D after the input).
int x, sum = 0;
while (scanf("%d", &x) == 1) {
sum += x;
}
if (feof(stdin)) {
printf ( "SUM: %d\n", sum );
} else {
printf("ERROR\n");
}
return 0;
How do you want to specify EOF?
^D is the way to do it in the terminal in Unix. In the Windows terminal, ^Z does the same thing. scanf will return -1 and feof() will be non zero. But any further input from stdin will fail too.
Do you want to just hit the enter key? If so, you have to check for that after scanf, otherwise the next call to scanf will read the linefeed and ignore it.
If you type something that is neither white space nor a number, scanf will return 0 and leave the unmatched character in the input stream. Your program will print ERROR. Is this what is happening?
The code is supposed to accept a line of user input containing different characters and then print out one line containing only the letters. For example, Cat8h08er64832&*^ine would be Catherine. However, the code works and outputs "Catherine" however the program doesn't exit... see picture here I'm not sure if the loop is just looping infinitely or...
int main(void){
int i=0, j=0;
char userString[1000];
char alphabet[1000];
printf("Please enter a string: ");
while(scanf("%c", &userString[i])){
if((userString[i]>='A' && userString[i]<='Z')||(userString[i]>='a'&&userString[i]<='z')){
alphabet[j]=userString[i];
printf("%c", alphabet[j]);
j++;
}
i++;
}
printf("\n");
return 0;
}
Your problem is that you're checking that scanf is finished by checking for the return value 0. scanf returns EOF (usually, -1) when there is no more input. So if you get some input (return 1) then no more input (return -1), your loop won't ever exit.
Change the scanf condition to check for <> EOF.
This answer also explains it quite well.
This question already has answers here:
Why is scanf() causing infinite loop in this code?
(16 answers)
Closed 9 years ago.
In line 5 I read an integer and isint is getting 1 if it reads an integer or 0 if it's not an integer. If isint is 0 I have a loop asking user to give an integer and I read until the user gives an integer. I try this code giving a character instead of an integer but I have an infinite loop. The program just doesn't wait to give a new input. What's wrong with my code?
#include <stdio.h>
int main(void) {
int arg1;
//int arg2;
int attacknum = 1;
int isint = 1;
//printf("Insert argument attacks and press 0 when you have done this.\n");
printf("Attack %d\n", attacknum);
attacknum++;
printf("Give attacking argument:");
isint = scanf("%d", &arg1); //line 5
while(isint == 0){
printf("You did not enter a number. Please enter an argument's number\n");
isint = scanf("%d", &arg1);
printf("is int is %d\n", isint);
}
return 0;
}
As others have mentioned, if scanf can't parse the input, it leaves it unscanned.
Generally scanf is a poor choice for interactive input because of this kind of behavior, and because it doesn't match the line-at-a-time interface experienced by the user.
You are better off reading one line into a buffer using fgets. Then parse that line using sscanf. If you don't like the input, throw the whole line away and read another one.
Something like this:
#include <stdio.h>
int main(void)
{
char line[256];
int arg1;
int isint;
while (1) {
printf("Give attacking argument:");
fgets(line, sizeof line, stdin);
isint = sscanf(line, "%d",&arg1);
if (isint) break;
printf("You did not enter a number.Please enter an argument's number\n");
}
printf("Thanks for entering %d\n", arg1);
return 0;
}
(For production code you'll want to handle long lines, check return codes, also check for trailing garbage after the number, etc.)
Actually, an even better approach would be to not use scanf if you just want to read an integer, and instead use strtol. That gives you a handy pointer to the character just after the number, and you can check that it's whitespace or nul.
When scanf is confronted with a non-digit it will not consume any input and return that zero integers were read. The non-digit will stay in the input for the next call to scanf that will behave the same as the first call, etc.
In answer to your question below. You could use fgetc to parse at least one character, but this will give the error messages for every character already typed. Typically I think you want to skip until a newline. To this end you could use fgets as suggested by poolie. Or you could add the following after scanf.
int ch;
if (isint == 0)
while ((ch = fgetc(stdin)) != EOF && ch != '\n')
{
/* Skip characters */
}
P.S: In your case it is probably better to put it just before the first printf in the loop.
I have a difficulty understanding getchar(). In the following program getchar works as expected:
#include <stdio.h>
int main()
{
printf("Type Enter to continue...");
getchar();
return 0;
}
However, in the following program, getchar does not create a delay and the program ends:
#include <stdio.h>
int main()
{
char command[100];
scanf("%s", command );
printf("Type Enter to continue...");
getchar();
return 0;
}
I have the following weired workaround, which works, but I don't understand why:
#include <stdio.h>
int main()
{
char command[100];
int i;
scanf("%s", command );
printf("Type Enter to continue...");
while ( getchar() != '\n') {
i=0;
}
getchar();
return 0;
}
So my questions are:
1. What is scanf doing? Why does scanf do this ?
2. Why is my work around working?
3. What is a good way to emulate the following Python code:
raw_input("Type Enter to continue")
The input is only sent to the program after you typed a newline, but
scanf("%s", command );
leaves the newline in the input buffer, since the %s(1) format stops when the first whitespace character is encountered after some non-whitespace, getchar() then returns that newline immediately and doesn't need to wait for further input.
Your workaround works because it clears the newline from the input buffer before calling getchar() once more.
To emulate the behaviour, clear the input buffer before printing the message,
scanf("%s", command);
int c;
do {
c = getchar();
}while(c != '\n' && c != EOF);
if (c == EOF) {
// input stream ended, do something about it, exit perhaps
} else {
printf("Type Enter to continue\n");
getchar();
}
(1) Note that using %s in scanf is very unsafe, you should restrict the input to what your buffer can hold with a field-width, scanf("%99s", command) will read at most 99 (sizeof(command) - 1)) characters into command, leaving space for the 0-terminator.
Whitespace is a delimiter for 5y3 %s format specifier, and newline is regarded as whitespace, so it remains buffered. Console input is normally line oriented, so a subsequent call to getchar() will return immediately because a 'line' remains buffered.
scanf("%s", command );
while( getchar() != '\n' ){ /* flush to end of input line */ }
Equally if you use getchar() or %c to get a single character you normally need to flush the line, but in this case the character entered may itself be a newline so you need a slightly different solution:
scanf("%c", ch );
while( ch != '\n' && getchar() != '\n' ){ /* flush to end of input line */ }
similarly for getchar():
ch = getchar();
while( ch != '\n' && getchar() != '\n' ){ /* flush to end of input line */ }
The sensible thing to do of course is to wrap these solutions into stand-alone specialised input functions that you can reuse and also use as a place to put common input validation and error checking code (as in Daniel Fischer's answer which sensibly checks for EOF - you would normally want to avoid having to duplicate those checks and error handling everywhere).
I'd rather first use fgets and then use sscanf to parse the input. I have been doing this stuff like this for a long time and the behaviour has been more predictable than using plain scanf.
Well, I have something easier: add another getchar() ... problem solved!!
after taking command input flush the stdin.
fflush(stdin);
but flushing a input stream results in undefined behavior (though Microsoft's C library defines the behaviour as an extension).
Below is the program that I wrote.
/*******************************************************************************
* This program reads EOF from standard input stream to store in an integer
* variable and in a character variable. Both values are then output to see the
* stored value as integer.
*******************************************************************************/
#include<stdio.h>
int main (void)
{
/* Local Declarations */
int num;
char ch;
/* Read EOF as character & integer and display values stored */
printf("\nPlease only input EOF for all input prompts below");
printf("\nNumber? ");
scanf("%d", &num);
printf("\nThat integer input converts to %d", num);
printf("\nCharacter? ");
scanf(" %c", &ch);
printf("\nThat character input converts to %d", ch);
/* Check if any of the stored values are recognized as EOF */
if(num == EOF)
printf("\nNumber is an EOF");
if(ch == EOF)
printf("\nCharacter is an EOF");
/* Exit Program */
printf("\n");
return 0;
}// main()
I compiled using gcc on Ubuntu 11.10. It does not recognize Ctrl-D for EOF in the program and outputs 0 when trying to print its value. The output for the above program on my terminal is below.
Please only input EOF for all input prompts below
Number?
That integer input converts to 0
Character?
That character input converts to 0
NOTE: CTRL-D is not echoed by the terminal when I press it for the two inputs, hence not visible in the above program execution.
I have read that EOF is defined as an integer in stdio.h and stdlib.h and is traditionally defined as -1. Also, I understand that Ctrl-D simulates EOF for standard input. Then why does it not translate to -1 when storing it to an integer variable?
Because scanf("%d") will attempt to read characters representing a number and then store that into the given variable.
It does not store EOF into the number if you close the stream. Otherwise how would you tell the difference between end of file and entering the numeric value of EOF (-1).
The scanf will return the number of items scanned (which will be zero if format was wrong, or EOF if the stream closed or certain errors occurred). It returns this as the return code from the scanf function, not via the pointer variable you passed to it.
You should only assume the variables (that you pass in the addresses for) are populated if the return value from scanf tells you so.
In other words, you're looking for something like:
int rc = scanf ("%d", &num);
switch (rc) {
case EOF: {
printf ("EOF returned\n");
break;
}
case 0: {
printf ("No items scanned\n");
break;
}
default: {
printf ("Scanned %d\n", num);
break;
}
}
From the docs:
"If the input ends before the first matching failure or conversion, EOF shall be returned. If a read error occurs, the error indicator for the stream is set, EOF shall be returned"
Note that it is returned, rather than being read into the pointer you pass.
To distinguish between an error and EOF you can use feof.