0

我正在尝试使用 getline() 从用户那里获取输入。

以下代码工作正常。它等待用户输入文件名并将其存储在 fileName 中。

#include <iostream>
#include <string>

using namespace std;

string inputFile();

int main() 
{
    string fileName;
    cout << "Enter the name of the file including the path" << endl;            
    getline(cin, fileName);

    return 0;
}

但是,此代码无法正常工作。

#include <iostream>
#include <string>

using namespace std;

string inputFile();

int main() 
{
    int option;

    cout << "Enter option number" << endl;
    cin >> option;

    switch (option)
    {
        case 1:
        {
            string fileName;
            cout << "Enter the name of the file including the path" << endl;            
            getline(cin, fileName);
            break;
        }
        case 2:
            cout << "You chose option 2";
            break;
        case 3:
            cout << "You chose option 3";
            break;
        default:
            cout << "value unknown";
    }   

    return 0;
}

在用户输入 1 并且程序进入 switch...case 之后,再次要求用户输入文件名。但是,这一次程序不等待响应。

为什么 getline() 不能像在 switch...case 结构之外那样工作?

任何建议将不胜感激。

4

4 回答 4

2

cin将换行符 ( \n) 留在流中。cin.ignore()提取和丢弃字符。它可用于冲洗cin直到\n达到。

因此,解决方案是std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');在第二次调用getline(cin, fileName);
Also add之前添加 ,cin.clear()以删除错误标志cin

例子:

case 1:
    {
        std::string fileName;
        std::cout << "Enter the name of the file including the path" << std::endl; 
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        getline(std::cin, fileName);
        break;
    }
于 2013-10-20T00:41:10.680 回答
0

您在单个流上混合格式化输入和行输入。这是一个坏主意,不要在同一个流上同时 使用格式化输入operator>>或行输入。std::getline()

这基本上是因为处理空白的方式。\n在这种情况下,当您阅读该选项时,您将在输入中留下一个字符。

cin >> option;

\n这会读取选项,但会在输入流(包括字符)上的选项(整数之后)之后留下任何内容。因此,下一次使用 std::getline() 只会读取\n字符(这可能会给你零个字符)。

交互式用户输入是基于行的。
特别是因为std::cin流是缓冲的(因此在您点击返回之前不会刷新)。

因此,当我阅读来自交互式用户的输入时,我总是一次阅读一行文本。然后解析这一行以获得我正在寻找的内容。

 std::string  optionLine;
 std::getline(std::cin, optionLine);

 int option = boost::lexical_cast<int>(optionLine);

注意:您不需要,您可以使用另一个变量boost::lexical_cast来实现相同的效果。std::stringstream

 // A simple alternative to boost::lexical_cast
 // Not quite as pedantic as above but you can add more tests as required.
 std::stringstream optionLineStream(optionLine);
 int option;
 if (optionLineStream >> option)
 {
     // reading the option worked.
 }

一次读取一行然后解析输入还有一个优点,即您永远不会将输入置于错误状态并且需要重置它(任何错误状态都设置在中间std::stringstream对象上)。因此修复错误的用户输入更容易。

于 2013-10-20T02:33:52.997 回答
0

问题可能是,您正在通过 >> 将案例数读取到整数变量中。通过这样做,回车键生成的换行符仍在缓冲区中。现在 getline 尝试从输入流中读取并立即接收换行符。而且因为它只读取下一个换行符,所以它退出了。

于 2013-10-20T00:34:25.947 回答
0

问题与switch-statement无关!相反,它与混合格式化输入(使用operator>>())和未格式化输入(在这种情况下std::getline())有关:一旦字符与格式不匹配,格式化输入就会停止读取。读取整数时,一旦找到非数字就停止。也就是说,在数字之后输入的任何换行符都将卡在流中,并且很std::getline()乐意将此换行符作为停止其输入的机会。

在格式化和未格式化输入之间切换时,您通常希望摆脱空格。例如,您可以使用

if (std::getline(std::cin >> std::ws, fileName)) { ... }

首先跳过任何空格,然后尝试读取fileName,如果成功,则处理输入(始终需要检查输入是否成功)。

于 2013-10-20T00:34:29.410 回答