【问题标题】:Using cin for keyboard input after processing redirected file input with getline使用 getline 处理重定向文件输入后使用 cin 进行键盘输入
【发布时间】:2015-06-17 01:59:49
【问题描述】:

我知道,这个问题已经被处理了很多次了..但我还是不能让它工作..在这里我粘贴一些代码:

#include <sstream>
#include "header.h"
using namespace std;
using namespace header;

int main(){
    string parent, child, line, node;
    int choose = 0;
    tree_ptr tree_inst = new tree;
    cout << "*** Start ***" << endl;    
    while (getline(cin, line, '\n')){
        istringstream line_stream(line);
        line_stream >> parent;
        if (parent.compare("0") == 0) break;
        while (line_stream >> child) {
            if (!tree_inst->insert(parent, child)) {
                cout << "*** ERROR! ***" << endl;
                tree_inst->visit(tree_inst->root);
                cout << "*** End ***" << endl;
                return -1;
            }
        }
    }
    while (true) {
        cin >> choose;  //<== doesn't wait for the input, just loop forever
                        //    on the default statement of the switch...
        switch (choose) {
            ...
        }
    }
}

我已经尝试插入一些 cin.sync() cin.clear() cin.ignore() ..etc.. 但没有任何改变!

【问题讨论】:

  • PS:“string”和“iostream”包含在“header.h”中..
  • 你的输入是什么,如果它不是可以解析为整数的任何内容,则不会从输入缓冲区中删除文本,因此下一个循环将再次读取相同的输入。您需要 both 忽略该行的其余部分 清除错误。请参阅此std::istream::ignore 参考中的示例如何操作。
  • 好的,我试试!无论如何,输入是一个文本文件(在 Linux 上,我使用控制台将文件通过“./myprogram
  • 我刚试过:while (true) { cin.clear(); cin.ignore(std::numeric_limits<:streamsize>::max(), '\n'); cin >> 选择; switch (choose) { ... etch... 但没有任何改变 :(
  • 我无法重现您的问题!你如何摆脱第一个循环?

标签: c++ cin getline io-redirection istream


【解决方案1】:

第一个getline() 循环将永远循环,如果您不以某种方式破坏它。如果以干净的方式完成,这根本不应该是一个问题。事实上,我无法重现您的错误。

如何分析错误

所以原因要么是cin 的状态不佳,要么是非数字非空格输入仍处于待处理状态。为了帮助您找出答案,我建议您添加一些诊断代码:

cout << "Enter free lines of text or stop to return to the menu:";
while (getline(cin, line, '\n')) {   // This would loop foreved
    if (line == "stop")              // I added this one to exit
        break;                       // but how do you do ?
}
while (true) {                       // I get no problem here
    cout << "Cin status: failed="    // <===Add this simple diagnostic to 
         << cin.fail() << " bad="    //     check the state of the stream 
         << cin.bad() << " eof=" << cin.eof() << endl;  
    cout << "Next char in decimal is:" // <=== Add this to show 
         << cin.peek() << endl;        //      where in the stream you're hanging
    cout << "Choose:";
    cin >> choose;  
    cout << "selected: " << choose << endl;
}

如果您的流状态不干净,尽管有 cin.clean() ,这是因为您关闭了流或在控制台输入了文件结束代码(Ctrl+D 或 Ctrl+Z 取决于系统)。

如果流状态是干净的,但 peeked 字符不是数字(即十进制代码不在 48 和 57 之间),则将流设置为失败状态是错误的输入。

编辑:您的具体情况

查看您提供的诊断信息(fail=1,eof=1),在第一个循环之后,您似乎已经完成了输入。因此,您的输入失败,因为没有更多数据要读取。您在 pastebin 上的输入文件确认最后一行是您用来退出第一个循环的“0”。

根据我们的交流,我了解到您实际上已从命令行重定向输入(例如 yourprogramme &lt;yourinput.txt ),并希望您的代码在重定向的文件输入结束后切换回键盘输入。不幸的是,这不是它的工作方式。如果您从文件重定向输入,cin 将始终引用重定向的文件。

为了能够混合文件和键盘输入,您需要使用&lt;fstream&gt;,更准确地说是ifstream 来读取文件,并使用cin 来进行键盘输入。

这是一个稍加修改的代码,它从命令行获取文件名,但没有间接(例如 yourprogramme yourinput.txt ):

...
int main(int argc, char**argv)
{
    if (argc != 2) {     // if called from command line wrong arguments
        cerr << "You must provide the name of the data file as command line argument\n";
        return EXIT_FAILURE;
    }
    ifstream file(argv[1]);     // open the file for reading 
    if (!file) {                // if open failed, end the programme
        cerr << "Could not open "<<argv[1]<<"\n";
        return EXIT_FAILURE;
    }
    string line;                // here your code from before
    int choose = 0;
    cout << "*** Loading "<<argv[1]<< " ***" << endl;
                              // but in the first loop replace cin with file
    while (getline(file, line, '\n')){   
        cout << "Read: " << line<<endl;
        if (line == "0")                // Abridged version;-)
            break;
    }
    file.close();               // File is no longer needed here.  
    while (true) {              // Second loop, unchanged, using cin  
        cout << "Choose (9 to exit):";
        if (!(cin >> choose))   // avoid looping forever if problem on cin
            break;
        cout << "selected: " << choose << endl;
        if (choose == 9)
            break;  
    }
return EXIT_SUCCESS;
}

【讨论】:

  • 现在的输出是(带有 cout 和 cin.fail cin.bad ...):Cin status: failed=1 bad=0 eof=1 Next char in decimal is:-1跨度>
  • @Moriduri 这意味着您肯定已经到达文件末尾。 (eof==1 并用 -1 窥视)。您是否删除了之前测试的 cin.ignore() ?
  • @Moriduri 好的,总而言之,当你离开第一个循环时,你不会忽略任何东西,但是当进入第二个循环时,你已经在文件的末尾。这意味着您退出第一个循环的代码不会像您想象的那样工作,而 while 只是因为您已到达文件末尾而被中断。您应该编辑问题并输入您必须离开第一个循环的确切代码,并显示输入文件的内容。
  • @Moriduri PS:查看您的代码以及您所说的文件这一事实,我知道您正在通过在操作系统级别(即myprog &lt;testfile.txt)重定向输入来运行您的程序。如果你这样做,在文件末尾,程序将不会切换回键盘:重定向是确定的,所以当你到达文件末尾时任何 cin 都会失败。如果你想混合文件输入和键盘输入,你必须使用ifstream 明确地读取文件并保留 cin 用于真正的键盘输入。
  • @Moriduri 我已经进行了编辑,向您详细展示了如何执行此操作。
猜你喜欢
  • 2014-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-19
  • 2016-02-05
  • 2010-10-31
相关资源
最近更新 更多