这里是函数代码:
#include <iostream>
#include <string>
#include <limits>
#include <sstream>
using namespace std;
int main (int argc, char **argv)
{
string StrInput;
while (1)
{
cout << "Enter a string : ";
getline(cin,StrInput);
if(cin.fail())
{
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
else
{
cout << StrInput;
}
}
return 0;
}
如果我启动我的软件:
echo "test" | ./test.exe
...它打印
test
,然后无限循环 cin.fail() 等于 1。
我想要的是,第一个循环它获取管道的值,但随后它停止并等待用户输入新字符串。 我试图寻找一个等待来更改 cin 的输入,但没有找到等待。
有人有想法吗?
我想要的是第一个循环它获取管道的值,但随后它停止并等待用户输入新字符串。
这个答案与上面的主题有关,如果您不知道管道到底是什么以及它是如何工作的,您应该寻求其他信息或提出新问题。
在您的程序中,
std::cin
失败,因为它从管道读取EOF
。如果你继续要求它读取,它就会永远失败。您需要做的是在 if
块之前插入一段代码:
// Judge EOF first
if (cin.eof()) {
cout << "\nEOF" << endl;
break;
} else if (cin.fail()) {
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
} else {
cout << StrInput << endl;
}
这只会暂时修复代码。
我们如何找出 STDIN 是绑定、管道还是键盘?在 Linux 中,您可以使用 POSIX:
#include <cstdio>
#include <iostream>
#include <string>
#include <unistd.h>
using std::cin;
using std::cout;
using std::endl;
using std::string;
int main() {
string str;
cin >> str;
cout << "read str: " << str << endl;
if (isatty(fileno(stdin))) {
cout << "std from keyboard" << endl;
} else {
cout << "std directed" << endl;
}
return 0;
}
❯ echo "111" | ./test
read str: 111
std directed
❯ ./test
111
read str: 111
std from keyboard
在Windows中,您可以使用Windows API:
#include <Windows.h>
#include <iostream>
#include <processenv.h>
using std::cin;
using std::cout;
using std::endl;
using std::string;
int main() {
string str;
cin >> str;
cout << "read str: " << str << endl;
DWORD file_type = GetFileType(GetStdHandle(STD_INPUT_HANDLE));
if (file_type == FILE_TYPE_CHAR) {
cout << "stdin from keyboard" << endl;
} else {
cout << "stdin directed" << endl;
}
}
如果通过管道启动进程,STDIN 会绑定到前一个进程的 STDOUT。在您的示例中,
./test.exe
的 STDIN 绑定到 echo
的 STDOUT。我们需要的是将其重新绑定到您的键盘。这是 Linux 上的代码:
#include <cstdio>
#include <iostream>
#include <string>
#include <unistd.h>
using std::cin;
using std::cout;
using std::endl;
using std::string;
int main() {
string input;
bool is_pipe = false;
if (!isatty(fileno(stdin))) {
is_pipe = true;
}
// if stdin is bound to pipe
if (is_pipe) {
// Your pipe code here
while (1) {
cout << "Enter a string : ";
getline(cin, input);
if (cin.eof()) {
cout << "pipeline EOF" << endl;
break;
} else if (cin.fail()) {
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
} else {
cout << input << endl;
}
}
// rebind stdin
freopen("/dev/tty", "r", stdin);
cout << "stdin rebind to keyboard" << endl;
cin.clear();
}
// keyboard code here
while (1) {
cout << "Enter a string : ";
getline(cin, input);
if (cin.fail()) {
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
} else {
cout << input << endl;
}
}
}
❯ echo "111" | ./test
Enter a string : 111
Enter a string : pipeline EOF
stdin rebind to keyboard
Enter a string : This is from keyboard
This is from keyboard
Enter a string : ^C
❯ ./test
Enter a string : This is from keyboard
This is from keyboard
Enter a string : ^C
并在 Windows 上使用 WinAPI:
#include <Windows.h>
#include <cstdio>
#include <fileapi.h>
#include <iostream>
#include <limits>
#include <processenv.h>
#include <string>
#include <winbase.h>
using std::cin;
using std::cout;
using std::endl;
using std::string;
int main() {
string input;
bool is_pipe = false;
if (GetFileType(GetStdHandle(STD_INPUT_HANDLE)) != FILE_TYPE_CHAR) {
is_pipe = true;
}
// if stdin is bound to pipe
if (is_pipe) {
// Your pipe code here
while (1) {
cout << "Enter a string : ";
getline(cin, input);
if (cin.eof()) {
cout << "pipeline EOF" << endl;
break;
} else if (cin.fail()) {
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
} else {
cout << input << endl;
}
}
// rebind stdin
freopen("CON", "r", stdin);
cout << "stdin rebind to keyboard" << endl;
cin.clear();
}
// keyboard code here
while (1) {
cout << "Enter a string : ";
getline(cin, input);
if (cin.fail()) {
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
} else {
cout << input << endl;
}
}
}