如何用系统调用read()读取文件至空格处?C编程新手求助
使用系统调用
read()读取文件直到空格的实现方案 完全可以用系统调用read()实现这个需求!既然是操作系统作业要求用read(),那我们就得抛弃标准库的fscanf这类封装好的函数,手动处理每一个读取的字节——毕竟read()本身是逐字节(或者指定字节数)从文件描述符读取数据,没有内置的分隔符识别功能,得我们自己来做判断。
核心思路
- 用
open()系统调用打开目标文件,获取文件描述符(要保持纯系统调用风格,不能用标准库的fopen) - 逐字节调用
read()读取字符,把数字字符收集到缓冲区里 - 当读取到空格(或其他分隔符)时,给缓冲区加上字符串结束符
'\0',再转换成整数 - 重复上述过程,读取后续的PID值
完整代码示例
#include <unistd.h> #include <fcntl.h> #include <stdlib.h> #include <stdio.h> #include <ctype.h> #define BUF_SIZE 100 // 定义足够大的缓冲区,避免数字太长溢出 int main() { int fd; char buf[BUF_SIZE]; int index = 0; ssize_t bytes_read; int num, pid; // 以只读模式打开文件,检查打开是否成功 fd = open("test.txt", O_RDONLY); if (fd == -1) { perror("打开文件失败"); exit(EXIT_FAILURE); } // 第一步:读取第一个数字,直到遇到空格 while ((bytes_read = read(fd, &buf[index], 1)) > 0) { // 遇到空格,停止当前数字的收集 if (buf[index] == ' ') { buf[index] = '\0'; // 必须添加字符串结束符,否则atoi无法正确解析 num = atoi(buf); printf("读取到的数字: %d\n", num); index = 0; // 重置缓冲区索引,准备读取PID break; } // 只收集数字字符,遇到无效字符直接报错 if (isdigit(buf[index])) { index++; // 防缓冲区溢出,避免数组越界 if (index >= BUF_SIZE - 1) { fprintf(stderr, "数字长度超过缓冲区上限\n"); close(fd); exit(EXIT_FAILURE); } } else { fprintf(stderr, "文件中包含非数字的无效字符\n"); close(fd); exit(EXIT_FAILURE); } } // 第二步:读取PID,直到遇到换行或文件结束 while ((bytes_read = read(fd, &buf[index], 1)) > 0) { // 遇到空格、换行或其他空白字符都停止(如果只想要空格,改成buf[index] == ' '即可) if (isspace(buf[index])) { buf[index] = '\0'; pid = atoi(buf); printf("读取到的PID: %d\n", pid); break; } if (isdigit(buf[index])) { index++; if (index >= BUF_SIZE - 1) { fprintf(stderr, "PID长度超过缓冲区上限\n"); close(fd); exit(EXIT_FAILURE); } } else { fprintf(stderr, "文件中包含非数字的无效字符\n"); close(fd); exit(EXIT_FAILURE); } } // 检查read()是否出错 if (bytes_read == -1) { perror("读取文件失败"); close(fd); exit(EXIT_FAILURE); } // 记得关闭文件描述符,这是系统调用的好习惯 close(fd); return 0; }
关键细节解释
- 逐字节读取:因为
read()不会帮我们拆分数据,所以必须每次读1个字节,自己判断是否遇到分隔符 - 字符串结束符:
atoi()需要处理以'\0'结尾的字符串,所以收集完数字后一定要手动添加 - 错误处理:系统调用
open()和read()都可能失败(比如文件不存在、权限不足),必须检查返回值,用perror()打印错误信息 - 缓冲区溢出防护:定义固定大小的缓冲区后,要检查索引是否超过上限,避免数组越界导致的程序崩溃
额外注意事项
- 如果你的文件里分隔符不只是空格(比如制表符、换行),可以用
isspace()代替直接判断' ',它能识别所有空白字符 - 如果数字可能包含正负号,可以在收集字符的逻辑里允许第一个字符是
+或- - 可以把读取数字的逻辑封装成一个函数,比如
read_int(int fd, int *result),这样代码更简洁,也方便复用
内容的提问来源于stack exchange,提问作者Alopex
相关产品推荐
相关产品推荐

