虽然您通常会使用 C++ iostream 库进行文件 I/O,但没有任何内容表明您不能使用诸如 fscanf 之类的 C 函数 fscanf -- 只要您正确使用它们(通常它们会比iostream 方法更快)
在您的情况下,您有很多数字,中间有一些文本,您正试图在循环中使用fscanf 阅读。很好,很简单,但是……你必须正确处理 匹配失败 情况当您尝试使用"%08x" 转换说明符 读取's' 时会发生。
当发生匹配失败时,从流中提取的字符会在失败点停止,以导致失败的字符开头的所有内容(以及后面的内容)未读 在输入缓冲区中。除非您从输入流中正确提取导致 匹配失败 的字符,否则您可能会遇到无限循环,因为导致失败的字符仍未被读取,只是在等待下一次尝试读取时再次咬您。
那么,如何处理匹配失败? cctype 标头提供了 isdigit 宏,它允许您简单地测试输入流中的下一个字符是否是数字。您首先使用fgetc(或getc - 相同但通常作为宏实现)读取字符,然后使用isdigit 进行测试,例如
int c = fgetc(in_file); /* read next char */
while (c != EOF && !isdigit(c)) /* check EOF and isdigit */
c = fgetc(in_file); /* get next char */
在您阅读下一个字符的上方,然后输入一个循环来验证您尚未到达EOF,然后检查c 是否不是数字。如果满足这些条件,则再次检查下一个字符,直到达到EOF 或者在输入流中找到下一个数字。但是现在你有一个问题,你已经从流中读取了数字,fscanf 怎么能将它作为下一个整数的一部分读取?
简单——放回输入流中:
if (c != EOF) /* if not EOF, then digit */
ungetc (c, in_file); /* put back for next read */
现在您可以通过简单的循环从in_file 中读取所有 64 个整数值,例如
while (1) { /* loop continually until EOF */
int rtn = fscanf (in_file,"%08x", &number1); /* validate return */
if (rtn == EOF) /* if EOF, break loop */
break;
else if (rtn == 0) { /* handle matching failure */
int c = fgetc(in_file); /* read next char */
while (c != EOF && !isdigit(c)) /* check EOF and isdigit */
c = fgetc(in_file); /* get next char */
if (c != EOF) /* if not EOF, then digit */
ungetc (c, in_file); /* put back for next read */
}
else /* good read, output number */
fprintf (out_file, "%08x\n", number1);
}
(注意:您的输出文件已从 in_file1 重命名为 out_file -- 始终使用有意义的变量名)
现在进行一些清理。当您打开 in_file 时,您验证文件是否已打开以供阅读。很好,但是对于您exit (-1); 的错误情况。不要向外壳返回负值。您有两个常量来指示成功/失败名称EXIT_SUCCESS (0) 和EXIT_FAILURE(值1,不是-1)。
虽然您确实检查了in_file 是否已打开以供读取,但您完全没有检查您的输出文件是否已打开以供写入?始终验证所有输入/输出流和 I/O 函数的返回。否则尝试写入处于错误状态的流会调用未定义行为。
总而言之,你可以这样做:
#include <cstdio>
#include <cstdlib>
#include <cctype>
using namespace std;
int main (void) {
unsigned int number1;
FILE* in_file = fopen ("example.txt", "r");
FILE* out_file = fopen ("wrte.txt", "w");
if (!in_file) { /* validate file open for reading */
printf ("oops, file can't be read\n");
exit (1); /* don't return negative values to the shell */
}
if (!out_file) { /* validate file open for writing */
printf ("oops, file can't be read\n");
exit (1); /* don't return negative values to the shell */
}
while (1) { /* loop continually until EOF */
int rtn = fscanf (in_file,"%08x", &number1); /* validate return */
if (rtn == EOF) /* if EOF, break loop */
break;
else if (rtn == 0) { /* handle matching failure */
int c = fgetc(in_file); /* read next char */
while (c != EOF && !isdigit(c)) /* check EOF and isdigit */
c = fgetc(in_file); /* get next char */
if (c != EOF) /* if not EOF, then digit */
ungetc (c, in_file); /* put back for next read */
}
else /* good read, output number */
fprintf (out_file, "%08x\n", number1);
}
fclose (in_file);
fclose (out_file);
}
示例输出文件
$ cat wrte.txt
01000000
01000000
01000000
01000000
...
01000000
所有 64 个值均已写入,您可以使用 wc -l 确认,例如
$ wc -l < wrte.txt
64
查看一下,如果您还有其他问题,请告诉我。如果您使用的是 iostream 库,同样的逻辑也适用,函数名称略有不同(有些相同),而是作为成员函数实现。