I wrote a code that requires two nested loops, I tried to create a control mechanism to prevent loops to entering an infinite loop if user enter except two double variable; but for example if I enter an char, it is entering infinite loop again. Which part I need to edit?(It will work as long as the user enters two double variables, the program will terminate if the user enters in a different variable type, but it does not end in the following code, it enters an infinite loop) edit1;Thanks to @EugeneSh fixed the first problem of this code(control==scanf("%lf %lf",&a,&b) should be(control=...)Iam controlling control and flag variable twice ,is there any way to do this better? edit2; when i add if(control==2 &&flag==1) this expression after while(flag==1) this code works without problem,problem is solved.
int flag=1;
int control=2;
double a,b;
while(flag==1){
...
while(control==scanf("%lf %lf",&a,&b)){
if(control==2 &&flag==1){
....
break;
}
else{
flag =0 break;
}
}
}
Let's suppose you type in something like c2.0Enter - the input stream will contain the sequence {'c', '2', '.', '0', '\n'}
.
The %lf
conversion specifier tells scanf
to read and discard any leading whitespace, then read up to the next character that is not part of a floating-point constant. The first character it sees is c
, which is not part of a floating point constant, so it stops reading at that point. a
and b
are not updated, that 'c'
character is not removed from the input stream, and scanf
returns 0
to indicate there were no successful conversions or assignments.
Even better is if you have bad input embedded in good input - if you type in 123c5
, scanf
will convert and assign 123.0
to a
, leave b
unmodified, and return 1
, whereas you'd ideally like to reject the whole thing.
The best way to address this is to abandon scanf
altogether. Instead, read the input as text using fgets()
and convert it using strtod
. That way you can catch bad input without it leaving crap in the input stream:
#include <stdlib.h>
#include <string.h>
#define INPUT_SIZE 80
/**
* Reads the next two floating point inputs from the specified input stream.
* Returns the number of valid inputs read and assigned.
*/
int get_inputs( double *x, double *y, FILE *stream )
{
char input[INPUT_SIZE];
double *ptr[2] = {x, y};
size_t i;
/**
* Read the next line from the input stream - if there's an error,
* we return 0.
*/
if ( !fgets( input, sizeof input, stream ) )
return 0;
/**
* Otherwise, split the input into whitespace-separated tokens,
* then try to convert each token to a double using strtod.
*/
char *tok = strtok( input, " \t\n\f" );
for ( i = 0; i < 2; i++ )
{
char *chk;
/**
* After calling strtod, chk will point to the first character
* that is not part of a valid floating-point constant. If this
* character is not whitespace or 0, then the input is bad and
* we break out of the loop.
*/
double tmp = strtod( tok, char &chk );
if ( !isspace( chk ) && *chk != 0 )
break;
/**
* Write this double value to the appropriate argument - ptr[0]
* corresponds to x, ptr[1] corresponds to y.
*/
*ptr[i] = tmp;
/**
* Get the next token in the sequence:
*/
tok = strtok( NULL, " \t\n\f" );
}
return i;
}