提问人:Alexey104 提问时间:10/5/2020 最后编辑:Robert ColumbiaAlexey104 更新时间:10/5/2020 访问量:405
有没有办法在 c++ 中确定以字节为单位的 stdin 内容大小?[复制]
Is there any way to determine stdin content size in bytes in c++? [duplicate]
问:
我是编程新手,我正在尝试为 Linux 编写一个 c++ 程序,该程序将创建一个子进程,而这个子进程将执行一个外部程序。该程序的输出应重定向到主程序并保存到字符串变量中,保留所有空格和换行符。我不知道输出将包含多少行/字符。
这是基本思想:
#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/wait.h>
int main()
{
int pipeDescriptors[2];
pipe(pipeDescriptors);
pid_t pid = fork();
if (pid == -1)
{
std::cerr << __LINE__ << ": fork() failed!\n" <<
std::strerror(errno) << '\n';
return 1;
}
else if (!pid)
{
// Child process
close(pipeDescriptors[0]); // Not gonna read from here
if (dup2(pipeDescriptors[1], STDOUT_FILENO) == -1) // Redirect output to the pipe
{
std::cerr << __LINE__ << ": dup2() failed!\n" <<
std::strerror(errno) << '\n';
return 1;
}
close(pipeDescriptors[1]); // Not needed anymore
execlp("someExternalProgram", "someExternalProgram", NULL);
}
else
{
// Parent process
close(pipeDescriptors[1]); // Not gonna write here
pid_t stdIn = dup(STDIN_FILENO); // Save the standard input for further usage
if (dup2(pipeDescriptors[0], STDIN_FILENO) == -1) // Redirect input to the pipe
{
std::cerr << __LINE__ << ": dup2() failed!\n" <<
std::strerror(errno) << '\n';
return 1;
}
close(pipeDescriptors[0]); // Not needed anymore
int childExitCode;
wait(&childExitCode);
if (childExitCode == 0)
{
std::string childOutput;
char c;
while (std::cin.read(&c, sizeof(c)))
{
childOutput += c;
}
// Do something with childOutput...
}
if (dup2(stdIn, STDIN_FILENO) == -1) // Restore the standard input
{
std::cerr << __LINE__ << ": dup2() failed!\n" <<
std::strerror(errno) << '\n';
return 1;
}
// Some further code goes here...
}
return 0;
}
上面代码的问题在于,当函数读取输入流中的最后一个字节时,它实际上并不“知道”这个字节是最后一个字节并尝试进一步读取,这导致了设置和,所以我以后无法再从标准输入中读取。 重置这些标志,但仍然无法使用。std::cin.get()
failbit
eofbit
std::cin
std::cin.clear()
stdin
如果我能在不超出流中最后一个字符的情况下获得内容的精确大小(以字节为单位),我将能够将这个确切的字节数读取到字符串变量中。但我想没有办法做到这一点。
那么我该如何解决这个问题呢?我是否应该使用中间文件将子进程的输出写入其中,然后再从父进程中读取它?stdin
std::cin.read()
答:
1赞
Maxim Egorushkin
10/5/2020
#1
子进程写入管道,但父进程在子进程终止之前不会读取管道。如果子项写入的管道缓冲区大小超过管道大小,则会阻塞等待父级读取管道,但父级在等待子级终止时会被阻塞,从而导致死锁。
为了避免这种情况,父进程必须继续读取管道,直到并且只有这样才能用于获取子进程退出状态。EOF
wait
例如:
// Read entire child output.
std::string child_stdout{std::istreambuf_iterator<char>{std::cin},
std::istreambuf_iterator<char>{}};
// Get the child exit status.
int childExitCode;
if(wait(&childExitCode))
std::abort(); // wait failed.
您可能还想从管道文件描述符打开一个新的 istream
,以避免混乱状态。std::cin
评论
0赞
Alexey104
10/5/2020
谢谢你指出来!我真的很想念它。
评论
std::cin