sscanf 通配符多字符串 %s 不是 return 第一个字符串对吗?

sscanf Wildcard multi string %s not return first string rightly?

我正在使用 sscanf 来读取字符串。字符串被 space 分割。 sscanf 不是 return 第一个字符串。 代码如下:

#include<stdio.h>
#include<stdlib.h>

int main(int argc, char** argv) {
    char TransactionID[15], CardID[8];
    char Datetime[50];
    int Amount;
    char * s="aaaabbbbcccc defadbed 2020:04:29:23:07:00 1234";
    sscanf(s,"%s %s %s %d", TransactionID, CardID, Datetime, &Amount);
    printf("s[0] = %c\n", s[0]);
    printf("amount = %d\n", Amount);
    printf("TransactionID = %s\n", TransactionID);
    printf("CardID = %s\n", CardID);
    printf("Datetime = %s\n", Datetime);
    return 0;
}

输出为:

s[0] = a
amount = 1234
TransactionID =
CardID = defadbed
Datetime = 2020:04:29:23:07:00

TransactionID 不是 return 正确的结果。不过其他都对。

您的代码中存在缓冲区溢出:CardID 只有 8 个字节长。虽然输入字符串中的卡 ID 为 8 个字符,但末尾的终止 NUL 字节还需要另一个字节。将 CardID 的声明更改为:

char TransactionID[15], CardID[9];

应该修复解析这个特定输入字符串的问题。

但是,如果输入有误,或者有人恶意地为您输入比您的代码预期更长的卡 ID,您仍然会 运行 遇到问题。因此,您应该确保永远不会发生缓冲区溢出。

一种方法是告诉 scanf() 每个缓冲区有多大,如下所示:

sscanf(s,"%14s %7s %49s %d", TransactionID, CardID, Datetime, &Amount);

请注意,您必须再次指定比缓冲区大小小一的值。所以如果要处理 8 个字符的卡 ID,你仍然需要将缓冲区大小设置为 9 个字节。然而,虽然这可以防止缓冲区溢出,但如果输入字符串大于缓冲区,其余的将被静默 t运行 处理,或者下一个 %s 转换可能会选择剩余的字符。

如果您知道输入是由空格分隔的,那么另一种方法是使用 strtok() 将输入拆分为各个部分。