为什么scanf会忽略最后一个值?
我想从命令行读取一行CSV。用户以为什么scanf会忽略最后一个值?,c,string,parsing,csv,scanf,C,String,Parsing,Csv,Scanf,我想从命令行读取一行CSV。用户以age,HH:MM:SS,number的形式输入它 我写了以下内容: 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时
age,HH:MM:SS,number
的形式输入它
我写了以下内容:
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]
而是使用类似于时间戳[16]
的东西。在这种情况下,名称长度可以最大为16
另外,
%8
最多消耗8个字符。这是另一个原因。在scanf()和UB中使用的弱格式
%8[^,]
(读取8个非'的char
,“
)将“HH:MM:S”读入太小的空间。因此,如果未定义的将8char
和空字符存储到时间戳[8]
中的行为没有杀死代码,那么尝试读取第二个S
并与匹配将停止扫描。不检查返回值(一个大的no-no),进一步隐藏了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()
这则广告由“练习安全输入”委员会提供。如果您不确定逗号之间的字符串长度,可以扫描整数和逗号。使用%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;
}
#包括
#包括
#包括
int main()
{
字符*逗号=空;
char csv1[]=“23,abcdefghijklmnop,9”;
字符时间戳[9]=“”;
int年龄=0;
整数=0;
int=0;
if((sscanf(csv1,“%d,%n%8[^,]”,&age,&used,timestamp))==2){
如果((逗号=strpbrk(csv1+使用,“,”)){
if((sscanf(逗号,,%d,&数字))==1){
printf(“%d,%s,%d\n”,年龄、时间戳、编号);
}
}
}
返回0;
}
您有一个可以装8升水(时间戳[8])的桶,正在倒入15升水(abcdefghijklmno)。为什么你对桶里只有8升感到惊讶?我假设%8只读取了前8升。有没有办法让它在8之后停止读取并跳到下一个字段?好吧,您告诉scanf需要8个字符,后跟一个逗号。但是在加载了这8个字符之后,您没有逗号,您有一个i
,因此其余的扫描模式失败代码>-->字符时间戳[9]代码>允许nul终止符。问题是,我不想增加最大长度;我只是想让它在读取8个字符后找到下一个整数。这可能是因为scanf吗?