getchar issue when check read char against Enter key - c

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.)

Related

How to replace do while loop , by for loop or while loop?

Here is my code, how could I replace do while by for loop or while loop? What should I change?
int main() {
int a;
do {
printf("\nEnter 1 to continue: ");
scanf("%d",&a);
if (a==1){
function=initial(function);
break;
} else {
function=final(function);
}
} while (a!=1);
}
A for loop is not suitable for this, you do not iterate over anything (you could still use one tho if you really wanted to).
To use a while loop, initialize a to 0:
int a = 0;
while(a != 1){
...
}
For the for loop:
int a = 0;
for(;a != 1;){
...
}
But none of this is relevant since you just break out of the loop as soon as a equals 1 anyway.
I found it hard to fight the problem of a busy loop after entering a letter: your scanf reads nothing because there is no digit, but the letter is still there in the input.
So the screen gets flooded with "Enter 1 to continue", and you enter "1", even though you rather want it to stop, but only ctrl-c helps.
If you really want the integer "1" or "+1" or "001" as test (and not e.g. first occurence of letter '1'), then you have to read the whole line (= what the user confirmed by enter) as string and convert it to integer.
This uses %ms format - m like mem allocation. I put it in a function so it fits in the while() condition. Otherwise it is just while(1) or for(;;) with a break.
#include <stdio.h>
#include <stdlib.h>
char *scanf_line1(char *line) {
printf("Enter 1 to continue: ");
scanf("%ms", &line);
return line;
}
int main() {
int loop = 0;
char *line;
while(atoi(scanf_line1(line)) != 1)
loop++;
printf("OK, continuing after %d extra loops\n", loop);
}
An impression:
$ ./a.out
Enter 1 to continue: -1
Enter 1 to continue: +1
OK, continuing after 1 extra loops
$ ./a.out
Enter 1 to continue: 111
Enter 1 to continue: r
Enter 1 to continue: rrrrrrrrr1
Enter 1 to continue: rrrrrrrrrrrrrrrrrrrrrr 1
Enter 1 to continue: OK, continuing after 4 extra loops
$ ./a.out
Enter 1 to continue: 5 4 3 2 1
Enter 1 to continue: Enter 1 to continue: Enter 1 to continue: Enter 1 to continue: OK, continuing after 4 extra loops
$ ./a.out
Enter 1 to continue: 2 00000000000000000000001
Enter 1 to continue: OK, continuing after 1 extra loops
Suddenly it works with hidden numbers, instead of crashing. Just the repeated message for each non-1 word in the line.

Double Ctrl+D input when using scanf for strings on Windows

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

Why is this C for-loop not working properly?

int main()
{
int t, i;
int *nums;
scanf("%d", &t);
nums = malloc(t * sizeof(int));
for(i = 0; i < t; i++)
{
scanf("%d", &nums[i]);
}
printf("hey");
}
For some reason, it hangs, waiting for more input! Any ideas?
This code is correct, except for the fact that you're not freeing your memory (not a big issue for this simple code) and you're not checking scanf for errors, which may be the cause of your problem.
A better implementation with error checking and correct memory handling is described below:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int t, i, ret;
int *nums;
ret = scanf("%d", &t);
if(ret != 1)
{
/* something wrong */
}
nums = malloc(t * sizeof(int));
if(nums==NULL)
{
/* memory error */
}
for(i = 0; i < t; i++)
{
ret = scanf("%d", &nums[i]);
if(ret != 1)
{
/* something wrong */
}
}
free(nums);
printf("hey");
return 0;
}
Just a guess here...
But I'm guessing you ran it and entered :
4
1234
For example, you put in 4 and then 1234 and it hangs. Well, that would be because 1234 is the first number and not 4 distinct numbers so its waiting for the second number. You have to press enter or some such delimiter between each number.
Try this set of inputs instead:
4
1234
29
4
5
You should get :
hey
Pro grammatically, you should be checking return values from your function calls. Make sure malloc didn't return zero. Make sure scanf returns the number of inputs you expected to read. Add in printouts to make sure the values it read in are what you expected/wanted to read in.
EDIT :
Guessing you have a typo in the program which isn't displayed here. such as :
scanf("%s", &t);
Or you are getting the 'hey' and just not seeing it.
[ov#MARVIN sotest]$ ./a.out
5 5 4 3 23 1
hey[ov#MARVIN sotest]$
See the 'hey' is sort of hidden in my prompt because you are missing the '\n' new line in the printout?
Remember to flush when you are done.
In chat, OP's comments "No... BTW, if I add a printf in the loop that prints the current input, it prints everything except from the last one...". This hinted that the issue was on the final output.
The following sends data out to be printed. But stdout is typically buffered. Actual output may not occur until sometime later. Output is flushed when 1) output contains an end-of-line '\n', 2) fflush() is called 3) the program ends. I am surprised output did not appear when the program ended, but possibly OP's true code differs from the post.
printf("hey");
Change to
printf("hey\n");
Or #Cool Guy
printf("hey");
fflush(stdout);
BTW: This is also hinted in #Diversity answer.
Note: Always a good idea to check the result of scanf()
// scanf("%d", &t)
if (1 != scanf("%d", &t)) Handle_BadInput_or_EOF();

Please help in finding the error in my program

I know the program I am posting is very basic but I am unable to find the error. I rechecked everything but despite no compilation error, the output is not coming.
#include<stdio.h>
#include <stdlib.h>
int main()
{
int i;
while(1)
{
if((scanf("%d",&i))!=42)
{
printf("%d",i);
}
else
{
break;
}
}
return 0;
}
Thank You for your time and consideration.
scanf does not return the value entered. It returns the number of inputs matched. So your check for 42 is incorrect. It will return 1 if an integer was assigned to i, or 0 if there was invalid input. If you want to exit the loop when the user enters 42, you should explicitly test if (i == 42).
As simonc mentioned, The reason you're not getting any output is because printf("%d",i); is not printing a newline "\n" after the number, and the standard out (stdout) stream is line-buffered. That means the standard library is going to continue to buffer up your printfs until a newline is encountered. At this point the buffer will be flushed to the console.
The solution is to add the newline (which is probably what you desire anyway): printf("%d\n",i); Alternatively, you could call fflush(stdout) to tell the std library to flush the buffered content to the console immediately. Or, writing to stderr will output immediately, because it is unbuffered.
This should demonstrate:
#include <stdio.h>
int main()
{
int i;
while(1) {
fprintf(stderr, "Enter a number (or 42 to quit): ");
if((scanf("%d",&i)) != 1) {
fprintf(stderr, "Invalid input.\n");
continue;
}
if (i==42)
break;
printf("Number provided: %d\n", i);
}
return 0;
}
Output:
$ ./a.exe
Enter a number (or 42 to quit): 17
Number provided: 17
Enter a number (or 42 to quit): 42
$
You are comparing the scanf function's return value to 42, not the variable i's value.
maybe you should read this
http://www.cplusplus.com/reference/cstdio/scanf/?kw=scanf

scanf() in while loop not terminating?

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.)

Resources