我正在尝试编写一个读取二进制文件并将其转换为数据类型的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个单词并获得它们。现在有了双倍,我得到随机数量的单词,但理论上我应该从40000字节的数据得到5000但是我得到4000到15000之间的随机量,对于char我得到40000就像它应该1个字节的一个字符。
我不知道同样的代码对于int
有什么问题,我从40000字节的数据中得到10000个单词。
答案 0 :(得分:5)
主要问题似乎是您的temp
数组对于printf格式和数据来说不够大。 IEEE-754 double
的小数指数范围为-308到+308。您正在使用格式"%f"
打印双打,这会产生纯十进制表示。由于未指定精度,因此默认精度为6。这可能需要多达1(符号)+ 309(数字)+ 1(小数点)+ 6(尾随小数位)+ 1(终结符)字符(总共318),但您只有100的空间。 / p>
使用snprintf()
打印到缓冲区,因此不会超出那里的数组边界,但snprintf()
会返回所需的字节数,更少终结者所需的那个。这是你write()
的字节数,在很多情况下, 溢出你的缓冲区。您可以在输出中看到结果。
其次,您还会在输出中看到大量0.00000
,这是因为将小数字舍入到6位小数位数精度。
如果更改打印数字的格式,您可能会获得更好的成功。例如,"%.16e "
将以指数格式输出,总共有17位有效数字(小数点前一位)。这不需要内存或磁盘上的过多空间,并且无论规模如何,它都会准确地传达所有数字,再次假设您的double
代表每个IEEE 754.如果您愿意,您可以进一步消除(非常安全)通过在评论中使用@chux建议的变体来假设IEEE 754格式。那将是最安全的方法。
还有一件事:IEEE浮点支持无穷大和多个非数值。相对于普通的FP数字,它们的数量非常少,但是你偶尔会遇到其中一个。它们可能会很好地转换为输出,但您可能需要考虑是否需要专门处理它们。