scanf() in while loop not terminating? - c

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

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.

How to repeat a process in a while until enter is pressed?

I need to repeat a process and I'm using a while. I need to do antoher process when enter key is pressed and I'm using if(getchar()). The problem is that the while "pauses" when it gets to the if because it's checking if getchar() it's true. I need to know how to keep looping the while whithout it stopping to check if there's an enter.
I'm making a game in which you have 1 minute to guess as much names as you can. So the purpose of the while() is to countdown from 60 to 0 seconds (clears the screen and prints the new second and the name you're actually guessing every second). So I want it to keep running the while() so the timer keeps running, but if enter is pressed it only changes the guessed name to a new name and the timer keeps running. (I don't know if I was clear but this is the idea)
//program in c
while(//specific condition)
{
/*- here goes the code for a timer that every second it clears the
- terminal and prints the next number (in seconds).
-
-
-*/
if(getchar()) //the current program stops here and keeps running the loop
//until enter is pressed
{
//second process
}
}
I expect the while to keep looping until there's an enter. When that happens I want it to enter the if, exit the if and keep looping.
char buffer[100];
while (fgets(buffer, sizeof(buffer), stdin))
{
if (strlen(buffer) == 1)
break;
if (sscanf(buffer, "%f", &f) == 1)
{
total += f;
printf("Enter another number: ");
}
}
if you have conio.h available in your environment you can use kbhit
while(//specific condition)
{
/*--process to do
-
-
-
-*/
if(kbhit())
{
if (getchar() == 0x0d)
{
break;
}
}
//second process
}
In this loop, the second process will run without checking the enter key and only exit if enter key is pressed.
You cannot use if(getchar()=='\n')
so the program runs until an enter key is pressed
because buffer value of '\n' will be present and it'll alter the next iteration
char a;
printf("Enter charecter or press enter to exit:");
scanf("%c",&a);
while(1)
{
//process 1 loop
if (a == '\n')
{
// process 2 here, if process two has loop make it's own loop here
printf("we are in process 2\n");
break;
}
getchar();
printf("Enter charecter or press enter to exit:");
scanf("%c",&a);
}
You did't give enough code to understand what input stream you are working with but something like this will do it, if it's file stream or string do it accordingly by replacing scanf with fgets, or file stream inputs like fscanf or fread.

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

Printf waiting for enter

int kr=0;
int ss =0;
while ((kr=getchar()) != EOF){
if(kr != '\n')
{
ss++;
}
printf("%d\n",ss);
}
With this code , printf is waiting until i press enter then printing all the sequential ss values at the same time like in this
. Can somebody explain this behavior ?
printf is not waiting it is getchar instead. getchar uses a buffer behind the scene. When that buffer is empty, getchar will read 1 line from stdin and then return the first caracter. If it is not empty, it will return the next caracter from the buffer immediatly.
That means that the getchar will wait the first time you call it. And thus your printf is never executed until you press enter

getchar issue when check read char against Enter key

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

Resources