Любая причина, почему std :: ofstream объект не закроется должным образом?

StackOverflow https://stackoverflow.com/questions/4058917

Вопрос

Я заметил в моем 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(), чтобы исключить ошибку доступа к файлу как необработанное условие, которое сбивает вашего наблюдаемого поведения.

На данный момент я предлагаю вам исправить эти очевидные недоразумения и вернуться с более конкретными вопросами, если вы не можете его работать.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top