使用sscanf从fgets读取

时间:2017-09-16 23:42:19

标签: c

我对编程还有点新意,我在编译程序时收到此警告:

warning: too many arguments for format [-Wformat-extra-args]
int c = sscanf(Input, "%f %f %*[^\n]%*d", &start, &end, &rows);
                      ^~~~~~~~~~~~~~~~~~

这是我的代码:

fgets(Input, 256, stdin);
int count = 0;
char *token = strtok(Input, " \n\t");
count++;

while(token != NULL)
{
    token = strtok(NULL, " \n\t");
    count++;
}

if(count == 3)
{
    int c = sscanf(Input, "%f %f %*[^\n]%*d", &start, &end, &rows);
    if(c != 3)
    {
        printf("\nError: Illegal input!\n");
    }
}

如果有三个单独的字符串,我尝试做的是读取三个数字。我知道sscanf可用于验证输入(因为它返回成功扫描的次数)。

例如,这些数字为1 6 8 它应该打印"非法输入"对于像0 ab 19这样的输入。

我也尝试将令牌存储到一个字符串数组中,但是在验证方面存在问题。

所以我想问的是,这是正确的方法吗?

提前致谢。

1 个答案:

答案 0 :(得分:2)

您的代码失败有两个原因:

  • 您使用strtok()执行的解析修改了Input数组,因此使用sscanf()的后续转换将失败,因为只会看到第一个字段。
  • 格式字符串"%f %f %*[^\n]%*d"包含float值的2个转换规范和2个带抑制存储的转换。传递3个目标参数不正确。

以下是如何在一次通话中执行转换和验证的方法:

int read_values(void) {
    char input[256];
    char str[256];
    float start, end;
    int rows;
    char c;

    if (fgets(input, sizeof(input), stdin)) {
        *string = '\0';
        if (sscanf(input, "%f%f%d %c", &start, &end, &rows, &c) == 3) {
            // start, end and rows were read and converted properly
            // you might way to perform further validation steps on their values.
        } else
        if (sscanf(input, "%s%f%f%d %c", str, &start, &end, &rows, &c) == 4) {
            // there was an initial word before the 3 numbers
        } else {
            printf("Error: invalid input: %s", input);
            return -1;
        }
        return 0;
    } else {
        printf("Error: premature end of file\n");
        return -1;
    }
}

sscanf()将返回3,当且仅当它可以转换2个浮点数和一个整数时,除了尾随空白之外,该行上不存在其他字符。数字之间的空白和空白也被忽略了。

如果可选字符串可以包含多个单词,则可以使用迭代方法:您可以尝试跳过单词,直到解析成功或输入完全消耗为止:

#include <stdio.h>
#include <string.h>

int read_values(void) {
    char input[256];
    float start, end;
    int i, rows;
    char c;

    if (fgets(input, sizeof(input), stdin)) {
        for (i = 0;;) {
            if (input[i] == '\0') {
                printf("Error: invalid input: %s", input);
                return -1;
            }
            if (sscanf(input + i, "%f%f%d %c", &start, &end, &rows, &c) == 3) {
                break;
            }
            i += strspn(input + i, " \t\n");   // skip white space
            i += strcspn(input + i, " \t\n");  // skip a word
        }
        // The initial string has `i` characters
        // start, end and rows were read and converted properly
        // you might want to perform further validation steps on their values.
        printf("string: %.*s\n", i, input);
        printf("start: %f\n", start);
        printf("end: %f\n", end);
        printf("rows: %d\n", rows);
        return 0;
    } else {
        printf("Error: premature end of file\n");
        return -1;
    }
}