繁体   English   中英

C sscanf 验证输入格式

[英]C sscanf to validate input format

我想编写一个程序,它从用户那里读取一行输入,格式如下: <Name>,<Age>,<City>

  • 名称只能包含英文字母、空格和-
  • 年龄必须是介于 18 到 120 之间的 integer。
  • City 必须包含英文字母和- only。

它们中的每一个都可以是 49 号。我想存储信息并打印一个信息性错误将打印错误输入。

我的代码如下:

    char str[150];
    char input[3][50] = { 0 };
    int num = 0;
    if (fgets(str, 150, stdin) != NULL) {
        num = sscanf(str, "%[a-zA-Z -],%[0-9],%[a-zA-Z-]", input[0], input[1], input[2]);
    }
    if (num < 3) {
        printf("ERROR\n");
    }

问题是对于诸如Name1$#,20,NYBest,19,Rome123Best,100,Paris1$之类的输入不会打印错误,其中城市格式错误(带有尾随字符)。 有什么方法可以使用sscanf解决它?

您可以根据需要使用sscanf()和字符类,但格式字符串存在一些小问题:

  • AZ采用 ASCII 编码或至少是字母连续的编码。
  • 尾随-具有特殊含义,将破折号放在第一个 position 以明确匹配破折号。
  • 没有长度前缀,因此超过 49 个字符的名称或城市将溢出目标数组。

而不是使用fgets() ,您应该手动阅读该行以检测过长的行。

您可以添加额外的%c以检查行尾的额外字符。 如果您不打算使用字段值,则不需要存储转换后的值,但您必须转换数字以检查其值是否在请求的范围内:

    char str[150];
    char name[50];
    char city[50];
    char agestr[4];
    size_t i;
    int c, age, pos, n;

    for (i = 0; (c = getchar()) != EOF && c != '\n'; i++) {
        if (i < sizeof(str) - 1)
            str[i] = (char)c;
    }
    if (c == EOF && i == 0) {
        printf("end of file\n");
        return -1;
    }
    if (i >= sizeof(str)) {
        printf("line too long\n");
        return 0;
    }
    str[i] = '\0';
    pos = 0;
    /* validate the name */
    if (sscanf(str + pos, "%49[-a-zA-Z ]%n", name, &n) != 1 || str[pos + n] != ',') {
        printf("invalid name\n");
        return 0;
    }
    pos += n + 1;
    /* validate the age */
    if (str[pos] == '0' || sscanf(str + pos, "%3[0-9]%n", agestr, &n) != 1 || str[pos + n] != ',') {
        printf("invalid age\n");
        return 0;
    }
    age = atoi(agestr);
    if (age < 18 || age > 120) {
        printf("age out of range: %d\n", age);
        return 0;
    }
    pos += n + 1;
    /* validate the city */
    if (sscanf(str + pos, "%49[-a-zA-Z]%n", city, &n) != 1 || str[pos + n] != '\0') {
        printf("invalid city\n");
        return 0;
    }
    /* Input was validated... proceed */

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM