I want to get an int and a float in the same line using scanf() which I know how to do, but I also want to be able to quit by entering one input ("-1") how can I do this?
while (input != -1){
printf("Enter: ");
scanf("%d %f", &input1, &input2);
if(input1 == -1){
input = -1;
}
CodePudding user response:
This shows a crude method to do it by asking scanf
to scan for spaces and tabs between the two inputs. If the user enters only one input and presses Enter/Return, there will be a newline character in the stream, and scanf
will not accept it for the space and tab request. It will return 1 to indicate only one input was assigned.
For demonstration, sscanf
is used in place of scanf
.
In %*[ \t]
, the *
tells scanf
not to store any results from this conversion, and [ \t]
says to match one or more space or tab characters. If there is a new-line character in the buffer after the “-1”, this match will fail, and scanf
will stop.
Note this is fragile; if the user enters a space or tab after “-1”, it will match the %*[ \t]
, and then scanf
will continue with the %d
.
Also note that using scanf
in this way is largely used for facilitating early learning of programming. Later on, more refined input processing is done with other techniques.
#include <stdio.h>
static void Test(const char *Input)
{
printf("Sample input is %s", Input);
int input1;
float input2;
int result = sscanf(Input, "%d%*[ \t]%f", &input1, &input2);
switch (result)
{
case EOF:
printf("Error, input failure occurred.\n");
break;
case 0:
printf("Error, no inputs read.\n");
break;
case 1:
if (input1 == -1)
{
printf("User entered -1.\n");
#if 0
/* When doing this with input from a stream, instead of a string, you may
wish to include this code to consume the rest of the line the user
entered.
*/
// Consume rest of line.
int c;
do
c = getchar();
while (c != EOF && c != '\n');
#endif
}
else
printf("Error, only one input but is not -1.");
break;
case 2:
printf("Two inputs: %d and %f.\n", input1, input2);
break;
}
}
#define NumberOf(a) (sizeof (a) / sizeof *(a))
int main(void)
{
const char *SampleLines[] =
{
"2 3.5\n",
"-1\n",
};
for (size_t i = 0; i < NumberOf(SampleLines); i)
Test(SampleLines[i]);
}
CodePudding user response:
Given the following conditions:
- each line contains exactly one or two inputs
- the first input is always a valid integer
- using only one
scanf()
family function
then you cannot do it in C. There must be a logical break to decide how to continue processing the line somewhere, and a single scanf()
can’t do it alone.
Option 1 • Break input into lines and then process with scanf
Eric Postpischil’s answer shows a way to do it if you preprocess each line as a separate input string — by transforming EOL into EOF (or, more accurately, end of string).
You can break input into lines any way you feel comfortable. The simplest and least problematic way would be to use a library function like fgets()
or readline()
.
Option 2 • Invoke scanf
multiple times
It is as simple as saying:
while (1)
{
if (scanf( "%d", &input1 ) != 1) break;
if (input1 == -1) break;
if (scanf( "%f", &input2 ) != 1) complain_or_something();
do_stuff_with_inputs( input1, input2 );
}
The brevity trap
C’s syntax encourages programmers to try to write things with brevity, but this should not be your goal. Rather, your goal should be readability and correctness — even if this means code that requires two or three lines to express itself.
If you find that a specific chunk of code would definitely benefit from some higher-level abstractions, write a helper function:
bool read_int_and_float( int * n, float * f )
{
if (scanf( "%d", n ) != 1) return false; // EOF or error --> false
if (*n == -1) return false; // first input == -1 --> false
if (scanf( "%f", f ) != 1) return false; // EOF or error --> false
return true; // both inputs good --> true
}
That function cannot be misread, and as it only does one task (obtaining a specifically-formatted line of input), managing your headspace becomes a billion times easier.
So now you can write brief, readable code where it counts:
while (read_int_and_float( &input1, &input2 ))
{
do_stuff_with_inputs( input1, intput2 );
}
You will find that correct and readable code lends itself to rather succinct structures anyway, but don’t shoot yourself in the foot by limiting yourself with a desire to be too pretty.
CodePudding user response:
In this case you want to use a do-while loop, this loop will executes at least one time and will loop until you enter a -1. You can change the condition in the while to satisfy your needs.
do{
printf("Enter: ");
scanf("%d %f", &input1, &input2);
}while(input1 != -1);