Here's the situation, I have a code that reads values until the user inputs Ctrl+D, the problem though is I have to input it TWICE for it to successfully exit the loop, I figured it had to do with the fact that the Ctrl+D was being inserted into the string along with the remainings of the buffer and therefore didn't register as EOF and simply another character inside the string and only the second Ctrl+D which would be saved in an int variable, actually stopped the reading loop. To solve this I added while(getchar() != '\n') to see if it fixed the problem, but to no end.
Here's my code:
typedef struct {
char nome[50];
int tempo;
int ncertas;
} equipa;
int ler_equipas(equipa *resultados)
{
int x, r1, r2 ,r3 ,r4, r11, r22, r33 ,r44, rcertas = 0, i = 0;
scanf ("%d %d %d %d", &r1, &r2, &r3, &r4);
while (scanf ("%s %d %d %d %d %d", resultados[i].nome, &resultados[i].tempo, &r11, &r22, &r33, &r44 ) == 6 )
{
i++;
if (r1 == r11) rcertas++;
if (r2 == r22) rcertas++;
if (r3 == r33) rcertas++;
if (r4 == r44) rcertas++;
resultados[i-1].ncertas = rcertas;
rcertas = 0;
while((x=getchar()) != '\n');
}
return i;
}
The input/output was as follows (">>" means output):
1 2 3 4
>> correct answers are 1 2 3 4
Team1 234 1 2 3 4
>> values inputed for team time and answers: Team1 234 1 2 3 4
>> getchar value was (ASCII): 10
>> Next read:
Team2 400 1 3 2 4
>> values inputed for team time and answers: Team2 400 1 3 2 4
>> getchar value was (ASCII): 10
>> Next read:
>>
^D
^D
>> return i was reached
>> Number of teams: 2
>> Team "Team1" took 234 seconds and answered 4 questions correctly
>> Team "Team2" took 400 seconds and answered 2 questions correctly
Since you are using windows, you shall use ctrl+z for emulating EOF
See https://stackoverflow.com/a/16136924/4386427
When you use ctrl+d, the first ctrl+d matches the initial %s so the scan continues.
The second ctrl+d will not match %d so the scan terminates. Since the number of scanned elements isn't 6, the while loop terminates.
Consequently two ctrl+d terminates the function. A single ctrl+z will also terminate the program.
I did not try this yet. But i remember having the same Problems...
Try this: How to clear input buffer in C?
while ((c = getchar()) != '\n' && c != EOF) { }
This is a way to clear the input buffer. But this after a scanf(); call to clear the input Buffer.
Best regards
Related
When I run the code below, it executes correctly but adds an extra iteration before I can input again. Not sure why. I am going to be using it for fork and pipe parent process to children. That step will come after the user inputs # of processes.
Code:
#include <stdio.h>
int main(void) {
int num_processes;
int running = 1;
do {
printf ("How many processes do you want? (1, 2 or 4) \n");
num_processes = getchar();
num_processes -= '0';
if(num_processes == 1 || num_processes == 2 || num_processes == 4){
int temp = num_processes - 1;
printf("\n1 Parent and %d child processes\n", temp);
printf("----------------------------------\n");
running = 0;
} else {
printf("Invalid Input, please try again.\n");
}
} while(running == 1);
// Do important stuff
return(0);
}
Out:
How many processes do you want? (1, 2 or 4)
3
Invalid Input, please try again.
How many processes do you want? (1, 2 or 4)
Invalid Input, please try again.
How many processes do you want? (1, 2 or 4)
2
1 Parent and 1 child processes
----------------------------------
Think what happens when you give your first input. You type 3, and then you hit Enter.
Now, in the Standard input buffer, there are two items awaiting to be consumed, 3 and \n (which is Enter).
You enter the body of the loop for the very first time, 3 is consumed. Now next in line awaits the \n...
When you enter the loop's body again (for the second time), the next character to be read by the Standard input buffer is \n, and that's what the second getchar() happily returns to you.
Here is a quick fix:
do {
printf ("How many processes do you want? (1, 2 or 4) \n");
// Eat trailing newline character, if any
do {
num_processes = getchar(); // read a character
} while(num_processes == '\n'); // if it was the newline character, repeat
// until `num_processes` is not the newline character
// Continue with your logic..
num_processes -= '0';
Output:
How many processes do you want? (1, 2 or 4)
3
Invalid Input, please try again.
How many processes do you want? (1, 2 or 4)
2
1 Parent and 1 child processes
----------------------------------
PS: As #Barmar commented, if you want to read lines, then use fgets(). Read more here: How to use fgets() to control the execution of while loop through user input in c?
I'm writing a simple tokenizer in C and when I use the Xcode console to run my code and give input to my lexer, sometimes it's adding weird characters onto the end of my input.
Here's an input that sometimes gets extra characters added onto it
The input is on the line starting with (>>) and the data I print from the buffer is below it. You can see extra characters "\357 \234 1" somehow made their way into the buffer.
>> 2147483618
num read: 14
2 1 4 7 4 8 3 6 1 8 \357 \234 1
I thought it was an overflow problem, but it only happens when I run my code through the Xcode debugger.
Here's what happens when I just use the Terminal to execute my code
>> 2147483618
num read: 11
2 1 4 7 4 8 3 6 1 8
Here's my C code for reading in characters from the user:
for (;;) {
char *buff = malloc(20 * sizeof(char));
// Max number of characters to read
size_t num_to_read = 0;
// Number of characters actually read
size_t num_read = 0;
num_read = getline (&buff, &num_to_read, stdin);
printf("num read: %d\n", num_read);
// Code to print out the buffer
for (int i = 0; i < num_read; i++) {
if (buff[i] == '\0')
break;
printf("%c ",buff[i]);
}
free(buff);
}
Does anyone have any idea what's causing this?
I'm a beginner in C, and I've got problem I can't figure out, and wasn't able to find a solution on other threads here.
I'm trying to read integers from a keyboard input/ txt file with the following code:
int grades[MAX_GRADES_LENGTH]={0}, histogram[HISTOGRAM_SIZE]={0};
int maxGradesHistogramBucket=0, median=0, gradesLength=0;
double avg=0.0;
int grade=0;
printf("Enter grades:\n");
while (scanf("%d",&grade) != EOF)
{
grades[gradesLength]=grade;
gradesLength=gradesLength+1;
}
I'm supposed to set these "grades" in the grades[] array and count the length of the array along the loop.
Somehow the loop is misbehaving, it seems that some inputs are ok with the loop, but for some inputs(most of them actually) the scanf() doesn't get the EOF, whether it's an actual end of file, or the ^D command in the terminal.
I've heard the scanf() is not the most reliable method to read data, but unfortunately I can't use anything else since we haven't learned any other method in class so we can only use scanf() on our homework.
I've tried to change the!= EOF with == 1 and its all the same.
for the input
100 0 90 10 80 20 70 30 60 40 50
for example it works fine.
but for the input:
0 50 100
the loop is infinite.
I'm using a macbook pro btw (if it matters).
Any ideas?
If you type a letter instead of a number, scanf() will return 0 (as in, "zero successfully converted numbers") and not EOF (as in, "there was no data left to read"). The correct test is to ensure that you got the expected number of values — in this case, 1:
while (scanf("%d", &grade) == 1)
If you need to know whether you got to EOF or got no result (but reading the rest of the line might clear the problem), then capture the return value from scanf():
int rc;
while ((rc = scanf("%d", &grade)) == 1)
{
}
if (rc != EOF)
…read the rest of the line, or at least the next character, before resuming the loop…
And, if you really want to, you could then write:
int rc;
while ((rc = scanf("%d", &grade)) != EOF)
{
if (rc == 1)
grades[gradesLength++] = grade;
else
{
printf("Discarding junk: ");
int c;
while ((c = getchar()) != EOF && c != '\n')
putchar(c);
putchar('\n');
if (c == EOF)
break;
}
}
The code in the else clause could plausibly be put into a function. It might also report the messages to standard error rather than standard output. It is courteous to let the user know what it was that you objected to. You could stop before newline with a different test (&& !isdigit(c) && c != '+' && c != '-', using isdigit() from <ctypes.h>). However, the user doesn't have a chance to re-edit the stuff they put after the letters, so you may be going to misinterpret their input. It is probably better just to throw away the rest of the line of input and let them start over again.
As chux noted, after reading a character that could be part of an integer, that character needs to be put back into the input stream. Therefore, if I were going to analyze the rest of the line and restart scanning at the first data that could actually be part of an integer, I'd consider using something like:
#include <ctype.h>
static inline int could_be_integer(int c)
{
return isdigit(c) || c == '+' || c == '-');
}
and then the else clause might be:
else
{
printf("Discarding junk: ");
int c;
while ((c = getchar()) != EOF && c != '\n' && !could_be_integer(c))
putchar(c);
putchar('\n');
if (could_be_integer(c))
ungetc(c, stdin);
else if (c == EOF)
break;
}
This gets messy, as you can see. Sometimes (as Weather Vane noted in a comment), it is easier to read a line with fgets() and then use sscanf() in a loop (see How to use sscanf() in a loop?). Be wary of suggestions about Using fflush(stdin); it isn't automatically wrong everywhere, but it won't work on a MacBook Pro under normal circumstances.
On the whole, simply ignoring the rest of the line of input is usually a better interface decision.
It works for me.
I enclosed your snippet thus:
#include <stdio.h>
#include <errno.h>
#define MAX_GRADES_LENGTH 20
#define HISTOGRAM_SIZE 20
main()
{
int grades[MAX_GRADES_LENGTH]={0}, histogram[HISTOGRAM_SIZE]={0};
int maxGradesHistogramBucket=0, median=0, gradesLength=0;
double avg=0.0;
int grade=0;
int i;
printf("Enter grades:\n");
while (scanf("%d",&grade) != EOF)
{
grades[gradesLength]=grade;
gradesLength=gradesLength+1;
}
if (errno)
perror("grade");
for (i = 0; i < gradesLength; ++i) {
printf("%d\n", grades[i]);
}
}
and ran it:
$ a.out
Enter grades:
100 0 90 10 80 20 70 30 60 40 50
100
0
90
10
80
20
70
30
60
40
50
$ a.out
Enter grades:
0 50 100
0
50
100
$
Perhaps you are looking in the wrong place. Maybe the bug is in your output routine?
Personally, if had to do this, given some ambiquity over what scanf returns when, and without rewriting it, then this small change is probably more reliable:
int i, r;
printf("Enter grades:\n");
while ((r = scanf("%d",&grade)) > 0)
I have a simple c code as follow:
#define RECORDS_PER_PAGE 24
int main(void) {
int i = 0, n;
char pause_char;
printf("Enter a number as the stop point: ");
scanf("%d", &n);
while (++i <= n) {
printf("i is: %d\n", i);
if (i % RECORDS_PER_PAGE == 0) {
printf("Press Enter to continue...");
while((pause_char = getchar()) != '\n');
}
}
return 0;
}
The problem is when I enter 30 as the stop point, I got the following output:
i is: 1
i is: 2
i is: 3
...
i is: 24
Press Enter to continue...i is: 25
...
i is: 30
I expect that the program stop when the if condition satisfies. But it continue without paying attention to getchar. But the strange part is when I enter for example 60 as the stop point it will give the following output:
i is: 1
i is: 2
i is: 3
...
i is: 24
(1) Press Enter to continue...i is: 25
...
i is: 30
...
i is: 46
i is: 47
i is: 48
(2) Press Enter to continue...
i is: 49
...
i is: 59
i is: 60
It will stop at (2) but not (1). I now that maybe something in the buffer cause this problem, but I don't understand why. Is there any explanation for it?
The problem is that when you read input you end the input by pressing ENTER, thus giving you your number and \n, like 30\n.
So your scanf reads out the number and leaves \n in the stdin buffer,
then getchar() comes along and reads a byte, the \n.
Simple but ugly solution, add another getchar() to read out the \n. (Nicer way is to handle it in your scanf read directly.)
I have a while loop that scans in an input set of integers. It scans and prints all of the numbers with "..." at the end and skips to the next line. However, the script does not: execute past the while loop and print TEST.
For example, I enter:
3 44 62 1
It prints:
3...
44...
62...
1...
When it should print:
3...
44...
62...
1...
TEST
while(scanf("%d", &n) != -1) {
x[i] = n;
i++;
printf("%d", n);
printf("...\n");
}
printf("TEST");
What am I doing wrong?
scanf("%d", &n) != 1 is wrong. It should be scanf("%d", &n) == 1.
You're expecting the loop to end just because you hit enter? As written, your program will only stop if scanf fails to read a number due to reaching the end of the input file. If you're on Unix, you can signal EOF from the terminal by hitting Ctrl-D. If you're on Windows, it's Ctrl-Z Enter. (Also, don't rely on EOF being -1; it's not portable.)