我正在尝试编写一个通过命令行与 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 只允许您发送或接收数据,具体取决于模式操作数。你永远不能两者兼得。你可以使用通常的 fork
和 exec
技术,或者你可以像 stockfish < sfcmds.txt
那样弹出一些东西。