【问题标题】:Validation using scanf() to protect against string使用 scanf() 进行验证以防止字符串
【发布时间】:2013-11-18 03:10:32
【问题描述】:

我在这里有一个代码,它可以查看用户输入是字符串还是 1-49 范围内的整数。如果我输入“asdas”,则表示无效,如果输入“1-49”中的整数,则表示有效。我在使用此代码时遇到的问题是,如果我输入“2 asda” 它会同时认为它有效和无效,如果我输入“2 2”,它也会认为有效。刚刚发现它也接受“2d”作为有效输入。

for (i = 0; i < 6; i++)
        {

            printf("\nPlease enter the %d winning ticket numbers!: ", i+1);
            if (scanf("%d", (&winningNumbers[i])) == 0 || (winningNumbers[i] <= 0) || (winningNumbers[i] >= 50))
            {
                    inputFlush();
                    printf("\nInvalid Input. Please re-enter.\n") ;
                    i = i - 1;
            }
       }

        for (i = 0; i < 6; i++)
        {
            printf("%d, ", winningNumbers[i]);
        }

【问题讨论】:

    标签: c


    【解决方案1】:

    将整行读入一个字符串(fgets,sn-p 中的第 2 行)。使用sscanf 从字符串中读取数据:读取整数一个字符,一个空格之后。检查sscanf 是否返回不同于 1 的值。如果是,那么您要么在开头有字符串(它返回 0,因为它无法读取整数),要么在末尾有额外的空白字符(即它也匹配%c 格式说明符)。需要空格跳过空格直到行尾(包括存储的\n)。

    printf("\nPlease enter the %d winning ticket numbers!: ", i+1);
    fgets(buffer, size, stdin);
    if (sscanf(buffer, "%d %c", &winningNumbers[i], &c) != 1 || (winningNumbers[i] <= 0) || winningNumbers[i] >= 50))
    {
        // inputFlush(); not needed now that you read the entire line
        printf("\nInvalid Input. Please re-enter.\n") ;
        i = i - 1;
    }
    

    【讨论】:

    • 我发布的代码不应该要求编译器让你更改为字符。请重新检查。
    • 考虑"%d %c" 而不是"%d%c"。当用户输入“12”时,额外的空间会有所帮助。
    • 我一直使用它,因为它清楚地描述了您希望阅读的内容。
    • @Mihai Maruseac(抱歉打扰)“或者您在末尾有额外的 非空白 字符(即它也匹配 %c 格式说明符)。”删除“将换行符实现为 CR-LF (\r\n) 字符对的平台需要空间。”因为那是不正确的。空格会扫描任意数量的空格、制表符、\r、\n、空格。
    • 请将扩展讨论移至Stack Overflow Chat,谢谢:)
    【解决方案2】:

    看看这个例子。

    #define MAX_LINE_SIZE 500
    
    int main(int argc, char** argv)
    {
    
        char line[MAX_LINE_SIZE];
        unsigned int num;
        char *ptr;
    
        while (fgets(line, MAX_LINE_SIZE, stdin) != NULL){
            num = strtol(line, &ptr, 10);
            if (line[0] != '\n' && (*ptr == '\n' || *ptr == '\0')) {
                printf("Your num: %u\n", num); // check num if you need
            } else {
                printf("Error\n");
            }
        }
    
        return 0;
    }
    

    输出:

    12
    Your num: 12
    45
    Your num: 45
    34 2 
    Error
    ads
    Error
    

    这里fgets 函数从标准输入读取数据。 strtol 解析读取字符串并将解析后的数字分配给ptr 指针的字符地址。假设用户只需要输入一个数字(后面没有任何字符),我们必须检查 *ptr 是新行还是行尾。

    line[0] != '\n' 防止空字符串。

    【讨论】:

    • 到目前为止效果惊人。你能给我解释一下吗:)
    • 我理解 strtol 部分,但如果您能向我解释一下您对 null 和新行所做的 if 语句
    • 一个问题是您需要输入另一个输入,直到收到这些消息。
    • 啊,有道理。那是切菜刀,但是如何修复需要再次输入的部分才能使其按预期工作?
    • @Leoc 我会使用计数器变量,在循环的“好”部分增加它并检查它是否等于 6(就像你做的那样)。如果是,则中断。
    【解决方案3】:

    使用peek检查下一个字符,详细信息here。你可以通过这种方式判断它是否好。

    Another SO question 差不多。

    【讨论】:

    • 感谢您的快速评论。我一回到家就试试。
    猜你喜欢
    • 2012-06-14
    • 2020-11-21
    • 1970-01-01
    • 1970-01-01
    • 2013-07-18
    • 1970-01-01
    • 2015-09-05
    • 1970-01-01
    • 2019-04-08
    相关资源
    最近更新 更多