为什么 scanf 忽略了最后一个值?

4

我希望能从命令行中读取CSV文件的一行。用户输入的格式为年龄,HH:MM:SS,数字

我已经写了以下代码:

int age;
char timestamp[8];
int number;

scanf("%d,%8[^,],%d", &age, timestamp, &number;
printf("%d, %s, %d", age, timestamp, number);

当我输入23, abcd, 9时,它会打印出23, abcd, 9
当我输入23, abcdefghijklmno, 9时,它会打印出23, abcdefgh, 0

我该怎么解决这个问题?


你有一个可以装8升水(时间戳[8])的桶,并倒入了15升(abcdefghijklmno)的水。为什么你会惊讶只有8升的水能装进桶里? - Marc B
我以为%8只会读取前8个字符。有没有一种方法让它在读到8个字符后停止读取并跳到下一个字段? - Matt
2
好的,你告诉scanf期望8个字符,后面跟着一个逗号。但是在这8个字符被加载之后,你没有逗号,而是有一个“i”,所以扫描模式的其余部分失败了。 - Marc B
4
注意:将 char timestamp[8]; 改为 char timestamp[9]; 以允许使用空终止符。 - Weather Vane
3个回答

3
scanf()中使用的弱格式和UB %8[^,](读取8个不是','的字符)将" HH:MM:S"读入空间过小的timestamp[8],如@Weather Vane所述。因此,将8个char和一个空字符存储到timestamp[8]中的未定义行为,如果不破坏代码,则尝试读取第二个S并与','匹配将停止扫描@Marc B。未检查返回值(一个大忌),进一步隐藏了未写入number的事实。
char timestamp[8];
//     12345678
// age, HH:MM:SS, number
scanf("%d,%8[^,],%d", &age, timestamp, &number;`

相反

char buf[100];
fgets(buf, sizeof buf, stdin);

// 1 bigger for the null character
char timestamp[8+1];

//                  v-- add space              check result --v
if (sscanf(buf, "%d, %8[^,],%d", &age, timestamp, &number) == 3) {
  printf("%d, %s, %d", age, timestamp, number);
} else {
  puts("Input data scan failed");
}

scanf() 是有害的。为了节省时间,避免头痛,请使用 fgets()
此广告由“安全输入实践委员会”提供。



1
如果您不确定逗号之间的字符串长度,可以扫描整数和逗号。使用%n格式说明符捕获扫描到的字符数。扫描字符串的前8个字符。然后使用strpbrk查找下一个逗号,并扫描该逗号和最后一个整数。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


int main()
{
    char *comma = NULL;
    char csv1[] = "23, abcdefghijklmnop, 9";
    char timestamp[9]= "";
    int age = 0;
    int number = 0;
    int used = 0;

    if ( ( sscanf ( csv1, "%d ,%n %8[^,]", &age, &used, timestamp)) == 2) {
        if ( ( comma = strpbrk ( csv1 + used, ","))) {
            if ( ( sscanf ( comma, ",%d", &number)) == 1) {
                printf ( "%d, %s, %d\n", age, timestamp, number);
            }
        }
    }
    return 0;
}

1

看一下。 声明一个小尺寸.. 时间戳[8]

最好有像时间戳[16]这样的东西。在这种情况下,名称长度可以最大为16。

另外%8会消耗多达8个字符。所以这是另一个原因。


问题是,我不想增加最大长度;我只想在读取8个字符后找到下一个整数。用scanf可能实现吗? - Matt

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