Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Запись класса в файл (Borland C++ 3.1)


Автор: DjoNIK 4.6.2007, 23:33
Доброго времени суток!
Я так понял, что классы fstream, ifstream и ofstream есть в этом компиляторе, но как с ними работать я не знаю, 
поэтому выбрал класический C-шный вариант работы с онными. Но мой код при PutDB() заносит какую-то совершенно 
"левую" информацию в файл, и, возможно по этой причине (или по другой), GetDB() выдаёт также что-то 
невообразимое.
Помогите понять в чём проблема!
Код

class player
{
private:
public:
    const int ID;
    static int count;
    char nik[35];
    float balance;
    long int seek_pos;
    float stake;
    int cock_num;
public:
    player() : ID(++count), balance(0.00f)
    {
     strcpy( nik, "unnamed" );
    }
    player( const char* name, float b, long int s_p ) :
      ID(++count), balance(b), seek_pos(s_p)
    {
     strcpy( nik, name );
    }
    void GetData() const
    {
      cout << "\n €¬п ЁЈа®Є : " << nik;            // Имя игрока
      cout << "\n Ѓ « ­б ЁЈа®Є : " << balance;        // Баланс игрока
    }
    void PutData()
    {
      cout << "\n ‚ўҐ¤ЁвҐ Ё¬п ЁЈа®Є : ";            // Введите имя игрока
      cin >> nik;
      cout << "\n ‚ўҐ¤ЁвҐ ЇҐаў®­ з «м­л© Ў « ­б ЁЈа®Є : ";    // Введите первоначальный баланс
      cin >> balance;
    }
    void Stake()
    {
       cout << "\n ђ §¬Ґа бв ўЄЁ: ";            // Размер ставки
       cin >> stake;
       cout << "\n Ќ  Є Є®Ј® в а Є ­  Ўг¤Ґ¬ бв ўЁвм?";    // Номер таракана
       cin >> cock_num;
    }
    void ResOfStake( int c_n )
    {
       if( cock_num==c_n )
        {
         balance += stake;
        }
       else
        {
         balance -= stake;
        }
    }
};


class DB
{
private:
    player* pl[100];
    char nik[35];
    float balance;
    FILE* f;
    char str[77];
public:
    void PutDB()
     {
      int i=0;
      char *strf, *strd;
      char choice;
      int dec, sign, ndig = 10;
      f = fopen("file.dat", "ab");
      if(!f)
       {
        cout << "\n Џа®Ў«Ґ¬л б ®вЄалвЁҐ¬ д ©« !";        // Проблемы с открытием файла
        getch();
        exit(1);
       }
      do
      {
       pl[i]=new player;
       pl[i]->PutData();
       fwrite( pl[i], sizeof(player), 1, f);
       i++;
       cout << "\n …йс ®¤Ё­ ЁЈа®Є?(y/n)";            // Ещё один игрок?(y/n)
       cin >> choice;
      }
      while(choice!='n');
      fclose( f );
     }

    void GetDB()
     {
      int i=0;
      char *strf, *strd;
      int dec, sign, ndig = 10;
      f = fopen("file.dat", "ab");
      if(!f)
       {
        cout << "\n Џа®Ў«Ґ¬л б ®вЄалвЁҐ¬ д ©« !";        // Проблемы с открытием файла
        getch();
        exit(1);
       }
      while( !feof(f) );
      {
       pl[i]=new player;
       fread( pl[i], sizeof(player), 1, f);
       pl[i]->GetData();
       i++;
      }
      fclose( f );
     }
 }

Автор: nerezus 5.6.2007, 08:18
Ты хоть знаешь, что fwrite делает?
У тебя же вместо буффера объект!!

P.S. и что, даже компилер ошибки не выдает?
P.P.S. Про сериализацию слышал?

Автор: EnergoHokum 5.6.2007, 08:25
По моему, сериализация объектов классов - очччень небезопасное занятие. Что случится, если сериализован объект с открытыми дескрипторами (файлов или чего ещё), а при восстановлении объекты, на которые указывали дескрипторы, удалены? Явно ничего хорошего. Ну, в качестве Експеримента можно поиграть, но в реальный проект я бы побоялся такое вводить.

Автор: nerezus 5.6.2007, 08:39
EnergoHokum, ну дык нужно при сериализации объекта сериализовывать объекты в нем, например агрегированный объект ФС.

Добавлено через 1 минуту и 27 секунд
Да или прросто при сериализации закрываем хендл файла и сохраняем имя. При обратном процессе - открываем файл на прежней позиции.

Автор: math64 5.6.2007, 08:47
Код

 f = fopen("file.dat", "ab"); // Открытие на дописывание
 f = fopen("file.dat", "wb"); // Открытие на перезапись
 f = fopen("file.dat", "rb"); // Открытие на чтение

class player не имеет виртуальных методов, поэтому можно применить fwrite()/fread(), но лучше
Код

struct PlayerData {
  ...
};
class Player : private PlayerData {
  ...
public:
    void Save(FILE* f) {
       fwrite((PlayerData*)this, sizeof(PlayerData), 1, f);
    }
    void Load(FILE* f) {
       fread((PlayerData*)this, sizeof(PlayerData), 1, f);
    }
}

Кроме того лучше не смешивать ввод/вывод по stdio и iostream в пределах одного файла (в вашем случае - консоль)

Автор: EnergoHokum 5.6.2007, 09:05
Всё равно, сериализация объектов компилируемого языка - неуютно как-то (может, я и зря паникую)

Автор: DjoNIK 5.6.2007, 11:58
Цитата

У тебя же вместо буффера объект!!


Код

player* pl[100];
...
fwrite( pl[i], sizeof(player), 1, f);

Разве указатель не сойдёт за буфер???

Цитата

P.S. и что, даже компилер ошибки не выдает?

Нет, по моему и не должен!

Цитата

P.P.S. Про сериализацию слышал?

Нет.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)