C++打开文本文件的输入校验
Input validation of opening a text file in 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()
引起的。根据 cppreference:
... the next available character c in the input sequence is delim
因此 ignore
将读取下一行,直到换行符,并且 保留换行符 。而后面的getline
只能读取一个空字符串!
顺便说一句,对 ignore
和 clear
使用未打开的 fstream
(file
) 至少是无用的,并且可能是有害的,因为这些方法是预期的在开放流中调用。使用 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;
}
我正在构建一个输入验证函数,它接受用户的输入并尝试打开该文件。如果用户输入的格式不正确,则重复。正确的格式是:
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()
引起的。根据 cppreference:
... the next available character c in the input sequence is delim
因此 ignore
将读取下一行,直到换行符,并且 保留换行符 。而后面的getline
只能读取一个空字符串!
顺便说一句,对 ignore
和 clear
使用未打开的 fstream
(file
) 至少是无用的,并且可能是有害的,因为这些方法是预期的在开放流中调用。使用 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;
}