我正在尝试编写一个通过命令行与 Stockfish 国际象棋引擎交互的程序。我研究过使用管道和重定向 cin/cout,但问题是 Stockfish 运行自己的 shell 而不是只给出单行输出,例如:

~$ stockfish
Stockfish 261014 64 by Tord Romstad, Marco Costalba and Joona Kiiski
> go movetime 5000
[output]
...
> quit
~$

我尝试了以下代码(来自 here )来读取执行命令并将它们读回,但是当我尝试运行 Stockfish 并打印输出时它永远不会完成:
#include <string>
#include <iostream>
#include <stdio.h>

std::string exec(char* cmd) {
    FILE* pipe = popen(cmd, "r");
    if (!pipe) return "ERROR";
    char buffer[128];
    std::string result = "";
    while(!feof(pipe)) {
        if(fgets(buffer, 128, pipe) != NULL)
            result += buffer;
    }
    pclose(pipe);
    return result;
}

int main(void)
{
    std::cout << exec("ls") << std::endl; // this works fine
    std::cout << exec("stockfish") << std::endl; // this never ends

    return 0;
}

我的问题是,为什么这不起作用,我如何编写一个程序来从 Stockfish shell 发送和接收文本?

最佳答案

您的 while 循环只会在它检测到管道上的 EOF 时完成,并且在 popen'd 命令终止之前不会发生这种情况。它正在等待输入的事实基本上是无法检测到的。

由于 popen 只重定向了 stdout,popen'd stockfish 与您的程序共享 stdin。当您启动 stockfish 时,它会尝试读取输入。如果你不输入一些东西,什么都不会发生。

因此,您应该尝试向 stockfish 发送您希望它执行的命令,并以“退出”命令结尾。

Popen 只允许您发送或接收数据,具体取决于模式操作数。你永远不能两者兼得。你可以使用通常的 forkexec 技术,或者你可以像 stockfish < sfcmds.txt 那样弹出一些东西。

10-08 04:05