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

C语言循环管道执行异常求助:大小写转换程序单次正常循环失效

问题分析与修复方案

你的代码存在多个核心逻辑错误,导致循环执行时完全失效,以下是关键问题和修复后的实现:

关键错误点

  • 错误使用feof:while(!feof(in))是典型的错误写法,feof只有在读取到文件末尾后才会置位,会导致最后一行重复处理;且父进程中重新打开input.txt会让读取指针回到开头,触发无限循环。
  • 管道与进程重复创建:每次外层循环都创建新管道和进程,且管道写端/读端被过早关闭,后续循环无法继续传输数据。
  • 循环终止条件逻辑混乱:子进程中用strcmp(tst, temp) != 0作为循环终止条件完全不符合实际读取内容,导致逻辑卡死或异常退出。
  • 文件指针共享冲突:父子进程共享同一文件指针in和out,会导致读写位置混乱,数据写入异常。
  • 不必要的嵌套fork:你的需求是大小写转换+写入文件,不需要三层进程(父+子+孙),两层进程配合管道即可完成。

修复后的代码

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#define BUFF_SIZE 100

int main() {
    FILE *in, *out;
    char buff[BUFF_SIZE];
    int p1[2]; // 父进程->转换进程的管道

    // 打开文件并做错误检查
    in = fopen("input.txt", "r");
    if (!in) {
        perror("Failed to open input.txt");
        return 1;
    }
    out = fopen("output.txt", "w");
    if (!out) {
        perror("Failed to open output.txt");
        fclose(in);
        return 1;
    }

    // 仅创建一次管道
    if (pipe(p1) == -1) {
        perror("Pipe creation failed");
        fclose(in);
        fclose(out);
        return 1;
    }

    pid_t convert_pid = fork();
    if (convert_pid < 0) {
        perror("Fork failed");
        fclose(in);
        fclose(out);
        close(p1[0]);
        close(p1[1]);
        return 1;
    }

    if (convert_pid > 0) {
        // 父进程:读取input.txt,写入管道
        close(p1[0]); // 关闭读端,父进程只写

        // 正确的文件读取循环:用fgets返回值判断
        while (fgets(buff, BUFF_SIZE, in) != NULL) {
            printf("Sending line: %s", buff);
            // 写入实际有效字节数(包含终止符)
            write(p1[1], buff, strlen(buff) + 1);
        }

        close(p1[1]); // 写完后关闭写端,告知子进程数据传输结束
        wait(NULL); // 等待转换进程结束
        fclose(in);
    } else {
        // 子进程:读取管道数据,转换大小写,写入output.txt
        close(p1[1]); // 关闭写端,子进程只读
        char temp[BUFF_SIZE];
        char rev[BUFF_SIZE];
        int i;

        // 读取管道直到EOF(父进程关闭写端后,read返回0)
        while (read(p1[0], temp, BUFF_SIZE) > 0) {
            printf("Converting line: %s", temp);
            // 大小写转换
            for (i = 0; temp[i] != '\0'; i++) {
                rev[i] = isupper(temp[i]) ? tolower(temp[i]) : toupper(temp[i]);
            }
            rev[i] = '\0'; // 确保字符串终止

            fputs(rev, out);
        }

        close(p1[0]);
        fclose(out);
        exit(0);
    }

    fclose(out);
    return 0;
}

修复说明

  1. 正确的文件读取逻辑:用while(fgets(buff, BUFF_SIZE, in) != NULL)替代!feof(in),避免重复读取最后一行。
  2. 管道与进程仅创建一次:不需要每次循环都新建管道和进程,一次创建即可完成整个文件的处理。
  3. 管道关闭时机正确:父进程写完所有数据后关闭写端,子进程通过read返回0判断数据传输结束,替代原来混乱的字符串比较终止条件。
  4. 简化进程结构:只用两层进程(父进程读文件写管道,子进程读管道转大小写写文件),避免不必要的嵌套fork。
  5. 完善错误检查:增加文件打开、管道创建、fork的错误检查,方便排查问题。
  6. 准确的写入长度:写入管道时使用strlen(buff)+1,确保只传输有效数据,避免多余空字符干扰。

如果你的需求是持续监控input.txt并循环处理(比如文件内容更新后重新处理),可以在外层套一个循环,配合sleep或文件变化检测逻辑,注意每次重新打开文件时重置文件指针,避免重复读取旧内容。

内容的提问来源于stack exchange,提问作者Lauren Hall

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 19:45:10