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

C语言多进程管道程序问题:无法将命令行参数argv[1]转换为大写

问题分析与修复方案

我帮你排查了代码里的几个核心问题,尤其是没实现转大写的逻辑,还有一些管道和字符串处理的细节错误:

主要问题点

  • 完全缺失转大写逻辑:子进程只是读取了管道内容,根本没调用toupper()处理字符,这是最核心的问题
  • 字符串长度计算错误:sizeof(argv[1])获取的是指针的字节数(比如64位系统是8),不是字符串实际长度,应该用strlen(argv[1]) + 1(要包含字符串结束符\0)
  • 输出内容错误:父进程读取管道B的内容后,依然打印原argv[1],而不是转换后的结果;子进程写入管道B的也是原字符串,不是处理后的大写版本
  • 变量复用错误:创建第二个管道时,你定义了err2但还是用了err接收返回值,会覆盖第一个管道的错误状态
  • 多余的等待调用:父进程里已经用wait(0)等待子进程退出,后面的wait(NULL)会导致不必要的阻塞
  • 缓冲区溢出风险:readmessage固定为12字节,如果输入的字符串超过11个字符会溢出,建议根据输入长度动态调整

修正后的代码

#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h> // 要包含strlen的头文件

int main(int argc, char* argv[]) {
    // 先检查命令行参数是否存在
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <text>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    int fd[2], err;
    int fd2[2], err2;
    pid_t pid;
    // 根据输入字符串长度定义缓冲区,避免溢出
    char* readmessage = malloc(strlen(argv[1]) + 1);
    if (!readmessage) {
        perror("malloc error");
        exit(EXIT_FAILURE);
    }

    // 创建管道A
    err = pipe(fd);
    if (err < 0) {
        perror("pipe A error");
        free(readmessage);
        exit(EXIT_FAILURE);
    }
    // 创建管道B,用err2接收错误
    err2 = pipe(fd2);
    if (err2 < 0) {
        perror("pipe B error");
        close(fd[0]);
        close(fd[1]);
        free(readmessage);
        exit(EXIT_FAILURE);
    }

    pid = fork();
    if (pid < 0) {
        perror("fork error");
        // 出错时要关闭已打开的管道和释放内存
        close(fd[0]);
        close(fd[1]);
        close(fd2[0]);
        close(fd2[1]);
        free(readmessage);
        exit(EXIT_FAILURE);
    } else if (pid > 0) {
        /* 父进程逻辑 */
        close(fd[0]); // 关闭管道A的读端
        close(fd2[1]); // 关闭管道B的写端

        size_t msg_len = strlen(argv[1]) + 1;
        printf("Parent Process - Writing to pipe A - Message is: %s\n", argv[1]);
        // 写入正确长度的字符串
        write(fd[1], argv[1], msg_len);
        // 从管道B读取转换后的内容
        read(fd2[0], readmessage, msg_len);
        printf("Parent Process - Reading from pipe B - Uppercase Message is: %s\n", readmessage);

        sleep(1);
        printf("Child is Terminated!\n");
        wait(NULL); // 等待子进程退出

        // 清理资源
        close(fd[1]);
        close(fd2[0]);
        free(readmessage);
    } else {
        /* 子进程逻辑 */
        close(fd[1]); // 关闭管道A的写端
        close(fd2[0]); // 关闭管道B的读端

        size_t msg_len = strlen(argv[1]) + 1;
        read(fd[0], readmessage, msg_len);
        printf("Child Process - Reading from pipe A - Original Message is: %s\n", readmessage);
        
        printf("Converting to uppercase...\n");
        sleep(1);
        // 核心:遍历字符串,转换每个字符为大写
        for (int i = 0; readmessage[i] != '\0'; i++) {
            readmessage[i] = toupper((unsigned char)readmessage[i]);
        }

        printf("Child Process - Writing to pipe B - Uppercase Message is: %s\n", readmessage);
        // 写入转换后的字符串
        write(fd2[1], readmessage, msg_len);
        
        printf("Child is exiting!\n");
        // 清理子进程的资源
        close(fd[0]);
        close(fd2[1]);
        free(readmessage);
        exit(EXIT_SUCCESS);
    }

    return 0;
}

关键修复说明

  1. 添加转大写逻辑:子进程中用循环遍历字符串的每个字符,调用toupper()转换,注意要把字符转成unsigned char避免处理负数的ASCII值
  2. 正确处理字符串长度:用strlen()获取实际长度,加1包含\0,避免截断或写入错误长度
  3. 动态分配缓冲区:根据输入字符串长度分配内存,避免固定大小的缓冲区溢出
  4. 修正管道和资源清理:每个进程只保留需要的管道端,出错时正确关闭管道和释放内存
  5. 参数检查:添加了命令行参数的检查,避免用户忘记输入文本

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 22:27:42