Is it recommended/ appreciable to use infinite loops in C programming - c

Here is an example. For small programs that's fine to use , but what if we are developing a real time project or Application . Need some suggestions
while (TRUE )
{
int temp =0 ;
printf ( "How many no's would you like to enter : " ) ;
temp = scanf ( "%d" , &n ) ;
if ( temp==1 )
break ;
else
{
printf ("Invalid input. Try again. \n" ) ;
fflush ( stdin ) ;
}
}

The trouble with any loops, be they while(TRUE) or while(condition), is their tendency to have a sneak infinite loop condition - like this one.
OP's code depends on 2 results of scanf("%d",...,: 1 and not 1.
If user enters "123", all is good. scanf() returns 1, loop exits, we all leave work and have a pint.
If user enters "abc", scanf() returns 0, code does a fflush(stdin) to empty the stdin. (This is really UB, but let us pretend it works.) Code loops, prompts again, our drinks get warm, but hopefully we will eventually enter digits.
But let us imagine the user closed stdin - maybe code had re-directed input and scanf() eventually returns EOF. Code loops, but fflush(stdin) does not re-open stdin, and scanf() again returns EOF - and again and again - true infinite loop - code will not pause for input and just says ""Invalid input. Try again." which translates into "dumb guy, dumb guy, dumb guy ...". Looks like the crew will start their brews without us.
Moral of the story: loop when code is working as intended (User entered good data). Watch out for loops when functions loops on the unexpected.

If you're asking about style, recommendations are going to be somewhat subjective.
If you're afraid that your loops may turn into true infinite loops when undesired, then you need to do something about that. For example:
redesign your code to be an explicit state machine with clearly documented and implemented conditions for when the state changes and when it remains the same
think through the various error conditions that may occur (and thus potentially cause hanging in a specific state indefinitely) and handle them the best you can, also think of those conditions that are fatal and can't be handled gracefully (do you crash and burn? do you log an error? do you show it on some dash board? do you eject the driver's seat with the driver? do you dial an emergency phone number if applicable? etc etc), incorporate that into the state machine
review the code with your peers (maybe even hire industry experts for this)
implement and use tests (unit/integration/scenario-based/scalability/stress/security/etc etc)

Related

How to completely clear stdin and the \n before scanf()

Environment:
Windows 7 Enterprise SP1
gcc version 6.3.0 (MinGW.org GCC-6.3.0-1)
I'm new to C language (not new to programming).
I'm migrating a big program to C language. All works fine except for this.
I create this small program to reproduce the problem:
int AAA ()
{
const char *p = "Enter to proceed.. X to Exit.. : ";
const char *ok = "OK" ;
char proceed1 ;
char proceed2 ;
printf(p) ;
fflush(stdin) ;
scanf("%c",&proceed1);
if (proceed1 == 'X'){
return 0 ; }
sleep(3) ;
fflush(stdin) ;
printf("\n%s",p) ;
scanf("%c",&proceed2);
if (proceed2 == 'X'){
return 0 ; }
printf("\n%s",ok) ;
return 0 ;
}
All worls fine, BUT if the user (wrongly) hits twice the enter key at the proceed1 then scanf of proceed2 automatically reads the newline character '\n' that remain in the buffer...
I tried all: rewind(stdin), fseek stdin, a getchar before the second prompt to bypass the problem, but let the scanf hang if the user correctly hit enter key once.
I repeat I'm new to C language. I understand the problem can be bypassed writing a scanf that does not accpet the \n alone.
But before proceeding I ask here this question:
How to completely clear the stdin buffer?
Just because this is a common enough question, notwithstanding the links to other like questions and/or duplicates, I think this bears repeating:
If you are trying to fflush(stdin), you are almost certainly doing something wrong
An input buffer flush says, “I don’t care what you typed so far. I’m throwing it away and we’re starting over.”
Such behavior is exceedingly frustrating to users of a program. Users expect their inputs to be recognized and acted on — even if those inputs are wrong! By throwing it away, your program tells the user that their wishes are not respected, leaving them feeling like they have less control of their computer than they should.
It’s an XY problem
The usual suspect behind desires to clear the input is a scanf failure. The user typed something wrong, input is stuck with invalid characters, and the program needs to get past that.
But the program does not need to get any further than the next newline, which is to say, it only needs to discard stuff that was input before the user pressed Enter. This comes from one very simple principle:
The user will always press Enter after every prompted input
The solution comes in three forms:
Crash and burn. This is a strong signal that the user needs to fix his input to work, and actually provides him (or her) with a greater sense of control: the program does only what it is supposed to, accepting only input it should, and does nothing unless the input is correct!This also affords the user greater control in how he or she uses your program, because he can now supply prepared input to the program without having to babysit the keyboard.
Skip to the EOL and ask for the user to try again. This presupposes a human is frobbing the keyboard. But if you are going to go through this grief, then:
Read all input as a string, one line at a time, and endeavor to process that string (using sscanf, for example). This keeps your input and processing pointers all lined up and you will never have need to try to resynchronize with the input buffer.
Obviously, my opinion is that crash and burn is the most correct method for your usual console programs.
This is, in fact, part of the core design of Unix. This behavior enables individual utility programs to combine to perform useful scripted tasks.
The exception is a TUI program.
A text-based user interface is for a program that requires a human to operate it*, and takes over the terminal to behave in a different way, not requiring the user to press Enter to receive and act on input.
Games and text editors are examples of this kind of program.
* It is still possible to automate a TUI, of course, but the point is that the expected interaction with the program is no longer via newline-delimited streams, but rather via direct, individual key presses as input.
The C Standard says that fflush(stdin) has undefined behavior. You should not use it to flush pending input even on platforms where it seems to have the expected effect. There is no portable way to flush pending input, ie: all input that was typed before the prompt was issued.
If you just want to consume the characters typed by the user for a previous entry parsed with scanf(), up to and including the newline, you can use this simple function:
#include <stdio.h>
// Read and discard the rest of the current line of input.
// Returns EOF at end of file, otherwise returns a newline character
int flush_input(FILE *fp) {
int c;
while ((c = getc(fp)) != EOF && c != '\n')
continue;
return c;
}
If you are required to use scanf(), you can use these 2 calls:
scanf("%*[^\n]"); // read the remaining characters on the line if any.
scanf("%1[\n]"); // read the newline character if present.
Note however that you should not combine these 2 as a single call to scanf() because the first conversion will fail if the pending byte is a newline, and this newline will not be consumed by the second conversion.

How to definitely solve the scanf input stream problem

Suppose I want to run the following C snippet:
scanf("%d" , &some_variable);
printf("something something\n\n");
printf("Press [enter] to continue...")
getchar(); //placed to give the user some time to read the something something
This snippet will not pause! The problem is that the scanf will leave the "enter" (\n)character in the input stream1, messing up all that comes after it; in this context the getchar() will eat the \n and not wait for an actual new character.
Since I was told not to use fflush(stdin) (I don't really get why tho) the best solution I have been able to come up with is simply to redefine the scan function at the start of my code:
void nsis(int *pointer){ //nsis arconim of: no shenanigans integer scanf
scanf("%d" , pointer);
getchar(); //this will clean the inputstream every time the scan function is called
}
And then we simply use nsis in place of scanf. This should fly. However it seems like a really homebrew, put-together-with-duct-tape, solution. How do professional C developers handle this mess? Do they not use scanf at all? Do they simply accept to work with a dirty input stream? What is the standard here?
I wasn't able to find a definite answer on this anywhere! Every source I could find mentioned a different (and sketchy) solution...
EDIT: In response to all commenting some version of "just don't use scanf": ok, I can do that, but what is the purpose of scanf then? Is it simply an useless broken function that should never be used? Why is it in the libraries to begin with then?
This seems really absurd, especially considering all beginners are taught to use scanf...
[1]: The \n left behind is the one that the user typed when inputting the value of the variable some_variable, and not the one present into the printf.
but what is the purpose of scanf then?
An excellent question.
Is it simply a useless broken function that should never be used?
It is almost useless. It is, arguably, quite broken. It should almost never be used.
Why is it in the libraries to begin with then?
My personal belief is that it was an experiment. It tries to be the opposite of printf. But that turned out not to be such a good idea in practice, and the function never got used very much, and pretty much fell out of favor, except for one particular use case...
This seems really absurd, especially considering all beginners are taught to use scanf...
You're absolutely right. It is really quite absurd.
There's a decent reason why all beginners are taught to use scanf, though. During week 1 of your first C programming class, you might write the little program
#include <stdio.h>
int main()
{
int size = 5;
for(int i = 0; i < size; i++) {
for(int j = 0; j < size; j++)
putchar('*');
putchar('\n');
}
}
to print a square. And during that first week, to make a square of a different size, you just edit the line int size = 5; and recompile.
But pretty soon — say, during week 2 — you want a way for the user to enter the size of the square, without having to recompile. You're probably not ready to muck around with argv. You're probably not ready to read a line of text using fgets and convert it back to an integer using atoi. (You're probably not even ready to seriously contemplate the vast differences between the integer 5 and the string "5" at all.) So — during week 2 of your first C programming class — scanf seems like just the ticket.
That's the "one particular use case" I was talking about. And if you only used scanf to read small integers into simple C programs during the second week of your first C programming class, things wouldn't be so bad. (You'd still have problems forgetting the &, but that would be more or less manageable.)
The problem (though this is again my personal belief) is that it doesn't stop there. Virtually every instructor of beginning C classes teaches students to use scanf. Unfortunately, few or none of those instructors ever explicitly tell students that scanf is a stopgap, to be used temporarily during that second week, and to be emphatically graduated beyond in later weeks. And, even worse, many instructors go on to assign more advanced problems, involving scanf, for which it is absolutely not a good solution, such as trying to do robust or "user friendly" input validation.
scanf's only virtue is that it seems like a nice, simple way to get small integers and other simple input from the user into your early programs. But the problem — actually a big, shuddering pile of 17 separate problems — is that scanf turns out to be vastly complicated and full of exceptions and hard to use, precisely the opposite of what you'd want in order to make things easy for beginners. scanf is only useful for beginners, and it's almost perfectly useless for beginners. It has been described as being like square training wheels on a child's bicycle.
How do professional C developers handle this mess?
Quite simply: by not using scanf at all. For one thing, very few production C programs print prompts to a line-based screen and ask users to type something followed by Return. And for those programs that do work that way, professional C developers unhesitatingly use fgets or the like to read a full line of input as text, then use other techniques to break down the line to extract the necessary information.
In answer to your initial question, there's no good answer. One of the fundamental rules of scanf usage (a set of rules, by the way, that no instructor ever teaches) is that you should never try to mix scanf and getchar (or fgets) in the same program. If there were a good way to make your "Press [enter] to continue..." code work after having called scanf, we wouldn't need that rule.
If you do want to try to flush the extra newline, so that a later call to getchar might work, there are several questions here with a bunch of good answers:
scanf() leaves the newline character in the buffer
Using fflush(stdin)
How to properly flush stdin in fgets loop
There's one more unrelated point that ends up being pretty significant to your question. When C was invented, there was no such thing as a GUI with multiple windows. Therefore no C programmer ever had the problem of having their output disappear before they could read it. Therefore no C programmer ever felt the need to write printf("Press [enter] to continue..."); followed by getchar(). I believe (another personal belief) that it is egregiously bad behavior for any vendor of a GUI-based C compiler to rig things up so that the output disappears upon program exit. Persistent output windows ought to be the default, for the benefit of beginning C programmers, with some kind of non-default option to turn that behavior off for those who don't want it.
Is scanf broken? No it is not. It is an excellent input function when you want to parse free form input data where few errors are to be expected. Free form means here that new lines are not relevant exactly as when you read/write very long paragraphs on a normal screen. And few errors expected is common when you read from files.
The scanf family function has another nice point: you have the same syntax when reading from the standard input stream, a file stream or a character string. It can easily parse simple common types and provide a minimal return value to allow cautious programmers to know whether all or part of all the expected data could be decoded.
That being said, it has major drawbacks: first being a C function, it cannot directly control whether the programmer has passed types meeting the format specifications, and second, as beginners are not consistenly hit on their head when they forget to control its return value, it is really too easy to make fully broken programs using it.
But the rule is:
if input is expected to be line oriented, first use fgets to get lines and then sscanf testing return values of both
only if input is expect to be free form (irrelevant newlines), scanf should be used directly. But never without testing its return value except for trivial tests.
Another drawback is that beginners hope it to be clever. It can indeed parse simple input formats, but is only a poor man's parser: do not use it as a generic parser because that is not what it is intended for.
Provided those rules are observed, it is a nice tool consistent with most of C language and its standard library: a simple tool to do simple things. It is up to programmers or library implementers to build richer tools.
I have only be using C language for more than 30 years, and was never bitten by scanf (well I was when I was a beginner, but I now know that I was to blame). Simply I have just tried for decades to only use it for what it can do...

Incomprehensible issue in a loop (C on Clion)

I'm learning C in my school for 2 months and I have to make a Halma's Game in the console, so I'm a newbie for now.
I use Clion and CodeBlock but I prefer Clion for his internal console.
The game work pretty good, but I've got 2 weird issues that I can't fix by myself:
- My loop is presumed to stop with the scanf,but it doesnt.
("saut" variable).
It work only in the 2nd(or more) passage in the loop.
-The variable "h" increment during the loop (in order to ignore the next condition when you are out the loop), but the program always get in.
I don't know why..
Check my code:
MY CODE (IN FRENCH DON'T WORRY ABOUT
Thanks for your help.
Robin.
On some platforms (especially Windows and Linux) you can use fflush(stdin);:
Do modify your code like :-
while(saut==1)
...
....
scanf("%d",&saut);
fflush(stdin);
}
fflush(stdin);
these is another trick to solve this issue :-
It goes into an infinite loop because scanf() will not consumed the input token if match fails. scanf() will try to match the same input again and again. you need to flush the stdin.
if (!scanf("%d", &sale.m_price)) fflush(stdin)

Can we have while loop test two arguments at the same time without &&/||

I was checking Beej's guide to IPC and one line of code took my attention.
In the particular page, the while loop in speak.c has two conditions to check while (gets(s), !feof(stdin)).
So my question is how is this possible as I have seen while look testing only one condition most of the time.
PS: I am little new to these. Will be grateful for any help. Thanks!
The snippet
while (gets(s), !feof(stdin))
uses the comma operator, first it executes gets(s), then it tests !feof(stdin), which is the result of the condition.
By the way don't use gets, it's extremely unsafe. Be wary of sources using it, they probably aren't good sources for learning the language.
The code
while(gets(s), !feof(stdin)) {
/* loop body */
}
is equivalent to
gets(s);
while(!feof(stdin)) {
/* loop body */
gets(s);
}
just more concise as it avoids the repetition of gets before the loop and in the loop body.
A couple of people have already pointed out some of the problems with this. I certainly agree that using gets (at all) is a lousy idea.
I think it's worth mentioning one other detail though: since this uses feof(file) as the condition for exiting the loop, it can/will also misbehave if you encounter an error before the end of the file. When an error occurs, the error flag will be set but (normally) the EOF flag won't be -- and since you can't read from the file any more (due to the error) it never will be either, so this will go into an infinite loop.
The right way to do the job is with fgets, and check its return value:
while (fgets(s, length_of_s, stdin))
process(s);
This tests for fgets succeeding at reading from the file, so it'll exit the loop for either end of file or an error.
One other minor detail: when fgets reads a string, it normally retains the new-line at the end of the line (where gets throws it away). You'll probably have to add a little more code to strip it off is it's present (and possibly deal with a line longer than the buffer you allocated if the newline isn't present).
This test is using the comma operator and has been used as a way of getting the next line of text using gets(s) and testing for end-of-file using !feof(stdin).
This syntax doesn't evaluate two expression. It executes first the gets(s) and then evaluates !feof(stdin) which may be modified by the gets() function call.
It's not a very good way to do it since it both use gets(), which is not a safe function and it's quite uneasy to read for a beginner (hence your question).

How to determine, inside of "while(fscanf != EOF){blah}", if the next fscanf is going to return EOF?

I've got some code executing in a while(fscanf != EOF) loop.
However, even when fscanf has finished executing, I need to keep running that code until some conditions are met.
I mean I guess I could copy/paste the code to outside the while(fscanf) loop, and only use global variables, but that seems messy. Surely someone has encountered something like this before and has a cleaner solution.
Couldn't you just modify the while condition to account for these additional conditions?
while(fscanf(...) != EOF || !(some_other_conditions_met))
You can't - the feof() function only tests for the end of file condition after a a read operation - there is no way of testing if the next operation will fail. You need to change the logic of your program, as C stream I/O doesn't directly support what you are asking for.
The answer to the title of your question is that it's pretty well impossible. Imagine getting a random number and deciding which of two format strings you're going to pass to fscanf. You want an advance prediction whether fscanf will get eof when you don't even know what the random number will be?
The answer to the body of your question is more or less what Andreas Brinck wrote. I have a feeling you might need something more like this though:
for (;;)
{
// .....
eofReached = (fscanf(..) == EOF);
// .....
if (eofReached && otherConditionsMet) break;
// .....
}
Cleaner solutions avoid using scanf/fscanf. It's much less error-prone to read an entire line at a time and to parse the line with sscanf instead.
From the comp.lang.c FAQ: Why does everyone say not to use scanf? What should I use instead?
The entry on feof usage is also relevant.

Resources