问题描述
我正在构建一个输入验证函数,该函数接受用户的输入并尝试打开该文件。如果用户没有输入正确的格式,则重复。正确的格式是:
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
只能读取一个空字符串!
顺便说一句,对 fstream
和 file
使用未打开的 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;
}