Will this for loop run infinitely? - c

I have some experience with the c programming but sometimes the author of some books just pose such strange syntactical question which we will never use in actual programming and similar to that I stuck on one such question though the answer is given but I am not able to understand the answer.Here is the code below
int main
{
int i;
for(;scanf("%d",&i);printf("%d",i)){
;
}
}
The question is how many times this for loop will run and the answer given is indefinite
Can anyone explain how the loop will get executed

scanf returns number of elements successfully read and in this case it will be 1 if it reads a integer and keeps printing it.
Let's say you pass a character here then scanf() fails and exits from a for loop

Scanf will return the no of successful input get. If you give the input correctly then the condition will be true so it keep on running as indefinite.
To make the condition false you can give the input other than the integer value. That time scanf will return zero. So the loop will end.

Here, indefinite means that it is cannot be defined(unknown), it does not mean infinite (just to clear things out). Because, here the no of times the loop is run is dependent on the input given. If a correct input is given, which is an integer, the loop keeps running. If a wrong input is given, that is a non integer, the control jumps out of the loop. So you cant have a single answer for all scenarios, hence it is indefinite.

No. This is not an infinite for loop.
As per the syntax of for loop, from section 6.8.5.3 of the n1256 TC3 C99
for ( clause-1 ; expression-2 ; expression-3 ) statement
behaves as follows: The expression expression-2 is the controlling expression that is
evaluated before each execution of the loop body....
In your case, expression-2 is scanf("%d",&i), and the return value of scanf() will be considered for evaluation of expression-2.
As per the man page of scanf()
Return Value
... 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.
So, in your case,
till time scanf() is success, it will number of input items
successfully matched, which is 1 and a TRUE value, for loop
will continue execution.
if the scanf() fails [example: input char value], the return
value of scanf() will be 0 [matching failure] and the loop will
terminate.

After accept answer
Yes this very well may be an infinite loop.
scanf() returns the number of successfully scanned fields (0 or 1 ) here or EOF on IO error or end-of-file.
The only way to exit the loop is to enter a non-numeric input like "xyz".
Should user close stdin, scanf() will return EOF. EOF is a negative value (not 0). So the loop will continue calling scanf(), continue receiving EOF until the program is killed.
#include <stdio.h>
int main(void) {
int i;
for (; scanf("%d", &i); printf("%d", i)) {
;
}
return 0;
}

Related

While loop never stops when I enter a character in a place [duplicate]

This question already has answers here:
Why is scanf() causing infinite loop in this code?
(16 answers)
Closed 5 years ago.
I have a problem with this loop when I enter a character for ˋscanfˋ. The loop will never stop. But when I enter a number all works good.
This Is The Code:
#include <stdio.h>
#include <stdlib.h>
int main() {
int x;
printf("Enter 1 Or 2\n");
scanf("%i",&x);
while (x!=1 && x!=2) {
printf("Please Enter A Right Value \n");
scanf("%i",&x);
}
printf("Finish");
}
Well when you input character, scanf actually tries to get those wrong character inputs from the stdin but as it is not as per the conversion specification provided it fails. And then it keeps those wrong input in the stdin. And next time the scanf fails again due to those wrong inputs. So you need to clear it before you attempt to get the input again using scanf. Also check the return value of scanf and in case it failed clear the stdin.
The provided code checks for EOF and also return value of scanf the standard says explicitly about the return value of scanf :-
7.21.6.2p16
The fscanf function returns the value of the macro EOF if an
input failure occurs before the first conversion (if any) has
completed. Otherwise, the function returns the number of input
items assigned, which can be fewer than provided for, or even
zero, in the event of an early matching failure.
The code will be something like this. (This is using scanf).
Better even use fgets. you can easily and more better way control the erro neous inputs. With fgets you will read the entire line and then parse the integer input from it using strtol or strtoul. Yes in case of integer input there will be a case there also - you need to check if the parsed long or unsigned long is of proper size so that they can be kept in int variable.

understanding of scanf() function

I was trying to figure out whether my input is numeric or not and I found this example:
while ( (scanf ("%d", &number) ) == 0) {
printf("Entered value is not integer");
}
I searched online but I did not find any explanation about this. Why it means not a integer (Does this mean your input contains alphabets?)if you scanf() a integer and equal to 0?
There probably wasn't any explanation for the code:
while ( (scanf ("%d", &number) ) == 0) {
printf("Entered value is not integer");
}
because there isn't a good explanation for it. It is bad code on multiple grounds, some of which have been covered by other answers, but some of which have not been mentioned.
The novel problems are:
If the scanf() reports 0, the program goes into an infinite loop. The character that was rejected as 'not part of a number' still isn't part of a number on the next cycle, so scanf() will consistently return 0 until the program is interrupted in some way.
You can work around this by eating (at minimum) the first character of the remaining input. It is probably better to eat up all the characters until the next newline is read. After all, if the user mistyped the number, whatever else is on the line is not reliably what they wanted to type.
The diagnostic message doesn't end with a newline, so it may not appear until enough copies of the message have been generated to fill the standard output buffer, whereupon a number of copies of the message will appear. There's a chance that you won't see this behaviour because the standard input and standard output stream might be synchronized so that any pending output is flushed before an input operation, but it is not reliable.
Then there's the boring stuff everyone else mentioned:
The scanf() function might return EOF, or 0, or 1 (because there is only one conversion specification). If it returns EOF, you have another cause for an infinite loop: it will return EOF each time it is called, but the code doesn't react to the information.
Most often, the correct way to detect that scanf() worked is to check that the return value is the number of values you expected should be returned (the number of active conversion specifications — you don't count %*d or %n or %% in the number of active conversion specifications, and maybe active isn't the best word, but it suffices for now).
Putting fixes for these issues together, you might arrive at:
int rc;
while ((rc = scanf("%d", &number)) != 1)
{
if (rc == EOF)
{
printf("EOF detected without a number\n");
break; // return, exit, ...
}
printf("Entered value is not an integer: ");
int c;
while ((c = getchar()) != EOF && c != '\n')
putchar(c);
putchar('\n');
// Optionally fflush(stdout);
}
See Using fflush(stdin) for why I didn't use fflush(stdin) instead of the loop. You may prefer not to echo the invalid entry, in which case you can replace the putchar(c); with just the semicolon (and adjust the error message before, and the putchar('\n'); after too), but it often helps people to understand what they did wrong if they see what the program thinks they typed. You might want to think about whether error messages should be written to standard error instead of standard output. If getchar() returns EOF, the next iteration of scanf() will also return EOF, so that case will be handled. Note the use of int c; — getchar() returns an int, not a character.
As mentioned in the man page, in case the matching is failure, scanf() retunes 0. IN other words, scanf() returns the number of successful matches.
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.
In case for a %d format specifier, the entered value is a char (i.e., not a match for an int) matching fails and scanf() returns 0.
So, the bottom line is, a return value of 0 here indicates, the input was improper and the scanning has failed. That also mentioned, the assignment of the value expected of scanf() has failed, leaving the possibility of usage of indeterminate value for the supplied argument.
If user gives integer then scanf will return 1 [the no of successfully scanned variable(s)] else return 0.
ALREADY AVAILABLE HERE :
Value returned by scanf function in c
Btw the code is not proper as if EOF reached then also it will show ".. not inte..." as scanf will return -1 [also != 0] .
See Value returned by scanf function in c
On success, the function returns the number of items successfully
read. This count can match the expected number of readings or fewer,
even zero, if a matching failure happens. In the case of an input
failure before any data could be successfully read, EOF is returned.
If it successfully reads the number, it returns 1. The loop will end.
If it fails to read anything (probably due to EOF), it returns EOF, which is -1. The loop will end.
If it reads something, but unable to convert it to integer, it returns 0, the loop continues.
From the man page for scanf:
Upon successful completion, these functions shall return the number of successfully matched and assigned input items
and
An input item shall be defined as the longest sequence of input bytes (up to any specified maximum field width, which may be measured in characters or bytes dependent on the conversion specifier) which is an initial subsequence of a matching sequence. The first byte, if any, after the input item shall remain unread. If the length of the input item is 0, the execution of the conversion specification shall fail; this condition is a matching failure, unless end-of-file, an encoding error, or a read error prevented input from the stream, in which case it is an input failure.
In your case, the input specifier is "%d", which Matches an optionally signed decimal integer.... So if the first character (after skipping any white space) is a numeric digit (or a +/- sign), this will convert the number (one or more digits), stopping when it sees any non-digit characters. The return value is the number of converted values, which will be 1 if it found a valid decimal number, or 0 if it didn't.
Beware that the result may not be what you expect, for example:
4-hydroxytoluene
would convert the number 4 and return 1, even though it doesn't appear to be the intent of the input. Similary 1337age, for "leetage", would convert the number 1337. I often use a code snippet like the following to avoid such cases:
char dummy;
int conversions = scanf("%d%c", &number, &dummy);
if ((conversions != 1) && ((conversion != 2) || !isspace(dummy)))
printf("Entered value is not an integer.\n");

Where to use this while loop?

I've just started to learn c programming. I don't know weather this question is silly or not.
Where do i use
while(getchar()! ='\n') ;
When using scanf function in some program the above mentioned while loop is used whereas some other program doesn't use the while loop after the scanf function.
So, where should i use this while loop and where not to?
Use the loop to clean up the rest of a line after an error
You use code similar to the loop in the question when you think there is debris left on a line of input after you (attempted to) read some data from standard input but the operation failed.
For example, if you have:
int n;
if (scanf("%d", &n) != 1)
…recover from error here?…
The error recovery should check for EOF (it is correct to use feof() here — but see while (!feof(file)) is always wrong for how not to use feof()), and if you didn't get EOF, then you probably got a letter or punctuation character instead of a digit, and the loop might be appropriate.
Note that you should always check that the scanf() operations — or any other input operation — succeeded, and the correct check for the scanf() family of functions is to ensure you got the expected number of successful conversions. It is not correct to check whether scanf() returned EOF; you can can get 0 returned when there's a letter in the input queue and you ask for a number.
Beware EOF
Incidentally, the loop in the question is not safe. It should be:
int c;
while ((c = getchar()) != EOF && c != '\n')
;
If the loop in the question gets EOF, it continues to get EOF, and isn't going to do anything useful. Always remember to deal with it. Note the use of int c; too — getchar() returns an int and not a char, despite its name. It has to return an int since it returns every valid character code and also returns a distinct value EOF, and you can't fit 257 values into an 8-bit quantity.
While loop syntax :
while (condition test)
{
// C- statements, which requires repetition.
// Increment (++) or Decrement (--) Operation.
}
while(getchar()! ='\n') ;
Here your condition is getchar()!='\n'.
First getchar() will execute . It will ask input from user. This function returns the character read as an unsigned char cast to an int or EOF on end of file or error. While loop keep continue executing until return value will not match with '\n'
scanf() example : scanf("%s", &str1);
With scanf you can ask user for enter input one time only For more than one input you have to place scanf in loop.
Where as you ask to enter input to user in while loop condition So It will keep asking input from user until EOF signal occur.
When the scanf() format string does not cause it to read the newline from the input buffer.
Most simple format specifiers will not read the newline. However if you use %c, any character may be read, including newline, in which case the loop will need modification:
while( ch != '\n' && getchar() != '\n' ) ;
Where ch is the variable receiving the %c input.
Because console input is normally line-buffered, failing to consume the newline will cause subsequent stdin reading functions to return immediately without waiting for further input, which is seldom what is intended.
You would not use such a loop in cases where multiple fields are entered in a single line but processed in separate scanf() (or other stdin function) calls.

C Ending a loop with user input

I'm trying to write a program that lets the user insert integer values into an array until they enter a specific key to stop, say ENTER, or X.
int array_numb[100];
char quit = 'x';
printf("Enter as many values into the array as you want, pressing x will end the loop\n");
while(1==1){
int i = 0;
scanf("%i",&array_numb[i]);
i++;
array_numb[i] = quit;
}
I know it's wrong but this is my thought process. Any ideas? thanks for the help
Enter as many values into the array as you want while having int array_numb[100];, at some point you will be in trouble. What if the user enters more than 100 numbers before entring the sentinel value? You'll be overruning the allocated memory, isn't it?
You should check the return value of scanf() to ensure proper input. A mismatch in the supplied format specifier and the type of input will cause scanf() to fail. Check the man page for details.
You need to have a break statement inside while(1) loop to break out. Otherwise, you need to have a conditional statement in the controlling expression for while() loop to terminate the loop.
Note: IMHO, the best way to stop scanning user input is to comapre the return value of scanf() against EOF, which can be produced by pressing CTRL+D on linux and CTRL+Z in windows.
You can check this answer for your reference.
The same thing can be achieved as shown below:
scanf() can fail and check the return value. When a character is scanned scanf() fails
int i=0;
printf("Enter as many values into the array as you want, pressing x will end the loop\n");
while(i<100 && scanf("%d",&array_numb[i])==1)
{
i++;
}
scanf, with %i, will fail to scan a number when invalid data, such as a character is inserted and will return 0(in your case) if it fails.
Just check the return value of scanf. If it is zero, use
if(getchar()=='x') //or if(getchar()==quit)
break;
Note: Clear/flush the standard input stream(stdin) using
int c;
while((c=getchar())!='\n' && c!=EOF);
after the loop as well as after the break; .
You could learn something and use signals:
http://man7.org/linux/man-pages/man7/signal.7.html
Register SIGINT, override it, let it check which key was pressed, then let it change a variable. In your loop check if this variable is 0 or 1.
Signals have top priority, signal code will be executed no matter the loop.
Example: http://www.thegeekstuff.com/2012/03/catch-signals-sample-c-code/
It's overkill for this case but a fun thing to know. Signals are the way how an OS is managing events, like process kills, keyboard input etc. Be warned, how to use this is OS specific and has not much to do with C itself.

Expected program to print the value of EOF

In the code:
#include<stdio.h>
int main()
{
int t;
for(;scanf("%d",&t);printf("%d",t));
}
The program runs as expected when I give general intergers as input. I am working on Windows so when I scanf Cntrl+Z into the argument t, I do not get the value of EOF i.e -1 on the standard output, but the previous argument that was stored in it.
Also when I press Cntrl + D the program terminates, why does Cntrl+D cause scanf to return 0?
And why on scanf Cntrl+C my compiler says: "Process terminated with status -107......"
I am not understanding why this is happening? Please help.
scanf returns the number of successfully matched formatting specifiers, or EOF if the end of input was reached before matching (or failing to match) the first specifier.
When you press Ctrl+Z, scanf reaches the end of input and returns EOF (because Ctrl+Z terminates input on Windows). This does not terminate your for loop because EOF is nonzero, so the previous value of t is printed (as t was not changed by the call). Note that t will not receive the value EOF on end-of-input as you seem to expect: scanf returns EOF as the return value, it does not write it into the pointers you pass to it.
When you press Ctrl+D, it is treated as any other character. Since it is non-numeric, it causes a matching failure for the %d specifier and scanf returns 0, which terminates the loop.
Try this code and When ever if you press CTL+Z(CTL+D on linux) will give you zero. otherwise prints 1
#include <stdio.h>
main()
{
int c;
while(c=getchar()!=EOF) //here get the character and then compares with the EOF if Not equal 1 will assign to c , if equal 0 will assign to c.
printf("%d",c);
printf("%d",c);//when ever we press ctl+Z(ctl+d on linux) then it will print zero remaing all cases this statement wont execute
getchar();
}

Resources