fscanf在返回之前读取空格分隔的数据
我试图从txt文件中读取数据。txt文件有多个条目,每个条目占用一个新行,每个条目都有由一些符号分隔的可变长度的十六进制字节数据(如空格“”)。示例txt文件如下所示fscanf在返回之前读取空格分隔的数据,c,delimiter,scanf,eol,C,Delimiter,Scanf,Eol,我试图从txt文件中读取数据。txt文件有多个条目,每个条目占用一个新行,每个条目都有由一些符号分隔的可变长度的十六进制字节数据(如空格“”)。示例txt文件如下所示 e4 e2 e2 e1 ff\n f2 a2 22 34\n ff ee dd\n 在循环中使用scanf(fp,“%2x”,buffer+offset),我试图将每个字节加载到字节缓冲区中,直到每行结束,标记一条完整的记录。主要问题是检测换行符,因为scanf完全忽略它并跳转到下一行。我的原始代码是 do{ count
e4 e2 e2 e1 ff\n
f2 a2 22 34\n
ff ee dd\n
在循环中使用scanf(fp,“%2x”,buffer+offset),我试图将每个字节加载到字节缓冲区中,直到每行结束,标记一条完整的记录。主要问题是检测换行符,因为scanf完全忽略它并跳转到下一行。我的原始代码是
do{
counter=fscanf(datain,"%2x",buffer1+offset);
fprintf(stdout,"%#2x ",buffer1[offset]);
offset+=counter;
}while(!feof(datain));
通过在每个十六进制说明符后添加%c,我可以从流中提取空格和换行符。通过对这个角色的测试,我可以知道一条新线已经到达
do{
counter=fscanf(datain,"%2x%c",buffer1+offset,&followsymbol);
fprintf(stdout,"Counter:%i\n",counter);
if (counter==2)
{fprintf(stdout,"data:%5x\tfollowsymbol:%5x\n",buffer1[offset],followsymbol);
offset+=1;
}
if(followsymbol==0x0a && counter==2)
printf("a nl symbol has been detected\n");
}while(!feof(datain));
来自终端的输出
Counter:2
data:ffffffe4 followsymbol: 20
Counter:2
data:ffffffe2 followsymbol: 20
Counter:2
data:ffffffe2 followsymbol: 20
Counter:2
data:ffffffe1 followsymbol: 20
Counter:2
data:ffffffff followsymbol: a
a nl symbol has been detected
Counter:2
data:fffffff2 followsymbol: 20
Counter:2
data:ffffffa2 followsymbol: 20
Counter:2
data: 22 followsymbol: 20
Counter:2
data: 34 followsymbol: a
a nl symbol has been detected
Counter:2
data:ffffffff followsymbol: 20
Counter:2
data:ffffffee followsymbol: 20
Counter:2
data:ffffffdd followsymbol: a
a nl symbol has been detected
Counter:65535
另一种通常更简单的方法是使用或读取整行,然后使用或处理行上的符号。在许多方面,这与当前方案类似,但您需要能够遍历字符串,因此
%n
转换规范在这里通常很有用:
while (fgets(line, sizeof(line), datain) != 0)
{
int line_offset = 0;
int new_offset;
while (sscanf(line + line_offset, "%2x%n", &buffer1[offset], &new_offset) == 1)
{
printf("%#.2x ", buffer1[offset]);
offset++;
line_offset += new_offset;
}
}
%n
转换不计入从sscanf()
返回的值
请注意,这避免了在另一个示例中看到的一些其他问题。它不会在没有行可读取时尝试处理数据,也不会在没有行可读取时尝试处理数据
此外,一次读取一行的优点之一是,如果您可以给出错误发生的整个上下文(行),而不是在一些不确定的成功转换次数后仍停留在行的剩余部分,则错误报告通常更容易/更好。如果行的第六个字段中有错误字符,您可以简单地显示前五个字段以及错误所在的位置。为什么要硬编码0x0a,最好使用
\n
替换?需要如果(计数器==2&&followsymbol==0x0a)
。否则,followsymbol
可能是先前的值,如果计数器的值为EOF或1,则应非常小心在转换失败时打印“新到达数据”的代码。同样,对使用feof()
检测EOF的代码非常谨慎;这几乎总是错误的。请特别注意,当成功读取文件中的最后一个数字时,feof()
不会显示EOF。有一个完整的问题你应该读一下。使用do{…}while(!feof(file))代码>不是改进。输出与代码/输入文件不匹配。1)文件的最后一行中没有\n
,或者2)发布的输出不显示最后一行“检测到新行”之后的内容。feof(datain)
直到在counter=fscanf()
返回2以外的值之后才会变为真。在每次fscnaf()
之后尝试打印counter
,查看。feof(datain)
在读取最后一个char
后不会立即返回true。相反,在尝试读取最后一个char
之后,它返回true。使用来自fgets()
、fgetc()
或fscanf()
的返回值比使用feof()
确定何时停止更好。在接收到失败的读取后,使用feof()
,确定失败是EOF还是IO错误。