关于c++用popen调用cmd的问题


#include <iostream>
#include <cstdlib>

int main() {
    // 打开命令管道
    const char* command = "cmd.exe";
    FILE* pipe = popen(command, "r");
    if (pipe == NULL) {
        std::cerr << "popen failed, error code: " << errno << std::endl;
        return 1;
    }

    // 向命令提供输入
    char input[] = "echo Hello, world!";
    std::fwrite(input, sizeof(input), 1, stdin);

    // 从命令读取输出
    char buffer[128];
    std::string result;
    while (fgets(buffer, sizeof(buffer), pipe) != NULL) {
        result += buffer;
    }

    // 关闭管道
    pclose(pipe);
    std::cout << result << std::endl;

    return 0;
}

它会一直卡在while循环里面出不去,fgets的返回值一直不为null,不知道为什么

你的代码中的问题在于你误解了popen函数的工作方式。popen函数创建一个管道,使得你可以通过stdin向命令提供输入,并通过stdout从命令读取输出。
在你的代码中,你试图向stdin写入一个字符串,但是这是不可能的,因为stdin是一个标准输入流,它通常连接到一个键盘,而不是一个文件或管道。因此,你的代码无法正常工作,因为它试图向一个无法写入的流写入数据。
为了解决你的问题,你应该使用fwrite向pipe写入数据,而不是stdin。你也需要处理命令执行的错误,以及确保在所有情况下都关闭管道。我的设备不支持发送代码框,我关注你一下,然后在私信里把代码给你发过去吧。

制作不易,点个关注吧!
求求了,我是一个小博主,很费劲的发了一篇,然后没人看。给我个支持,点个关注吧!谢谢!

【以下回答由 GPT 生成】

答案:

问题的原因是,在调用popen函数后,子进程的输出可能会被缓冲,而fgets函数是按行读取的,只有在缓冲区有内容或者读到了文件结束符时才会返回。所以可能出现的情况是,子进程的输出被缓冲起来,fgets一直等待直到缓冲区被填充满。

解决这个问题的方法是在调用popen函数之前,使用setvbuf函数来设置缓冲方式为无缓冲。这样就可以实现即时的读取。

下面是修改后的代码:

#include <iostream>
#include <cstring>
#include <cstdlib>

int main() {
    // 打开命令管道
    const char* command = "cmd.exe";
    FILE* pipe = popen(command, "r");

    if (pipe == NULL) {
        std::cerr << "popen failed, error code: " << errno << std::endl;
        return 1;
    }

    // 将缓冲方式设置为无缓冲
    setvbuf(pipe, NULL, _IONBF, 0);

    // 向命令提供输入
    const char* input = "echo Hello, world!\n";
    std::fwrite(input, strlen(input), 1, pipe);

    // 从命令读取输出
    char buffer[128];
    std::string result;
    while (fgets(buffer, sizeof(buffer), pipe) != NULL) {
        result += buffer;
    }

    // 关闭管道
    pclose(pipe);
    std::cout << result << std::endl;

    return 0;
}

这样修改后的代码就可以正常地从子进程中读取输出了。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^