sim*_*556 2 c file-io file binary-data
我正在尝试编写一个读取二进制文件并将其转换为数据类型的C程序.我正在使用head命令生成二进制文件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));
}
}
Run Code Online (Sandbox Code Playgroud)
这是有效的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));
}
}
Run Code Online (Sandbox Code Playgroud)
问题是,使用char我需要获得40000个单词wc -w file并且我得到它们.现在有了双倍,我得到随机数量的单词但理论上我应该从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位有效数字(小数点前一位).这不需要内存或磁盘上的过多空间,它将准确地传达所有数字,无论规模如何,再次假设您的doubles代表IEEE 754.如果您愿意,您可以进一步消除(相当安全)的假设IEEE 754格式采用@chux在评论中提出的变体.那将是最安全的方法.
还有一件事:IEEE浮点支持无穷大和多个非数值.相对于普通的FP数字,它们的数量非常少,但是你偶尔会遇到其中一个.它们可能会很好地转换为输出,但您可能需要考虑是否需要专门处理它们.