如何使用sscanf确保缓冲区正好是我想要的内容?

9

我希望能够对一行文本进行sscanf操作,并确保其中没有超出我的要求。代码如下:

void parse_init_command(char *buffer, command *new_command) {
    if (sscanf(buffer, 
        "%s %d %d %d %d %d %d %d\n",
        new_command->name,
        &new_command->data[0],
        &new_command->data[1],
        &new_command->data[2],
        &new_command->data[3],
        &new_command->data[4],
        &new_command->data[5],
        &new_command->data[6]) != 8) {
        strncpy(new_command->name, "WRONG_INPUT", 15);
    }
}

When I get an input like:

INIT 9 11 3 1 1 1 9

一切都很好,但像这样的输入

INIT 9 11 3 1 1 1 9 s

也可以接受。我本以为如果添加 "\n",一切都会正常工作,因为我知道每个输入行都以 EOL 结尾,但事实并非如此。


3
scanf会将换行符视为空白字符,就像制表符和空格一样。你可以读取第九个虚拟值,比如强制最大宽度为2的短字符串(%2s),并强制转换的数量不超过8个。 - M Oehm
在传递到此函数之前,您的缓冲区是否已初始化? - bentank
1个回答

2

如果您的输入总是以换行符结尾,那么类似这样的代码就可以实现。该代码需要一个额外的char类型,并检查它是否为\n,以及扫描到的正确数量的项。它打印出1表示成功——这是针对本示例目的而进行的函数略微变化。

#include <stdio.h>

typedef struct {
    char name[100];
    int data[7];
} command;

int parse_init_command(char *buffer, command *new_command) {
    char eol = 0;
    int num = sscanf(buffer, "%s%d%d%d%d%d%d%d%c",
                                new_command->name,
                                &new_command->data[0],
                                &new_command->data[1],
                                &new_command->data[2],
                                &new_command->data[3],
                                &new_command->data[4],
                                &new_command->data[5],
                                &new_command->data[6],
                                &eol);
    return num == 9 && eol == '\n';
}

int main(void)
{
    char inp[50];
    command rec;
    fgets(inp, sizeof inp, stdin);
    printf("%d\n", parse_init_command(inp, &rec) );
    return 0;
}

从键盘启动程序会话:

INIT 9 11 3 1 1 1 9
1

INIT 9 11 3 1 1 1 9 s
0

请注意,在%c之前没有前导空格,否则会跳过空格,从而失去其意义。

2
当用户输入 INIT 9 11 3 1 1 1 9 (末尾有一个空格)时,这将创建一个难以解释的错误。我更喜欢@MOehm在评论中提出的解决方案(针对原始帖子)。 - rici

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接