Любая причина, почему std :: ofstream объект не закроется должным образом?
-
27-09-2019 - |
Вопрос
Я заметил в моем C ++ код, который в любое время я закрываю std::ofstream
объект, который я не могу открыть файл, с которым я закрыл std::ifstream
. std::ifstream
С. open
Функция всегда не удастся.
Есть ли что-нибудь «дополнительно», я могу сделать, чтобы убедиться, что мой std :: ofstream объект закрывается правильно?
Кто-то, вероятно, собирается попросить увидеть мой конкретный код, так что ради того, чтобы сохранить этот пост маленький, я приставил его здесь. Отказ В моем коде после пробега через случай A или D всех std::ifstream
Открытые звонки потерпели неудачу. (До публикации этого вопроса у меня было несколько людей, которые играют с моим кодом, который не смогли сделать что-то, кроме этого std::ofstream
Закрыть неудачу по неизвестным причинам)
Спасибо заранее на любую и все ответы получали.
Код есть
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
typedef struct Entry
{
string Name;
string Address;
string Phone;
};
int main()
{
bool exit = false, found = false;
char input, ch;
string stringinput, stringoutput;
ifstream fin, ibuffer;
ofstream fout, obuffer;
Entry buffer;
while(!exit)
{
cout << "Welcome to the Address Book Application!" << endl << endl;
cout << "\tSelect an option:" << endl << endl;
cout << "\tA -- Add New Entry" << endl;
cout << "\tD -- Delete an Entry" << endl;
cout << "\tS -- Search for an Existing Entry" << endl;
cout << "\tE -- Exit" << endl << endl;
cin >> input;
switch(input)
{
case 'a':
case 'A':
cin.ignore(255,'\n');//Apparently necessary because an extra new line carrys over in the cin stream
system("cls");
//Get Information from User
cout << "Enter Phone Number: ";
getline(cin, buffer.Phone);
cout << endl << "Enter Name: ";
getline(cin, buffer.Name);
cout << endl << "Enter Address: ";
getline(cin, buffer.Address);
/*Copy existing database into a buffer. In other words, back it up*/
fin.open("address.txt");
if(!fin)
{
fin.close();
fout.open("address.txt");
fout << buffer.Phone << endl << buffer.Name << endl << buffer.Address << endl;
}
if(fin)
{
obuffer.open("buffer.txt");
while(fin && fin.get(ch))
obuffer.put(ch);
fin.close();
obuffer.close();
/*Copy buffer to new database file*/
ibuffer.open("buffer.txt");
fout.open("address.txt");//This removes all of the previously existing info from database.txt
while(ibuffer && ibuffer.get(ch))
fout.put(ch);
ibuffer.close();
remove("buffer.txt");//Delete the buffer
fout << endl << buffer.Phone << endl << buffer.Name << endl << buffer.Address << endl;
}
buffer.Phone.erase();
buffer.Name.erase();
buffer.Address.erase();
fout.close();
break;
case 'd':
case 'D':
cin.ignore(255,'\n');//Apparently necessary because an extra new line carrys over in the cin stream
system("cls");
cout << "Enter the phone number of the entry to delete: ";
cin >> stringinput;
fin.open("address.txt");
if(!fin)
{
cout << endl << "No entries exist!";
fin.close();
break;
}
obuffer.open("buffer.txt");
/* Copy everything over into the buffer besides the account we wish to delete */
while(!fin.eof())
{
fin.read(&ch, sizeof(char));
if(ch != '\n' && ch != '\0')
stringoutput += ch;
if(ch == '\n' || ch == '\0')
{
if(stringinput.compare(stringoutput))
{
stringoutput += ch;
obuffer << stringoutput;
stringoutput.erase();
}
if(!stringinput.compare(stringoutput))
{
stringoutput += ch;
getline(fin, stringoutput);
getline(fin, stringoutput);
fin.read(&ch, sizeof(char));//Get rid of the extra '\n'
stringoutput.erase();
}
}
}
//Hack: Copy the last line over since the loop for some reason doesn't
obuffer << stringoutput;
stringoutput.erase();
fin.close();
obuffer.close();
fout.open("address.txt");
ibuffer.open("buffer.txt");
while(ibuffer && ibuffer.get(ch))
fout.put(ch);
ibuffer.close();
fout.close();
remove("buffer.txt");
cout << endl << "Entry " << stringinput << " deleted successfully!" << endl;
stringinput.erase();
stringoutput.erase();
break;
case 's':
case 'S':
cin.ignore(255,'\n');//Apparently necessary because an extra new line carrys over in the cin stream
system("cls");
found = false;
fin.open("address.txt");
if(!fin)
{
cout << "No entries currently exist!" << endl << endl;
fin.close();
break;
}
cout << "Enter the phone number to search for: ";
cin >> stringinput;
while(!fin.eof())
{
fin.read(&ch, sizeof(char));
if(ch != '\n' && ch != '\0')
stringoutput += ch;
if(ch == '\n' || ch == '\0')
{
if(!stringinput.compare(stringoutput))
{
found = true;
break;
}
stringoutput.erase();
}
}
if(found)
{
cout << "Phone Number: " << stringinput << endl;
getline(fin, stringoutput);
cout << "Name: " << stringoutput << endl;
getline(fin, stringoutput);
cout << "Address: " << stringoutput << endl << endl;
}
if(!found)
{
stringoutput.erase();
cout << endl << stringinput << " is not in the address book!" << endl << endl;
}
stringinput.erase();
stringoutput.erase();
fin.close();
break;
case 'e':
case 'E':
exit = true;
break;
default:
system("cls");
cout << input << " is not a valid option." << endl << endl;
break;
}
}
return 0;
}
Решение
Лучший способ убедиться, что ваши потоки сбрасываются в каждой точке этой обработки, не говоря уже о том, чтобы их явно закрыть, но, чтобы объявить их в точке использования и позволить им выйти из неисправности. Это точка Raii, которая была сделана в комментариях. В вашем случае это означает, что перемещение DENCAWAINE от верхней части функции в каждую руку переключателя, где они используются. Таким образом, вы можете быть уверены, что каждый файл чисто закрыт при выходе из определенного case
, как по течению и IFSTREAM закрывают файл во время разрушения на выходе сфера.
Еще одна вещь, которую я заметил, это то, что вы тестируете странную вещь после открытия файла:
fin.open("address.txt");
if(!fin)
Это тесты для плохого потока, но я не думаю, что он завершен - если вы тестируете на успешную открытую, вы также должны проверить
fin.open("address.txt");
if (!fin.is_open())
Все ваши петли обработки файлов и open()
Звонки должны проверить на fin.fail()
или fout.fail()
также как и fin.eof()
, чтобы исключить ошибку доступа к файлу как необработанное условие, которое сбивает вашего наблюдаемого поведения.
На данный момент я предлагаю вам исправить эти очевидные недоразумения и вернуться с более конкретными вопросами, если вы не можете его работать.