You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用系统调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 09:00:39