#c #vector #fstream
Вопрос:
Я пытаюсь удалить элемент из моего вектора, который хранится в моем файле. Я могу добавлять элементы в свой вектор, но я не могу сделать это, чтобы удалить элемент. Я попытался удалить элемент из вектора без использования fstream, и он отлично работает, так что моя проблема в файле. Есть ли способ удалить элемент из моего вектора с помощью fstream ?
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <fstream>
using namespace std;
void Menu()
{
cout << "******************" << endl;
cout << "1 - Add student" << endl;
cout << "2 - Delete student" << endl;
cout << "3 - All students" << endl;
cout << "******************" << endl;
}
struct School
{
string Name;
string remove;
int Ages;
int Option;
};
int main()
{
ofstream Myfile("practiceFile.txt", ios::app);
School Students;
vector <string> Names;
if(!Myfile.is_open())
{
cout << "Error opening file" << endl;
}
if(Myfile.is_open())
{
Menu();
cout << endl;
cout << "Option: ";
cin >> Students.Option;
cin.ignore();
if(Students.Option == 1)
{
cout << "Enter name: ";
getline(cin, Students.Name);
Names.push_back(Students.Name);
for(int i = 0; i < Names.size(); i )
{
Myfile << Names[i] << endl;
}
}
if(Students.Option == 2)
{
cout << "Enter name: ";
getline(cin, Students.remove);
for(int i = 0; i < Names.size(); i )
{
if(Students.remove == Names[i])
{
auto itr = find(Names.begin(), Names.end(), Students.remove);
if(itr != Names.end())
{
Names.erase(itr);
}
}
}
}
}
string line;
ifstream NewFile("practiceFile.txt", ios::in);
while(NewFile >> line)
{
if(Students.Option == 3)
{
cout << line << endl;
}
}
}
Комментарии:
1. Удалите его из вектора, а затем запишите весь файл, используя содержимое вектора.
Ответ №1:
Есть несколько способов, которыми вы могли бы это сделать.
- Переписывайте файл всякий раз, когда список обновляется, используя вектор в качестве «руководства» для написания предостережения здесь заключается в том, что если в какой-либо момент ваш код вызовет исключение, файл останется в неопределенном состоянии, что может привести к потере ваших данных. Пример:
std::vector<std::string> Names;
std::ofstream MyFile("practiceFile.txt", std::ios::app);
// add or remove names
// clear the file using truncate mode
MyFile.close();
MyFile.open("practiceFile.txt", std::ios::trunc | std::ios::out);
// write out the whole list of names
for (autoamp; Name : Names)
MyFile << Name << std::endl;
- Другим (вероятно, лучшим) способом была бы запись во временный файл, единственное предостережение здесь заключается в том, что если временный файл существует, вы будете перезаписывать все, что в нем есть
std::vector<std::string> Names;
std::ofstream MyFile("practiceFile.txt", std::ios::app);
// add or remove names
// create a temp file
std::ofstream TempFile("practiceFile_temp.txt", std::ios::trunc | std::ios::out);
// write out the whole list of names
for (autoamp; Name : Names)
TempFile << Name << std::endl;
// close all open files
TempFile.close();
MyFile.close();
// delete the old file
std::remove("practiceFile.txt");
// move the temp file to the new file
std::rename("practiceFile_temp.txt", "practiceFile.txt")
Здесь есть несколько вещей, которые вы можете сделать лучше, например, сохранить путь к файлу в какой-нибудь постоянной переменной, чтобы случайно не забыть его где-нибудь изменить или что-то еще, но что бы вы ни делали, вам придется полностью переписать файл.
Редактировать
Как упоминал Тед Лингмо, лучшим подходом для второго метода было бы использование std::filesystem::rename
, которое автоматически удалит старый файл и заменит его новым. Кроме того, есть дополнительное преимущество наличия исключений C , которые вы можете распространять на абонентов, если вам когда-нибудь это понадобится:
std::vector<std::string> Names;
std::ofstream MyFile("practiceFile.txt", std::ios::app);
// add or remove names
// create a temp file
std::ofstream TempFile("practiceFile_temp.txt", std::ios::trunc | std::ios::out);
// write out the whole list of names
for (autoamp; Name : Names)
TempFile << Name << std::endl;
// close all open files
TempFile.close();
MyFile.close();
// move the temp file to the new file
std::filesystem::rename("practiceFile_temp.txt", "practiceFile.txt");
Комментарии:
1. Однако я бы не стал удалять старый файл. Просто позвольте переименованию разорвать его связь.
2. @TedLyngmo из cppreference : «Если имя файла new_filename существует, поведение определяется реализацией».
3. Спасибо за ваш ответ, я собираюсь проверить это сейчас. @msimonelli
4. Правда. Я бы использовал
std::filesystem::rename
вместо этого. Использование thst гарантирует атомарное удаление старого файла и переименование нового.5. Я боролся с #include <файловой системой> . Я не могу заставить это работать в моем визуальном коде. Я пытался обновить свой визуальный код до C 17, но не могу. Мои конфигурации показывают, что я перешел на C 17, но я все еще получаю в своем сборнике: «Содержимое <файловой системы> доступно только с C 17 или более поздней версией». Что я могу сделать ? @msimonelli