Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 28.08.2011, 18:42   #1
zetaBiT
Пользователь
 
Регистрация: 01.05.2010
Сообщений: 11
По умолчанию запись и загрузка с бинарного файла массива структур

помогите пожалуйста, что делаю не так?

Код:

//сама структура
struct TUser{
    unsigned int UIN;                               //уин
    int id, many, raiting;                           //айди, деньги, рейтинг
    AnsiString nick, status, group, POL, SP;  //ник, статус, группа, пол, СП
};

TUser *reg_users = NULL;
int n_reg_users = 0;  


void SaveRegUsers(){
  FILE *FH = NULL;
  size_t file_size = (sizeof(TUser)*n_reg_users);
 
  if ((FH = fopen("reg_users.dat", "wb")) == NULL) {
    Dialogs::ShowMessage("не могу открыть файл reg_users.dat для записи\n");
    return ;
  }
 
  for(int i=0; i<n_reg_users; i++)fwrite(&reg_users[i],file_size, 1, FH);
  fclose(FH);
 
  return ;
}
 
 
//загрузка массива структур
void LoadRegUsers(){
  FILE *FH = NULL;
  size_t file_size = 0;
 
  if ((FH = fopen("reg_users.dat", "rb")) == NULL) {
    Dialogs::ShowMessage("не могу открыть файл reg_users.dat\n");
    return ;
  }
 
  fseek(FH, 0, 2);
  int n = ftell(FH); //получаю размер файла
  rewind(FH);
 
  n_reg_users = n/sizeof(TUser);//получаю количество структур(вот тут именно и косяк при загрузке, есть сомнения что не правильно сохраняю)
  F->sizeE->Text=n;               //вывод размера файла
  F->sizeofE->Text=sizeof(TUser);//вывод размера структуры
  F->nE->Text=n_reg_users;       //вывод количества структур
  if(reg_users) delete[]reg_users;
  reg_users = new TUser[n_reg_users]; //выделяю массив под данное кол. структур
 
 
  fread(&reg_users, sizeof(TUser), file_size, FH); //правильно считываю с файла????
  fclose(FH);
 

//вывод в список (потом расширеная по клику на список информация о пользователе)
  F->LB->Items->Clear();
  for(int i=0; i<n_reg_users; i++) F->LB->Items->Add(IntToStr(reg_users[i].UIN));
  return ;
}

при загрузке, количество структур больше чем нужно.....

Последний раз редактировалось zetaBiT; 28.08.2011 в 18:53.
zetaBiT вне форума Ответить с цитированием
Старый 28.08.2011, 18:49   #2
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

нельзя тупо сохранять в файл структуры содержащие указатели/ссылки.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 28.08.2011, 19:00   #3
zetaBiT
Пользователь
 
Регистрация: 01.05.2010
Сообщений: 11
По умолчанию

я верно понял???
Код:
fwrite(reg_users,file_size, 1, FH);
спасибо, теперь хоть количество структур определяется правильно
но при загрузке все равно не те данные какие сохранялись

а загрузка через ссылку у меня верна?
Код:
fread(&reg_users, sizeof(TUser), file_size, FH);
zetaBiT вне форума Ответить с цитированием
Старый 28.08.2011, 19:02   #4
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

проблема в структуре у вас, класс AnsiString содержит указатель.
и именно про них я и говорил, вывод, нужно ручками сохранять по-членно.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 28.08.2011, 19:08   #5
zetaBiT
Пользователь
 
Регистрация: 01.05.2010
Сообщений: 11
По умолчанию

помоему понял....сейчас попробую, отпишусь о результатах
zetaBiT вне форума Ответить с цитированием
Старый 28.08.2011, 19:35   #6
zetaBiT
Пользователь
 
Регистрация: 01.05.2010
Сообщений: 11
По умолчанию

Код:
  for(int i=0; i<n_reg_users; i++){
    fwrite(&reg_users[i].UIN,sizeof(unsigned int), 1, FH);
    fwrite(&reg_users[i].id, sizeof(int), 1, FH);
    fwrite(&reg_users[i].many, sizeof(int), 1, FH);
    fwrite(&reg_users[i].raiting, sizeof(int), 1, FH);
    fwrite(&reg_users[i].nick, sizeof(AnsiString), 1, FH);
    fwrite(&reg_users[i].status, sizeof(AnsiString), 1, FH);
    fwrite(&reg_users[i].group, sizeof(AnsiString), 1, FH);
    fwrite(&reg_users[i].POL, sizeof(AnsiString), 1, FH);
    fwrite(&reg_users[i].SP, sizeof(AnsiString), 1, FH);
  }
и так-же чтение

Код:
  for(int i=0; i<n_reg_users; i++){
    fread(&reg_users[i].UIN,sizeof(unsigned int), 1, FH);
    fread(&reg_users[i].id, sizeof(int), 1, FH);
    fread(&reg_users[i].many, sizeof(int), 1, FH);
    fread(&reg_users[i].raiting, sizeof(int), 1, FH);
    fread(&reg_users[i].nick, sizeof(AnsiString), 1, FH);
    fread(&reg_users[i].status, sizeof(AnsiString), 1, FH);
    fread(&reg_users[i].group, sizeof(AnsiString), 1, FH);
    fread(&reg_users[i].POL, sizeof(AnsiString), 1, FH);
    fread(&reg_users[i].SP, sizeof(AnsiString), 1, FH);
  }

но опять проблемка...при добавлении использую функции

Код:
TUser* add_user(){
  int n=n_reg_users+1;     //количество структур + новая структура
  TUser *buf=new TUser[n]; //выделяем память для массива  кол. структур tn
  for (int i=0;i<n_reg_users;i++)   //цикл в котором
    buf[i]=reg_users[i];            //все
  if(reg_users)delete[]reg_users;   //если что-то есть очищаем
  reg_users=buf;                    //из временного массива все в глобальный массив
  n_reg_users=n;                    //глобальные данные о количестве элеметнов=
  return &reg_users[n-1];
}

int inRegList(AnsiString uin){
  unsigned int UIN=uin.ToInt();
  for(int i=0; i<n_reg_users; i++){
    if(reg_users[i].UIN==UIN)return i;
  }
  return -1;
}

int AddRegUser(AnsiString uin, AnsiString nick){
  unsigned int UIN = uin.ToInt();
  if(inRegList(uin)>=0)return -1;  //если уже зарегистрирован -1

  TUser *user = add_user();

  user->UIN = UIN;
  user->id = n_reg_users;
  user->many    = 1000;
  user->group   = "user";
  user->raiting = 100;
  user->nick    = nick;
  user->status  = "*****";
  user->POL     = "*****";
  user->SP      = "*****";

  return user->id;
}
все работает но при загрузке в конце параметра group и параметра pol структуры та то в самом конце находиться, - добавляется иероглиф, пример

UIN 3333
id 1
many 1000
group user
raiting 100
nick ddddddd
status *****
POL *****
SP *****


после загрузки с файла



UIN 3333
id 1
many 1000
group user
raiting 100
nick ddddddd
status *****
POL *****
SP ****¤


и уже не могу добавить пользователя...
ошибка invalid pointer operation

и строка в функции что возвращает ссылку на новую структуру add_user()
Код:
 if(reg_users)delete[]reg_users;    //если что-то есть очищаем
я совсем запутался...

Последний раз редактировалось zetaBiT; 28.08.2011 в 19:39.
zetaBiT вне форума Ответить с цитированием
Старый 28.08.2011, 19:44   #7
zetaBiT
Пользователь
 
Регистрация: 01.05.2010
Сообщений: 11
По умолчанию

теперь вообще выдает ошибку на group... а может мне в структуре сделать AnsiString какойто длины???
zetaBiT вне форума Ответить с цитированием
Старый 28.08.2011, 20:00   #8
zetaBiT
Пользователь
 
Регистрация: 01.05.2010
Сообщений: 11
По умолчанию

ааа помогите пожалуйста! мне нужен вместо AnsiString char постоянной длины???
zetaBiT вне форума Ответить с цитированием
Старый 28.08.2011, 22:29   #9
zetaBiT
Пользователь
 
Регистрация: 01.05.2010
Сообщений: 11
По умолчанию

разобрался наконецто

AnsiString - это класс, содержащий ссылку\указатель c_str на динамически выделяемую строку. Конструктор по умолчанию создает пустую AnsiString с c_str = NULL и соотв-но в твоей структуре tmp все AnsiString содержат NULL
Избежать облома можно если перед первым чтением выделить память под все строковые мемберы tmp вызовом SetLength

т.е. структуры которые в файл должны иметь неизменный размер


через время напишу как должна быть в моем случае структура
zetaBiT вне форума Ответить с цитированием
Старый 28.08.2011, 22:43   #10
zetaBiT
Пользователь
 
Регистрация: 01.05.2010
Сообщений: 11
По умолчанию

структура

Код:
struct TUser{
    unsigned int UIN;                         //уин
    int id, many, raiting;                    //айди, деньги, рейтинг
    char nick[20], status[40], group[20], POL[4], SP[20];
};
сохранение
Код:
void SaveRegUsers(){
  FILE *FH = NULL;
  if ((FH = fopen("reg_users.dat", "wb")) == NULL) {
    Dialogs::ShowMessage("не могу открыть файл reg_users.dat для записи\n");
    return ;
  }
  for(int i=0; i<n_reg_users; i++)fwrite(&reg_users[i], sizeof(TUser), 1, FH);
  fclose(FH);
}

загрузка
Код:
void LoadRegUsers(){
  FILE *FH = NULL;
  if ((FH = fopen("reg_users.dat", "rb")) == NULL) {
    Dialogs::ShowMessage("не могу открыть файл reg_users.dat\n");
    return ;
  }
  fseek(FH, 0, 2);
  int n = ftell(FH);
  rewind(FH);
  n_reg_users = n/sizeof(TUser);
  F->sizeE->Text=n;
  F->sizeofE->Text=sizeof(TUser);
  F->nE->Text=n_reg_users;
  if(reg_users) delete[]reg_users;
  reg_users = new TUser[n_reg_users];
  for(int i=0; i<n_reg_users; i++)fread(&reg_users[i], sizeof(TUser), 1, FH);
  fclose(FH);
  F->LB->Items->Clear();
  for(int i=0; i<n_reg_users; i++) F->LB->Items->Add(IntToStr(reg_users[i].UIN));
}
все работает %)

Пепел Феникса, спасибо за направление в нужное русло!
zetaBiT вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
запись/чтение из бинарного файла. H1ghlander Общие вопросы C/C++ 0 21.11.2010 17:44
сохранение\ загрузка List View в\из бинарного файла bulldog5293 Общие вопросы Delphi 6 12.07.2010 13:59
Заполнение массива структур данными из файла Brutallus Общие вопросы C/C++ 0 26.11.2009 19:01
Запись/чтение из бинарного файла - непонятные проблемы.... Jorgen Общие вопросы C/C++ 1 26.11.2009 11:45
Запись массива с цифрами файл, и его загрузка Kycaka Общие вопросы C/C++ 4 08.06.2009 22:38