首页 > 解决方案 > 在 C++ 中打开文本文件的输入验证

问题描述

我正在构建一个输入验证函数,它接受用户的输入并尝试打开该文件。如果用户输入的格式不正确,则重复。正确的格式是:

test1.txt

如果我在第一次运行时编写了正确的格式,我的函数就可以工作,但是在第二次运行之后,尽管我正在编写要打开的写入格式,但它会继续打印错误消息。我尝试在输入后清除输入“cin”和“filename”,但它不起作用。有任何想法吗 ?

string getFileInput()
{
    string filename;
    fstream file;

    cout << "Please enter the name of the file: ";
    getline(cin, filename);
    file.open(filename.c_str());
    while(!file.is_open())
    {
        file.clear(); file.ignore();
        cout << "File name is incorrect, please enter again: ";
        cin.clear(); cin.ignore();

        getline(cin, filename);
        file.open(filename.c_str());
    }
    // Extra condition. Empty file
    if (file.eof())
    {
        cout << filename << " is an empty file." << endl;
    }
    file.close();
    return filename;
}

标签: c++filevalidationinputfilestream

解决方案


我可以复制和修复。

问题是由cin.ignore(). 根据cppreference

...输入序列中的下一个可用字符 c 是 delim

所以ignore将阅读下一行,直到换行,然后不理会该换行。而下面getline只能读取一个空字符串!

顺便说一句,对and使用未打开的fstream( file)至少是无用的,并且可能是有害的,因为这些方法预计将在打开的流上调用。而且使用也是无用的,并且可能是有害的:如果由于任何原因出现读取错误(例如,因为您到达文件末尾),您将始终清除错误条件并在应该中止时再次尝试读取。ignoreclearcin.clear()

最后,仅读取由于文件结尾而没有返回任何eof内容后才设置条件。打开空文件时永远不会设置它,也不会成功读取文件末尾。

所以函数应该归结为:

string getFileInput()
{
    string filename;
    fstream file;

    cout << "Please enter the name of the file: ";
    getline(cin, filename);
    if (! cin) {
        // test the error immediately and before using filename!
        cerr << "read error: aborting...\n";
        return "";
    }
    file.open(filename.c_str());
    while(!file.is_open())
    {
        cout << "File name is incorrect, please enter again: ";

        getline(cin, filename);
        if (! cin) {
            // test the error immediately and before using filename!
            cerr << "read error: aborting...\n";
            return "";
        }
        file.open(filename.c_str());
    }
    file.close();
    return filename;
}

推荐阅读