在 C++ 中打开文本文件的输入验证

问题描述

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

test1.txt

如果我在第一次运行时编写了正确的格式,我的函数就可以工作,但是在第二次运行后,尽管我正在编写要打开的写入格式,但它仍会继续打印错误消息。我试图在接受输入后清除输入“cin”和“文件名”,但没有奏效。有什么想法吗?

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;
}

解决方法

我可以重现和修复。

问题是由 cin.ignore() 引起的。根据{{​​3}}:

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

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

顺便说一句,对 fstreamfile 使用未打开的 ignore (clear) 至少是无用的,并且可能是有害的,因为这些方法预计在一个开放的流上调用。并且使用 cin.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;
}