从文件中删除特定行
Delete specific line from file
我正在尝试从C++文件中按 id 删除特定行,这是我的代码:
void deleteRow()
{
ifstream inDb("files/students.dat", ios::in);
if(!inDb)
{
cerr << "File could no be opened!n";
}
cout << countRowsOfDb() << " records." << endl;
Student *studentsArray[countRowsOfDb()];
int n = 0;
while(inDb >> id >> name >> grade >> points >> type)
{
studentsArray[n] = new Student(id, name, grade, points, type);
n++;
}
inDb.close();
for(int i = 0; i < countRowsOfDb(); i++)
{
cout << studentsArray[i]->id << " " << studentsArray[i]->name << " " << studentsArray[i]->grade << " "
<< studentsArray[i]->points << " " << studentsArray[i]->type << "n";
}
cout << "nWhich one you would like to delete? Enter an id: ";
string term;
cin >> term;
ofstream outDb("files/students.dat", ios::out);
if(!outDb)
{
cerr << "File could no be opened!n";
}
for(int i = 0; i < countRowsOfDb(); i++)
{
if(studentsArray[i]->id != term)
{
outDb << studentsArray[i]->id << " " << studentsArray[i]->name << " " << studentsArray[i]->grade << " "
<< studentsArray[i]->points << " " << studentsArray[i]->type << "n";
}
}
outDb.close();
cout << "nObject deleted!n";
}
我创建一个输入文件流,然后获取所有行,使其成为对象数组并在屏幕上显示它们,然后通过键入 id 询问要删除哪一个,当我键入 id 时,我尝试仅放置数组的所有这些元素,而没有具有相同 id 的元素, 但它不起作用,之后文件中没有任何内容。有什么想法吗?
countRowsOfDb()
里有什么? 如果它打开文件并计算行数在其中(我不知道它还能做什么),那么它就不会在最后一个循环中找到很多,因为创建了 ostream 与相同的名称将清空该文件。
更一般地说,这是一种非常低效的做事方式(并且如果文件格式有错误,很容易失败)。处理此问题的最佳方法是使用 std::vector<Student>
,具有:
studentVector.push_back( Student( id, name, grade, points, type ) );
在输入循环中。 在所有后面的循环中,studentVector.size()
给出了条目数,或者您可以使用迭代器。
更好的是使用 std::getline
输入,然后初始化一个std::istringstream
来解析每一行。 这将更可靠地捕获输入格式错误。 像这样:
std::string line;
int lineNumber = 0;
while ( std::getline( inDb, line ) ) {
++ lineNumber;
std::istringstream data( line );
if ( data >> id >> name >> grade >> points >> type ) {
studentVector.push_back( Student( id, name, grade, points, type ) );
} else {
std::cerr << "Format error in lne " << lineNumber << std::endl;
}
}
此外,通常更好的主意是写入单独的文件,然后在验证写入有效后重命名它,即:
std::ofstream outDb( "files/students.dat.new" );
// Do output...
outDb.close();
if ( outDb ) {
remove( "files/students.dat" );
rename( "files/students.dat.new", "files/students.dat" );
} else {
std::cerr << "Write error on output" << std::endl;
}
当然,任何写入错误都会导致返回 EXIT_FAILURE
来自main
. (这是全局变量的一种情况或者单例是合理的 - 跟踪返回代码。
我通过添加一个重播内容的新函数来使其工作,因此现在的代码是:
void deleteRow()
{
ifstream inDb("files/students.dat", ios::in);
if(!inDb)
{
cerr << "File could no be opened!n";
}
cout << countRowsOfDb() << " records." << endl;
Student *studentsArray[countRowsOfDb()];
int n = 0;
while(inDb >> id >> name >> grade >> points >> type)
{
studentsArray[n] = new Student(id, name, grade, points, type);
n++;
}
inDb.close();
for(int i = 0; i < countRowsOfDb(); i++)
{
cout << studentsArray[i]->id << " " << studentsArray[i]->name << " " << studentsArray[i]->grade << " "
<< studentsArray[i]->points << " " << studentsArray[i]->type << "n";
}
cout << "nWhich one you would like to delete? Enter an id: ";
string term;
cin >> term;
for(int i = 0; i < countRowsOfDb(); i++)
{
if(studentsArray[i]->id != term)
{
Student studentTemp(studentsArray[i]->id, studentsArray[i]->name, studentsArray[i]->grade, studentsArray[i]->points, studentsArray[i]->type);
replaceRow(studentTemp);
}
}
cout << "nObject deleted!n";
}
替换函数为:
void replaceRow(Student student)
{
ofstream outDb("files/students.dat", ios::out);
if(!outDb)
{
cerr << "File could no be opened!n";
}
outDb << student.getId() << ' ' << student.getName() << ' ' << student.getGrade()
<< ' ' << student.getPoints() << ' ' << student.getType() << endl;
outDb.close();
}
相关文章:
- 如何在输入新内容 c++ 之前删除文件中的所有内容
- 文件模式标志"ios::app"是否用于删除文件(如果文件已存在)?
- 查找并删除文件 C++ 中的整行
- 如何删除文件中的数字,通过 c++ fstream 的
- 以编程方式防止重命名或删除文件,但仍使其可写
- C++ 如何使用_rmdir删除文件?
- 关于从驱动器中删除文件的问题
- Linux 从永远在线的应用程序中创建和删除文件
- 用户使用C++中的删除功能删除文件
- 如何在C++中删除文件中的一部分文本
- 我可以删除 *.o文件(代码:: blocks)
- 为什么std ::删除文件始终返回-1
- C++ 使用数字删除文件 io 行
- 如何使用 c++ 删除文件夹及其内容
- 如何在 C++ 中的文件处理中删除文件
- 用数字删除文件
- Cygwin:打开句柄时删除文件
- 接收文件并删除文件中的重复项
- 删除文件 C++ 中字符串中最后一个出现的字符
- 在循环内删除文件时使提升recursive_directory_iterator无效