using scanf to check input parameters

2019-08-02 16:16发布

问题:

Trying to use scanf to check i have the right amount of inputs ( in this case 2), and the code works fine, but if i put in 1 input it just keeps waiting for a second, and if i put in 3 it just discards the 3rd, nothing i do will ever return the error message. Have searched for an answer, but not found anything i could use, the reason i ask is the text book i am using for this subject has the code exactly the same as i have it here ( i copied out a different example for int_swap word for word, and it doesn't seem to work either? Any ideas? Sorry if this is a stupid or easy question.

#include <stdlib.h>
#include <stdio.h>



void int_sort2(int*, int*);


int
main(int argc, char* argv[])
{
        int x, y;
        printf("Please enter 2 numbers : ");
        if(scanf("%d%d", &x, &y) != 2)
    { 
            printf("Error in numbers entered\n");
        exit(EXIT_FAILURE);
    }
printf("The original order was %d,   %d\n", x, y);
int_sort2(&x, &y);
printf("The sorted order is : %d,    %d\n", x,y);


return 0;
}


void
int_sort2(int *x, int *y)
{
if(*y < *x)
    {
        int temp;
        temp = *x;
        *x = *y;
        *y = temp;

    }

    return;
}

回答1:

As the documentation of scanf said that

On success, the function returns the number of items of the argument list successfully filled.

It will return the number of items that was loaded not the number of item that you just inputted.

solution:

count the number of ints before you scanf it.



回答2:

if i put in 1 input it just keeps waiting for a second

At that point, if the input stream ends (like the end of data from a pipe or by pressing platform specific keys to terminate console input), you will get the error message.

Let's say you built an executable called mytest from the above code. If you use:

echo 20 | ./mytest

you should get the error message.

if i put in 3 it just discards the 3rd, nothing i do will ever return the error message.

Your scanf line looks for two integers. If it find them, it returns them. If there are more data in the stream, it is not responsible for dealing with them. Hence, you don't get any error message if there are more than 2 numbers in the input.

i copied out a different example for int_swap word for word, and it doesn't seem to work either? Any ideas?

Your version of int_swap seems to be fine.



回答3:

Okay, so you have to understand how scanf is actually behaving internally to understand why it's not acting properly.

From the scanf man page:

RETURN VALUE

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.

let's say you have:

#include <stdio.h>

int main() {
    int x, y, rv;
    rv = scanf("%d %d", &x, &y);

    if(rv <  2) {
          fprintf(stderr, "Woops not enough arguments available on input\n");
          return -1;
    } 

    printf("X was %d and Y was %d\n", X, Y);
    return 0;
}

The reason you think that you are experiencing misbehavior is because you are misunderstanding how buffered input works, and you are confused about the fact that scanf will actually care about any input beyond the end of its format string.

The end of format string does NOT indicate end of input or closing of stdin. So in code above if you want to induce an error, run the program and if you are using some *nix just type CTRL+D to indicate EOF on stdin, and it will trigger the if statement provided you haven't entered 2 numbers.

An Aside: Swapping two integers without the use of a temp variable

void swap(int *a, int *b) 
{
     *a ^= *b;
     *b ^= *a;
     *a ^= *b;
}

Or you can define a macro:

#define swap(a, b) do { a ^= b; b ^= a; a ^= b; } while(0)


标签: c scanf