fscanf(input_fp, "%30[^ ,\n\t]%30[^ ,\n\t]%30[^ ,\n\t]", ...
不使用文本文件中的 ',' 和 '\n'。随后的 fscanf() 尝试也失败并返回值 0,这不是 EOF,会导致无限循环。
fscanf() 解决方案,fgets()/sscanf() 更好地处理潜在的 IO 和解析错误:
main()
{
FILE *input_fp;
FILE *output_fp;
char buf[100];
while (fgets(buf, sizeof buf, input_fp) != NULL)
{
char name[30]; // Insure this size is 1 more than the width in scanf format.
char age_array[30];
char occupation[30];
#define VFMT " %29[^ ,\n\t]"
int n; // Use to check for trailing junk
if (3 == sscanf(buf, VFMT "," VFMT "," VFMT " %n",
name, age_array, occupation, &n) && buf[n] == '\0')
{
// Suspect OP really wants this width to be 1 more
if (fprintf(output_fp, "%-30s%-30s%-30s\n", name, age_array, occupation) < 0)
break;
} else
break; // format error
}
fclose(input_fp);
fclose(output_fp);
}
不调用 ferror(),而是检查 fgets()、fprintf() 的返回值。
怀疑 OP 的未声明字段缓冲区为 [30] 并相应调整了 scanf()。
关于if (3 == sscanf(buf, VFMT "," ...的详细信息
if (3 == sscanf(...) && buf[n] == '\0') { 在以下情况下变为真:
1) 正是 3 个 "%29[^ ,\n\t]" 格式说明符,每个 scanf 至少有 1 个字符。
2) buf[n] 是字符串的结尾。 n 通过“%n”说明符设置。 "%n" 中的前面的 ' ' 会导致使用最后一个 "%29[^ ,\n\t]" 之后的任何后续空格。 scanf() 看到“%n”,它指示它设置从扫描开始的当前偏移量,以分配给 &n 指向的 int。
"VFMT "," VFMT "," VFMT " %n" 被编译器连接到
" %29[^ ,\n\t], %29[^ ,\n\t], %29[^ ,\n\t] %n".
我发现前者比后者更容易维护。
" %29[^ ,\n\t]" 中的第一个空格指示 sscanf() 扫描(使用而不是保存)0 个或多个空格(' '、'\t'、'\n' 等)。其余部分指示 sscanf() 使用并保存除 ','、'\n'、'\t' 之外的任何 1 到 29 个字符,然后附加一个 '\0'。