想象一下,我有一个 csv,每个值都是一个整数。所以第一个值是 INTEGER 100
。
我希望 fscanf() 读取这一行,或者告诉我它只是一个整数,或者不是。所以,它会通过100
但失败100t
。我一直在努力工作的是“%d”,其中逗号是我的 CSV 的分隔符。所以整个功能是
fscanf(fp, "%d,", &count)
不幸的是,这在“100t”上失败,在“100”上有效,在“t”上有效。所以它只是不区分100
和100t
(当然,所有这些数字后跟逗号
改为使用strtol
。
你没有。
问题是这fscanf()
不是很有用。处理它的最佳方法是读取整行(或行的重要部分),然后分析字符串。这是一个例子:
int value;
char *extra;
char buffer[100];
// read in some data from the buffer
fgets(buffer, sizeof buffer, stdin);
// parse out a digit, if we can
i = strtol(buffer, &extra, 0);
此时,您可以检查extra
是否有任何多余的字符,这意味着该行不是纯粹的数字,或者如果extra
指向 的开头buffer
,则意味着没有要解析的数字。
fscanf 实际上比其他一些答案所暗示的要有用得多——但大多数人不太了解它,也不知道如何发挥其全部功能。
有用的点:首先,使用 fscanf 的返回值——它告诉你有多少项目被转换了。其次,“扫描集”转换非常有用。考虑以下内容(我曾经sscanf
避免需要外部文件,但fscanf
仅在它读取的源方面有所不同):
#include <stdio.h>
int main() {
int i;
char *test[] = {
"100,", // should succeed.
"100t,", // should fail.
"t" // should also fail.
};
for (i=0; i<3; i++) {
int count;
char ch[2];
if (2 == sscanf(test[i], "%d%[,]", &count, &ch))
fprintf(stderr, "Conversion of \"%s\" succeeded.\n", test[i]);
else
fprintf(stderr, "Conversion of \"%s\" failed.\n", test[i]);
}
return 0;
}
关于什么
fscanf(fp, "%d%c", &count, &aChar)
如果 aChar != ',' && != '\n' 那么你不只有一个整数
非 100% 控制的输入上的 scanf-functions 可能会很痛苦,这样才能避免错误,最好使用 fgets() 读取行,然后使用 strtok() 将行拆分为标记,然后可以转换。
在像“100t”这样的令牌上使用atoi将产生0,而“100”将产生100
scanf()
函数族不太擅长检测这种错误。这并非不可能(请参阅 Jerry Coffin 的回答,该回答有效,但 IMO 难以概括),但 IMO 并没有那么强大。更好的选择是将fgets()
输入读取为文本,使用strtok()
或类似标记,然后使用strtol()
或strtod()
将标记转换为数值:
char buffer[LINE_SIZE];
while (fgets(buffer, sizeof buffer, inFile))
{
char *token;
char *newline = strchr(buffer, '\n');
if (newline)
*newline = 0;
token = strtok(buffer, ",");
while (token)
{
char *chk;
int value = (int) strtol(token, &chk, 10);
if (!isspace(*chk) && *chk != 0)
{
printf("%s is not a valid integer\n", token);
}
else
{
printf("successfully read integer value %d\n", val);
}
token = strtok(NULL, ",");
}
}
if (feof(inFile))
{
printf("Hit end-of-file\n");
}
else
{
printf("Error during read\n");
}