我正在尝试用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的元素,但它不起作用,之后文件中没有任何内容。有什么想法吗?
答案 0 :(得分:2)
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
的{{1}}。 (这是全局变量的一种情况
或单身是合理的 - 跟踪返回代码。)
答案 1 :(得分:0)
我通过添加一个重播内容的新函数使其工作,现在代码是:
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();
}