使用系统调用read读取文本文件double数据全为零,求无fscanf解决方案
嘿,我来帮你搞定这个问题~
首先得搞清楚你之前的代码为啥全是零:你用read(fd, &a[i], sizeof(double))是直接把文件里的字节当成double的二进制存储来读,但你的File.txt里是文本格式的数字(比如"2.00"是ASCII字符),这些字符的字节和double类型的二进制表示完全不是一回事。举个例子,2.0的二进制是0x4000000000000000,但文本里的"2.00"对应的字节是0x32 0x2E 0x30 0x30,把这些乱码字节塞进double变量里,结果自然是无效的(表现为全零或者垃圾值)。
既然你说逐字符读取到行尾是正常的,那咱们就基于这个逻辑来做,不用fscanf也能搞定,核心思路是:先把文本里的数字字符串读出来,再转换成double类型。给你一个具体的实现方案:
解决方案:逐字符读行 + 字符串转double
#include <unistd.h> #include <stdlib.h> #include <string.h> #include <stdio.h> #include <fcntl.h> int main() { // 打开文件(注意要包含fcntl.h) int fd = open("File.txt", O_RDONLY); if (fd == -1) { perror("Failed to open file"); return 1; } double a[5] = {0.0}; // 初始化数组 char buf[1024]; // 存储读取到的一行文本 int buf_pos = 0; char current_char; ssize_t read_bytes; // 逐字符读取整行(假设所有数字都在一行里) while ((read_bytes = read(fd, ¤t_char, 1)) > 0) { if (current_char == '\n' || buf_pos >= sizeof(buf) - 1) { break; // 读到换行或者缓冲区满了就停止 } buf[buf_pos++] = current_char; } buf[buf_pos] = '\0'; // 一定要加字符串终止符,否则后续处理会出错 // 分割字符串里的每个数字(按空格分割) char *token = strtok(buf, " "); int idx = 0; while (token != NULL && idx < 5) { char *end_ptr; // 把字符串转成double,end_ptr用来检查转换是否有效 a[idx] = strtod(token, &end_ptr); // 错误检查:如果end_ptr等于token,说明这不是有效的数字 if (end_ptr == token) { fprintf(stderr, "Warning: Invalid number '%s' at position %d\n", token, idx); a[idx] = 0.0; // 可以自己定义错误处理逻辑 } idx++; token = strtok(NULL, " "); // 取下一个数字 } // 打印结果 for (int i = 0; i < 5; i++) { printf("a[%d] = %.2lf\n", i, a[i]); } close(fd); return 0; }
代码说明
- 逐字符读行:复用了你已经验证过的逐字符读取逻辑,把整行文本读到缓冲区里,确保拿到所有数字的字符串形式。
- 分割字符串:用
strtok按空格分割出每个数字的子串,如果你不想用strtok(它会修改原缓冲区),也可以手动遍历缓冲区,找到空格的位置来截取子串。 - 字符串转double:用标准库函数
strtod来完成转换,它比atof更安全,因为可以通过end_ptr检查转换是否成功(比如遇到非数字字符时能及时发现)。
其他可选思路
如果你的文件里数字可能分布在多行,只需要修改逐字符读取的逻辑,每次读取一行就处理一行的数字,直到填满数组或者文件读完就行。
内容的提问来源于stack exchange,提问作者Thunfische
相关产品推荐
相关产品推荐

