常见的宏读取输入数据,并检查它的有效性 [英] Common macro to read input data and check its validity

查看:111
本文介绍了常见的宏读取输入数据,并检查它的有效性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Stack Overflow上看到许多类似的问题重复,它们是从标准输入与一个输入数据项的阅读和检查它的有效性。

I saw on Stack Overflow that many similar questions are repeated and they are related to the reading of one input data item from stdin and check its validity.

数据可能是整数%D,双%F,字符串%S,无符号整型%U ...

The data could be integer "%d", double "%f", string "%s", unsigned int "%u"...

和我想开发一种可用于这些问题的大多数共同的宏。

And I want to develop a common macro which could be used for the majority of these questions.

问题示例1

在OP可能会问:


  • 扫描输入数据

  • 的数据应该是整数,那么 11A AAA aa44 ,...输入是不允许的。只有整数,后面跟一个空格(参考 isspace为())允许

  • 其他条件可能是这个问题像present:输入整数应> 3 < 15

  • scan the input data
  • the data should be integer so 11a, aaa, aa44,... inputs are not allowed. Only integer followed with a white space (refer to isspace()) is allowed
  • other conditions could be present in the question like: input integer should be >3 and <15

问题示例2

在OP可能会问:


  • 扫描输入数据

  • 数据应该是双所以 11.2a AAA aa44.3 ,...输入是不允许的。双人床遵循的空白(参见 isspace为())允许

  • 其他条件可能是像这个问题present:输入双应&GT; 3.2 &LT; 15.0

  • scan the input data
  • the data should be double so 11.2a, aaa, aa44.3,... inputs are not allowed. Only double followed with a white space (refer to isspace()) is allowed
  • other conditions could be present in the question like: input double should be >3.2 and <15.0

是否有可能开发像

#define SCAN_ONEENTRY_WITHCHECK(FORM,X,COND)
// FORM: format of the input data like "%d", "%lf", "%s"
// X: address where to store the input data
// COND: condition to add in the check of the input data

....

// example of calling the macro in the main()

int a;
SCAN_ONEENTRY_WITHCHECK("%d", &a,(a>3 && a<15))

宏应该扫描的数据,如果满足下列条件之一是不正确的,然后打印一条消息给用户,要求他重新输入。并重复,直到用户输入有效的数据?

The macro should scan the data and IF one of the following criteria is not true then print a message to the user asking him to enter again. and repeat that until the user enters valid data?

标准:

  • input data type should be the same indicated by format
  • input data should be followed by white space indicated in the isspace()
  • input data should be valid the condition COND

推荐答案

有关这个问题的一个快速的回答将是

A quick answer for this question will be

#define SCAN_ONEENTRY_WITHCHECK(FORM,X,COND)\
   while(scanf(" "FORM, X)<1 || !(COND))
      printf("Invalid input, enter again: ");

要求在code上面的宏用下面的方式

calling the above macro in the code with the following way

int a; 
SCAN_ONEENTRY_WITHCHECK("%d", &a, (a>3 && a<15))

等同于本

int a;
while(scanf(" %d", &a)<1 || !(a>3 && a<15))
    printf("Invalid input, enter again: ");

但因为如果用户例如输入上面的答案是错的 AAA 作为输入,那么上面的code会导致一个无限循环,因为标准输入没有清理因为 AAA 输入不被逮住scanf函数(%d个,&安培; A)。因此,我们有,如果用户输入一个这样的输入以添加清洁标准输入的东西。加入 scanf函数(%* [^ \\ n])可能是一个解决方案。和上面的code将

but the above answer is wrong because if the user enter for example aaa as input then the above code will result an infinite loop because the stdin is not cleaned because the aaa input is not catched by the scanf(" %d", &a). So we have to add something that clean the stdin if the user enter a such input. adding scanf("%*[^\n]") could be a solution for that. and the above code will be

int a;
while(scanf(" %d", &a)<1 || !(a>3 && a<15)) {
    scanf("%*[^\n]"); // clean stdin
    printf("Invalid input, enter again: ");
}

但上面code还含有一种限制。例如,如果用户输入一个有效的整数( 20 )和INTEGR不尊重的条件(A&GT; 3及和放大器; A&LT; 15 )。在这种情况下,我们没有清洁标准输入,因为它已经清洗干净,否则用户将被要求输入数据的2倍。 TIS问题coud解决了以下解决方案:

but the above code still contains a limitation. For example If the user enter a valid integer (20) and the integr does not respect the condition (a>3 && a<15). In this case we do not have to clean the stdin because it's already cleaned otherwise the user will be asked for input data for 2 times . tis problem coud solved with the following solution:

int a;
int c;
while((c=(scanf(" %d", &a)<1)) || !(a>3 && a<15)) {
    if (c) scanf("%*[^\n]"); // clean stdin
    printf("Invalid input, enter again: ");
}

以上code不尊重的标准输入数据应遵循的空格例如,如果用户输入 10abc 作为输入,那么上面的code将赶上10作为输入整数,它会清理剩下的 ABC 。如果我们检查下一个charachter是一种白色空间(与 isspace为()功能)闲来无事

The above code does not respect the criteria input data should be followed by white space for example if the user enter 10abc as input then the above code will catch 10 as input integer and it will clean the rest abc. this problem could be solved if we check that the next charachter is a white space (with isspace() function) nothing else

int a;
char tmp;
int c;
while((c=(scanf(" %d%c", &a, &tmp)!=2 || !isspace(tmp))) || !(a>3 && a<15)) {
    if (c) scanf("%*[^\n]"); // clean stdin
    printf("Invalid input, enter again: ");
}

现在,如果我们想回去的宏。宏code将是:

And now if we want to go back to the macro. the macro code will be:

#define SCAN_ONEENTRY_WITHCHECK(FORM,X,COND) \
do {\
    char tmp;\
    int c;\
    while ((c=(scanf(" "FORM"%c", X, &tmp)!=2 || !isspace(tmp)))\
            || !(COND)) {\
        if (c) scanf("%*[^\n]");\
        printf("Invalid input, please enter again: ");\
    }\
} while(0)

添加做{...}而(0)宏可以通过这个来解释<一个href=\"http://stackoverflow.com/questions/13993011/difference-between-macros-with-and-without-using-do-while\">link

Adding do {...} while(0) in the macro could be explained by this link

上面的宏可以以另一种方式writen

The above macro could be writen in another way

#define SCAN_ONEENTRY_WITHCHECK(FORM,X,COND) \
do {\
    char tmp;\
    while(((scanf(" "FORM"%c",X,&tmp)!=2 || !isspace(tmp)) && !scanf("%*[^\n]"))\
            || !(COND)) {\
        printf("Invalid input, please enter again: ");\
    }\
} while(0)

使用的宏例子:

int main()

{
    int decision;
    double q;
    char buf[32];

    printf("Input data, valid choice 1 or 0: ");
    SCAN_ONEENTRY_WITHCHECK("%d",&decision,(decision==0 || decision==1));
    printf("You have entered good input : %d\n", decision);

    printf("Input unsigned double: ");
    SCAN_ONEENTRY_WITHCHECK("%lf",&q, (q == (unsigned int) q));
    printf("You have entered good input : %lf\n", q);

    printf("Input name: ");
    SCAN_ONEENTRY_WITHCHECK("%s",buf, (strcmp(buf,"kallel")==0));
    printf("You have entered good input : %s\n", buf);

    printf("Input data should be valid integer: ");
    SCAN_ONEENTRY_WITHCHECK("%d",&decision,1);
    // COND is 1 ==> we do not have any check in the input integer
    printf("You have entered good input : %d\n", decision);
}

执行

$ ./test
Input data, valid choice 1 or 0: 4
Invalid input, please enter again: a4
Invalid input, please enter again: a1
Invalid input, please enter again: 1a
Invalid input, please enter again: 1
You have entered good input : 1
Input unsigned double: 2.3
Invalid input, please enter again: a.0a
Invalid input, please enter again: 2.0a
Invalid input, please enter again: a2.0
Invalid input, please enter again: 2.0
You have entered good input : 2.000000
Input name: an
Invalid input, please enter again: anyad
Invalid input, please enter again: adny
Invalid input, please enter again: any
You have entered good input : any
Input data should be valid integer: 2.5
Invalid input, please enter again: -454f
Invalid input, please enter again: -454
You have entered good input : -454

这篇关于常见的宏读取输入数据,并检查它的有效性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆