Loop going on longer than intended checking for empty line - c

I have a loop that is stopped once a flag is set to 1.
scanf("%d", &next);
scanf("%d", &next1);
int done=0,next,next1;
while (done==0) {
printf("%d,%d.",next,next1);
if (getchar()=='\n') {
scanf("%d", &next);
scanf("%d", &next1);
}
//if not, set flag and stop looping
else{
done=1;
}
}
It scans for 2 numbers from every line of input every loop until there are no more lines of the input left. I thought this would work fine but I encountered a problem when I tested out the following input:
1 0
1 1
1 2
1 3
The output should be
1,0.
1,1.
1,2.
1,3.
but instead it prints the last loop twice like this:
1,0.
1,1.
1,2.
1,3.
1,3.
Why does this scan the last line twice before terminating? is there a character I can check for so it ends after it prints the first "1,3."?

I would suggest something like that
int main(){
int next,next1;
scanf("%d", &next);
scanf("%d", &next1);
while (getchar()=='\n') {
printf("%d,%d.\n",next,next1);
scanf("%d", &next);
scanf("%d", &next1);
}
}
by this way you save a little bit of memory, and is more readable. The output should be correct now, try by yourself.

scanf() -
If a reading error happens or the end-of-file is reached while reading, the proper indicator is set (feof or ferror). And, if either happens before any data could be successfully read, EOF is returned.
So, when the no more lines of the input left, the scanf() returns EOF and the while loop iterate because done is not set to 1 yet and printf() prints the value stored in next and next1 one more time. That's why the last entered value printed twice. After this the condition if (getchar()=='\n') fails and done set to 1 and while loop exits.
You can do:
int done=0,next,next1;
while (done==0) {
if (scanf("%d%d", &next, &next1) != EOF)
printf("%d,%d.",next,next1);
else
done=1;
}
Or
while (scanf("%d%d", &next, &next1) != EOF)
printf("%d,%d.",next,next1);

Related

why the below code is taking two input on single execution of scanf funcion

#include<stdio.h>
#include<conio.h>
int main()
{
int Dividend,divisor;
printf("Checking Divisiblity of 1st number with 2nd number \n\n") ;
printf("Enter Number \n") ;
scanf("%d",&Dividend);
printf("Enter Divisor = ");
scanf("%d",&divisor) ;
if(Dividend % divisor == 0)
{
printf("Number %d is divisible by %d",Dividend,divisor) ;
}
else
{
printf("Number %d is not divisible by %d",Dividend,divisor) ;
}
getch();
return 0;
}
Above is my code that i have written in C ;
on running this program . Only on first execution of scanf function if i give two input space seperated , the second input is going on right variable . and on hitting enter i am getting result . I am not understanding how is this happing .
When space is pressed, scanf doesn't see anything yet. Something happens only after enter is pressed. It then takes everything to the left of the space character and assigns it to the first variable, and everything to the right of the space character and assigns it to the second variable.
If you don't press the spacebar, scanf will interpret everything you type as a single number and will assign it to the first variable.
Instead what you may want to do is use the %c format specifier to read a single character at a time. You can then check if the character is a space character and if it is, you can break out of the loop. Otherwise, you can keep reading characters until you reach a space character.
stdin is line based by default. Your program gets nothing until you press enter. Then your program has the entire line of text available.
Result of this is, that scanf, getchar, fgets, etc calls will not return until you press enter. After enter press, entire line is available and the function starts to process it.
scanf is kinda special, that if you have int parsed_count = scanf("%d%d", &a, &b);, it will read two integers, no matter how many times you press enter, so you can either do
1 2<enter>
Or you can do
<enter>
1<enter>
<enter>
2<enter>
and scanf will still read these two integers (it returns early if there is parse error, which is why you need to check the return value!).
And vice versa, if there is already input available, then scanf may return immediately, so if you have this code
scanf("%d",&Dividend);
printf("Enter Divisor = ");
scanf("%d",&divisor) ;
and enter text
1 2<enter>
Then first scanf will wait for enter press, then consume the first integer, leaving 2<enter> still unread. Then there's print, and then 2nd scanf starts reading, skipping the whitespace and immediately getting 2nd integer. So you see
1 2 <- this is your typing echoed, not print from your program
Enter Divisor = <- printf printed this
If you want to take only one input per enter press, you can simply read characters until newline, because scanf leaves them there. Example loop to read until newline, or exit program at end of file/error:
while(true) {
int ch = getchar();
if (ch == EOF) exit(1);
if (ch == '\n') break;
}

Validate integer against chars

I'm trying to make a program where the user inputs value to an array. What is actually required is that the program should validate against a char character. So if the user inputs a random char such as 'n' the program should tell him "You introduced a char, please input an integer: ".
How is that possible to make that without using a char variable?
for (i = 1; i <= size; i++) {
printf("Introduce the value #%d of the list: ", i);
scanf("%d", &list[i]);
if () { // I'm blocked right in this line of code.
printf("What you tried to introduce is a char, please input an integer: ");
scanf("%d", &list[i]);
}
Thanks in advance.
As #MFisherKDX says, check the return value of scanf. From the scanf man page:
These functions return the number of input items successfully matched
and assigned, which can be fewer than provided for, or even zero in
the event of an early matching failure.
The value EOF is returned if the end of input is reached before either
the first successful conversion or a matching failure occurs. EOF is
also returned if a read error occurs, in which case the error
indicator for the stream (see ferror(3)) is set, and errno is set
indicate the error.
So capturing the return value of scanf in an int variable and then comparing that variable to 1 (in your case, because you are only attempting to read 1 item) should tell you if scanf successfully read an integer value.
However, there is a nasty pitfall when using scanf that you should be aware of. If you do type n at the prompt, scanf will fail and return 0, but it will also not consume the input you typed. Which means that the next time you call scanf, it will read the same input (the n character you typed), and fail again. And it will keep doing so no matter how many times you call scanf. It always amazes me that computer science educators continue to teach scanf to students, given not only this potential pitfall, but several other pitfalls as well. I wish I had a nickel for every hour that some CS student somewhere has spent struggling to get scanf to behave the way their intuition tells them it should. I'd be retired on my own private island by now. But I digress.
One way around this particular pitfall is to check if scanf failed, and if so, to purposely consume and discard all input from stdin up to and including the next newline character or EOF, whichever comes first.
First let's look at some unfixed code that causes an infinite loop if you enter a non-integer as input:
// Typing the letter 'n' and hitting <Enter> here causes an infinite loop:
int num, status;
while (1) {
printf("Enter a number: ");
status = scanf("%d", &num);
if (status == 1)
printf("OK\n");
else
printf("Invalid number\n");
}
The above code will (after you type n and hit <Enter>), will enter an infinite loop, and just start spewing "Invalid number" over and over. Again, this is because the n you entered never gets cleared out of the input buffer.
There are a few possible ways to get around this problem, but the consensus seems to be that the most portable and reliable way to do so is as follows:
// Fixed. No more infinite loop.
int num, status;
while (1) {
printf("Enter a number: ");
status = scanf("%d", &num);
if (status == 1)
printf("OK\n");
else {
printf("Invalid number\n");
// Consume the bad input, so it doesn't keep getting re-read by scanf
int ch;
while ((ch = getchar()) != '\n' && ch != EOF) ;
if (ch == EOF) break;
}
}
The function scanf() will returns the number of elements read, so in this case it will return 1 every time it reads an int and 0 when it reads a char, so you just need to verify that return value.
Keep in mind that after reading a character it will remain in the buffer so if you use the scanf() command again it will read the character again and repeat the error. To avoid that you need to consume the character with while(getchar() != '\n');
With that in mind I modified your code so that it works properly printing an error message if a character is introduced and asking for a new int.
for (int i = 1; i <= size; i++) {
printf("Introduce the value #%d of the list: ", i);
while (!scanf("%d", &list[i])) { //verifies the return of scanf
while(getchar() != '\n'); //consumes the character in case of error
printf("What you tried to introduce is a char\n");
printf("please introduce the value #%d of the list: ", i);
}
}

while(scanf) is infinite looping?

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.

Infinite loop in C when entered character [duplicate]

This question already has answers here:
Skipping over Scanf statement in C
(4 answers)
Closed 8 years ago.
I am writing an objective c program for hangman. I need to replicate another program which has been given to me. I have done most of it, but am having an issue. It has to replicate the other program exactly, so I went into the other one and entered a character into the wordlength. It came up with the "number must be between 3 and 14 (inclusive)" statement, and asked me to enter a number again, but it started to loop infinitely. It works when i enter a number lower than 3 and larger than 14 (comes up with the error and asks for another input) but with a letter it infinitely loops. Also, the loop is meant to loop infinitely until the word length is larger than 3 and less than 14. That is why the while loop will loop infinitelyAny ideas??? Thanks
while (i == 0) {
printf("\n\n > Please enter a word length: ");
scanf("%i", &wordLength);
printf("\n\n");
if (wordLength > 3 && wordLength < 14) {
continue;
}
else printf("number must be between 3 and 14 (inclusive)");
}
The main problem (that you seem to be asking about) here is that you don't check for errors from the scanf call. It will return with the number of successfully scanned items, or zero if none were scanned, or EOF on error.
If scanf fails to extract data from the input, like when you ask for an integer but the user write a letter, then that letter will continue to be in the input buffer, so the next call to scanf will see that letter again. And again and again...
The best way to fix this is to read the whole line, as text, into a buffer, and then try to parse the integer from this buffer (using e.g. sscanf):
char input[16];
if (fgets(input, sizeof(input), stdin) == NULL)
{
printf("Error reading your input\n");
exit(0); /* Do whatever error handling you want */
}
if (sscanf(input, "%d", &wordLength) != 1)
{
printf("Error: Input was not a valid integer\nPlease try again: ");
fflush(stdout);
continue;
}
Problem is with while (i == 0){ you never change i in the loop. You may want to update it to
while (wordLength == 0){
But make sure you do wordLength=0 before the loop.
change the value of i for the loop to terminate. you dint change the value of i anywhere inside loop.
continue;
will not exit the loop, it will just skip the statement after continue statement and start the loop again. To exit the loop use
break;
so use break or change the value of i to some value other than i=0 to exit the loop.
I think you meant break instead of continue:
if (wordLength > 3 && wordLength < 14)
break;
break will take you out of the loop, whereas continue skips to the next iteration of the loop (which , as others have mentioned, never terminates because i is never changed)
Do not forget to break your loop when the condition is met.
while ( 1 ){
printf("\n\n > Please enter a word length: ");
scanf("%i", &wordLength);
printf("\n\n");
if (wordLength > 3 && wordLength < 14) {
break;
}
else printf("number must be between 3 and 14 (inclusive)");
}

C: Scanning from stdin

I'm writing code that, when called from the command line, is redirected a file. The lines of the file (which are sent over stdin) are parsed and read. I want to be able to call a function and have it scan an int, but it seems that there are issues with residual data in scanf (I don't actually know if that's the issue, but that's all I can think of). Here is my code:
dataSetAnalysis(data, experiments);
int selection;
while(1){ //always true. The loop only breaks when the user inputs 4.
printf("DATA SET ANALYSIS\n"
"1. Show all the data.\n"
"2. Calculate the average for an experiment.\n
"3. Calculate the average across all experiments.\n
"4. Quit.\n"
"Selection:__");
switch(selection){
case 1:
displayAll(d,e);
break;
case 2:
individualAverage(d,e);
break;
case 3:
allAverage(d);
break;
case 4:
exit(0);
}
scanf("%d", &selection);
}
And this is the second half of the main method.
while(fgets(currentLine, 20, ifp) != NULL){ //while there is still data in stdin to be read
experiments[i] = currentLine; //experiment[i] points to the same value as current line. Each value in experiments[] should contain pointers to different positions in the allocated buffer array.
currentLine += 20; //currentLine points 20 characters forward in the buffer array.
int j = 0; //counter for the inner while loop
while(j<10){ //while j is less than 10. We know that there are 10 data points for each experiment
scanf("%d ", &intBuffer[j]);
data[i][j] = intBuffer[j];
j++;
}
numExperiments++; //each path through this loop represents one experiment. Here we increment its value.
i++;
}
The program loops infinitely when reaching the while loop in dataSetAnalysis() and continues printing "DATA SET ANALYSIS...." without ever stopping to accept more input over stdin. Is the problem with scanning to the selection variable?
The problem is that your stdin is not clear, You have to clear your input buffer by iterating till you find an '\n' or an enter hit.
Try use this
while('\n' != getchar())
{ }
just before you scanf , it will get rid of the infinite loop
something like
while('\n' != getchar())
{}
scanf("%d", selection);
The first and fundamental rule is 'always check the return value from an input function' (such as scanf()). They always return some indication of whether they were successful or not, and if they're unsuccessful, you should not use the values that would have been set had the function call been successful.
With scanf() et al, the correct way to use the function is to test that you got the expected number of values converted:
if (scanf("%d", &intBuffer[j]) != 1)
…handle error…
You also have the format string: "%d " in the code. That doesn't stop until you type a non-white space character after the number. This is confusing, but any white space (blank, tab, newline) in a format string means read optional white space, but the function only knows when it has finished reading white space when a non-white space character is entered.

Resources