我正在尝试编写一个C程序,该程序读取二进制文件并将其转换为数据类型。我正在使用头命令head -c 40000 /dev/urandom > data40.bin
生成一个二进制文件。该程序适用于int和char数据类型,但不能执行double。这是程序的代码。
void double_funct(int readFrom, int writeTo){
double buffer[150];
int a = read(readFrom,buffer,sizeof(double));
while(a!=0){
int size = 1;
int c=0;
for(c=0;c<size;c++){
char temp[100];
int x = snprintf(temp,100,"%f ", buffer[c]);
write(writeTo, temp, x);
}
a = read(readFrom,buffer,sizeof(double));
}
}
这是有效的char函数
void char_funct(int readFrom, int writeTo){
char buffer[150];
int a = read(readFrom,buffer,sizeof(char));
while(a!=0){
int size = 1;
int c=0;
for(c=0;c<size;c++){
char temp[100]=" ";
snprintf(temp,100,"%d ", buffer[c]);
write(writeTo, temp, strlen(temp));
}
a = read(readFrom,buffer,sizeof(char));
}
}
问题是使用char我需要使用
wc -w file
获得40000个单词,然后我将它们获得。现在有了double我得到了随机的单词数量,但理论上我应该从40000字节的数据中得到5000,但是我得到4000到15000之间的随机数,对于char我得到40000,就像它应该为一个字符提供1个字节。我不知道这是什么问题,相同的代码适用于
int
,其中我从40000字节的数据中获得10000个单词。 最佳答案
主要问题似乎是您的temp
数组不足以容纳您的printf格式和数据。 IEEE-754 double
的十进制指数范围是-308至+308。您正在使用"%f"
格式打印双打,它会生成普通的十进制表示形式。由于未指定精度,因此默认精度为6。这可能需要多达1(符号)+ 309(数字)+1(小数点)+6(尾随小数位)+1(终止符)字符(总共318个字符),但是您只能容纳100个空间。
您使用snprintf()
打印到缓冲区,因此不会超出那里的数组范围,但是snprintf()
返回所需的字节数,减去终止符所需的字节数。那就是你write()
的字节数,并且在许多情况下确实超出了缓冲区。您会在输出中看到结果。
其次,您还会在输出中看到大量的0.00000
,这是由于将小数舍入到6位小数位数而引起的。
如果更改打印数字的格式,可能会获得更好的成功。例如,"%.16e "
将为您提供指数格式的输出,总共有17个有效数字(小数点前一位)。再次假设您的double
是根据IEEE 754表示的,那将不需要在内存或磁盘上占用过多的空间,并且它将准确地传递所有数字,而不管其规模如何。如果您愿意,还可以消除(非常安全的)假设通过使用@chux在注释中建议的变体来更改IEEE 754格式。那将是最安全的方法。
还有一件事:IEEE浮点支持无限性和多个非数字值。与普通FP编号相比,这些编号的数量很少,但是您偶尔还是会碰到其中之一。它们可能会被转换为输出,但是您可能要考虑是否需要专门处理它们。