我正在使用 C++system()
函数运行一些命令:
int system ( const char * command );
如何从发出的命令中收集标准输出?
具体来说,我想收集发出命令的输出(例如,发出命令的目录列表输出dir
)。
system()
返回一个int
,所以抓住它:int rvalue = system(command);
不过,我相信 system() 将返回的确切细节是特定于系统的。
系统程序通常有两种“返回”值的方法:写入标准输出,以及在程序结束时返回一个状态整数。(通常有更多方法可以返回结果,例如通过写入文件或数据库,但我认为这些超出了这里的范围)。
对于接收状态码,只需检查system
函数的返回值。
要接收输出,请将其重定向到文件中,然后再读取文件,或者使用popen
.
的返回值system
(具有讽刺意味的是)取决于系统,但在 POSIX 系统(包括 Linux 等)中,它与等待相同- 低 8 位或 16 位是孩子的退出状态(可能是您所说的“ ") 返回的值,高位指示终止子的信号类型(如果有)。我给出的联机帮助页的 URL 提供了预处理器宏,您可以使用它来撬开该返回值!
没有程序的“返回字符串”之类的东西,正如您现在在评论中阐明的那样,这是您想要的;作为已经提到的另一个答案,如果您想要由其他程序输出的文本,您应该使用popen
而不是system
.
受 bmorin 尝试的启发,但工作和测试,这个片段将接受一个 char* 命令并返回一个 char* 包含执行该命令的结果......
// Calling function must free the returned result.
char* exec(const char* command) {
FILE* fp;
char* line = NULL;
// Following initialization is equivalent to char* result = ""; and just
// initializes result to an empty string, only it works with
// -Werror=write-strings and is so much less clear.
char* result = (char*) calloc(1, 1);
size_t len = 0;
fflush(NULL);
fp = popen(command, "r");
if (fp == NULL) {
printf("Cannot execute command:\n%s\n", command);
return NULL;
}
while(getline(&line, &len, fp) != -1) {
// +1 below to allow room for null terminator.
result = (char*) realloc(result, strlen(result) + strlen(line) + 1);
// +1 below so we copy the final null terminator.
strncpy(result + strlen(result), line, strlen(line) + 1);
free(line);
line = NULL;
}
fflush(fp);
if (pclose(fp) != 0) {
perror("Cannot close stream.\n");
}
return result;
}
我只考虑编辑 bmorin 的代码,但不得不更改大多数行,因此单独的答案似乎更合适。如果没有,请道歉。(在其他问题中,bmorin 的代码实际上并没有累积这些行;它将它们打印到标准输出,我认为它们不会被需要,因为 system() 会这样做;并且它在一个错误路径中返回 void,当函数必须返回一个 char*,因此代码无法编译。也许最令人震惊的是,它在返回结果之前释放了结果。)
正如其他人所说,我建议使用 popen() 函数,但这个问题是特定于平台的。popen() 函数在使用 POSIX API 的操作系统上可用。我不确定此命令是否适用于其他 API,例如 WIN32
这是一个代码片段(纯 C 语言)执行命令popen
并返回其输出:
char* exec(const char* command) {
FILE* fp;
char* result = NULL;
size_t len = 0;
fflush(NULL);
fp = popen(command, "r");
if (fp == NULL) {
printf("Cannot execute command:\n%s\n", command);
return;
}
while(getline(&result, &len, fp) != -1) {
fputs(result, stdout);
}
free(result);
fflush(fp);
if (pclose(fp) != 0) {
perror("Cannot close stream.\n");
}
return result;
}