Форум программистов, компьютерный форум, киберфорум
C++ Qt
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.73/11: Рейтинг темы: голосов - 11, средняя оценка - 4.73
5 / 6 / 4
Регистрация: 18.11.2009
Сообщений: 661
1

Строки конечной длины в полях структуры. Файловое чтение-запись

12.06.2014, 09:14. Просмотров 2308. Ответов 23
Метки нет (Все метки)


Переделываю под QT еще Дельфевый вариант программы хранящей данные в т.н. типизированном файле
(т.е. однотипные записи, должны читаться в массив структур).
Так вот как создать структуру-то эту?
Если в обычном С, С++
C++
1
2
3
4
5
6
7
8
9
10
#include <string.h>
...
struct TComp {
  int tip;//тип 0-настольн,1-ноутбук,2-нетбук,3-КПК,4-смартфон,5-планшетн
  string Marka[40];//модель
  string  Pr[30];//процессор
  int Vop;//объем ОП
  int Vgd;//объем ЖД
  int Price; //цена
            };
то в QT он не находит #include <string.h>. Правда там есть тип QString
и так проходит
C++ (Qt)
1
2
3
4
5
6
7
8
struct TComp {
  int tip;//тип 0-настольн,1-ноутбук,2-нетбук,3-КПК,4-смартфон,5-планшетн
  QString Marka;
  QString Pr;
  int Vop;//объем ОП
  int Vgd;//объем ЖД
  int Price; //цена
            };
однако возникают сразу проблемы с чтением.
Читать видимо в стиле QT надо в моем случае в потоке QDataStream или QTextStream
т.е. вообще не получается "типизированного файла" как в Паскале.
Как правильно написать файловое чтение и запись полей такой структуры (в каждой строке файла-экземпляр такой структуры)
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
12.06.2014, 09:14
Ответы с готовыми решениями:

Файловое чтение и запись данных для решения СЛАУ
Добрый день, данная программа решает СЛАУ методом Гаусса, но каждый раз, при новом запуске...

Чтение/запись структуры
Всем привет! Есть файл, в который записана структура. По сути это дерево и соответственно в каждом...

Чтение/запись структуры
День добрый! Помогите пожалуйста решить задачу: Сформировать текстовый файл, имеющий следующую...

Запись в файл структуры подобной TList переменной длины
День добрый. Вопрос собственно вот в чем: Есть переменная типа списка (TList). я хочу ее...

23
Почетный модератор
11171 / 4128 / 412
Регистрация: 12.06.2008
Сообщений: 11,968
12.06.2014, 09:59 2
В структуре не получится хранить поля переменной длины. В случае с полями переменной длинны в самой структуре хранятся только указатели, а сами данные хранятся уже снаружи. Поэтому если требуется просто записать структуру, то придётся заранее указывать размер. Только обычно используют тип char[]... не уверен, что string будет работать, ведь по сути дела std::string - это класс. К тому же, объявлять как string Pr[30] - это должно объявиться 30 пустых переменных типа string.

В общем, что бы просто записывать и читать структуру в файл придётся указывать что-то вроде
C
1
2
3
4
5
6
7
8
struct TComp {
  int tip;//тип 0-настольн,1-ноутбук,2-нетбук,3-КПК,4-смартфон,5-планшетн
  char Marka[40];//модель
  char  Pr[30];//процессор
  int Vop;//объем ОП
  int Vgd;//объем ЖД
  int Price; //цена
            };
Если нет уверенности, что таких размеров хватит, а хранить слишком длинные переменные не хочется, тогда можно использовать QString, но записывать придётся вручную - размер строки и саму строку. И желательно её вначале перевести в QByteArray, а после этого записывать. И читать так же: прочитать размер, прочитать QByteArray этого размера, а потом перевести его в QString.
0
870 / 769 / 174
Регистрация: 11.01.2012
Сообщений: 1,942
12.06.2014, 10:44 3
Цитата Сообщение от eugrita Посмотреть сообщение
то в QT он не находит #include <string.h>.
А зачем вам string.h ?
Для std::string #include <string>
0
5 / 6 / 4
Регистрация: 18.11.2009
Сообщений: 661
12.06.2014, 11:50  [ТС] 4
да с этим согласен. Я и сам переделал за время поста.
C++ (Qt)
1
2
char Marka[40];
  char  Pr[30];
В моем случае надо считывать записи в список с данными типа TComp. Имеется класс-список ListComp с головным указателем TComp *Head; и методами Add(TComp * value);-добавления структуры в список и
ReadFile(char * fln) -чтения файла в список
В методе ReadFile заведена вспомогательная структура w типа TComp.
Собственно продолжение вопроса -каким методом считывания надо читать файл в структуру w? Каждое поле с помощью f.read(...) или потоковое чтение?
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
bool ListComp::ReadFile(char * fln)
{//чтение из файла 
  QFile f(fln); TComp w;
  if(!f.exists()) return false;
  while (!f.atEnd())
  {
     f.read(w.Marka, sizeof(w.Marka)); f.read(w.Pr,sizeof(w.Pr));
     f.read(w.Vop,sizeof(w.Vop)); f.read(w.Vgd,sizeof(w.Vgd));
     f.read(w.Price,sizeof(w.Price));
     Add(w);
  }
  f.close();
  return true;
}
В данном коде ошибочно чтение из файла в целые поля. Но мне надо прочесть их все независимо от их типов

Добавлено через 5 минут
(должен быть еще метод WriteFile(..) -выгрузки списка в файл)
0
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
12.06.2014, 13:04 5
Поскольку теперь структура состоит из POD типов фиксированного размера, читать можно структуру целиком:

C++
1
f.read((char*)&w,sizeof(TComp));
Писать аналогично.
0
1440 / 1321 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
12.06.2014, 14:56 6
eugrita, в read нужно передавать указатель.
C++
1
f.read(&w.Price,sizeof(w.Price));
Цитата Сообщение от uglyPinokkio Посмотреть сообщение
Поскольку теперь структура состоит из POD типов фиксированного размера, читать можно структуру целиком:
Нельзя.
Изначальный вариант был правильный.
0
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
12.06.2014, 15:07 7
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
Нельзя.
Почему?
0
334 / 182 / 80
Регистрация: 22.08.2013
Сообщений: 724
12.06.2014, 18:44 8
Цитата Сообщение от Humanoid Посмотреть сообщение
В структуре не получится хранить поля переменной длины. В случае с полями переменной длинны в самой структуре хранятся только указатели, а сами данные хранятся уже снаружи. Поэтому если требуется просто записать структуру, то придётся заранее указывать размер.
Разве QDataStream не делает сериализацию (QString)?

Добавлено через 27 минут
Как-то так:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
struct Comp 
{
  int tip;
  QString Marka;
  QString Pr;
  int Vop;
};
 
QDataStream& operator << (QDataStream& out, const Comp& comp)
{
    out << comp.tip << comp.Marka << comp.Pr << comp.Vop;
    return out;
}
 
QDataStream& operator >> (QDataStream& in, Comp& comp)
{
    in >> comp.tip >> comp.Marka >> comp.Pr >> comp.Vop;
    return in;
}
...
 
    QFile file("file.dat");
    file.open(QIODevice::WriteOnly);
    QDataStream out(&file); 
 
    Comp comp_in[2] = {{123, "ASDF", "PP4", 2}, {345, "QWERT", "AAA5", 3}};
 
    out << comp_in[0] << comp_in[1];
 
    file.close();
    file.open(QIODevice::ReadOnly);
    QDataStream in(&file);
    
    Comp comp_out[2];
    in >> comp_out[0] >> comp_out[1];
    file.close();
...
0
1440 / 1321 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
12.06.2014, 19:57 9
Цитата Сообщение от uglyPinokkio Посмотреть сообщение
Почему?
Каков размер структуры?
0
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
12.06.2014, 20:24 10
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
Каков размер структуры?
sizeof(TComp).

И после

Цитата Сообщение от eugrita Посмотреть сообщение
да с этим согласен. Я и сам переделал за время поста.

C++
1
2
char Marka[40];
char Pr[30];
Он фиксированный.
0
1440 / 1321 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
12.06.2014, 21:28 11
Цитата Сообщение от uglyPinokkio Посмотреть сообщение
sizeof(TComp).
а почему размер больше суммы размеров полей структуры?
0
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
12.06.2014, 21:35 12
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
а почему размер больше суммы размеров полей структуры?
Потому что структура не выровнена на байт, что с одной стороны легко исправляется а с другой не является проблемой, пока пишет-читает одно и то же приложение.
0
1440 / 1321 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
12.06.2014, 21:44 13
Цитата Сообщение от uglyPinokkio Посмотреть сообщение
что с одной стороны легко исправляется
Ага. И забивать гвозди в крышку гроба производительности.

Цитата Сообщение от uglyPinokkio Посмотреть сообщение
другой не является проблемой, пока пишет-читает одно и то же приложение.
Напоминаю что топик находится в разделе Кроссплатформенная разработка, где предполагается что приложение должно собираться разными компиляторами, на разных ОС.
Такие штуковины в продакшене не пройдут.
0
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
12.06.2014, 21:53 14
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
Ага. И забивать гвозди в крышку гроба производительности.
Выравнивать не обязательно на байт, требуется только что бы выравнивание было известно.

Цитата Сообщение от Dmitriy_M Посмотреть сообщение
Такие штуковины в продакшене не пройдут.
Правда? .

Разбор бинарного файла, тот же tiff, размером 20-30 мегабайт,имеем их тысяч 100-200.
Я отображу файл в память и разберу наложением структуры оглавления.

Свой вариант предложите?
0
1440 / 1321 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
12.06.2014, 22:13 15
Цитата Сообщение от uglyPinokkio Посмотреть сообщение
Выравнивать не обязательно на байт, требуется только что бы выравнивание было известно.
Ты знаешь какое выравнивание на каких архитектурах оптимальнее?

Цитата Сообщение от uglyPinokkio Посмотреть сообщение
Правда? .
Разбор бинарного файла, тот же tiff, размером 20-30 мегабайт,имеем их тысяч 100-200.
Я отображу файл в память и разберу наложением структуры оглавления.
Это называется перекладывания с больной головы на здоровую.
В продакшене тебе бывают случаи когда приложение поддерживается и развивается годами, и тут нужно поддерживать все версии форматов. И тут уже будет такого
Цитата Сообщение от uglyPinokkio Посмотреть сообщение
пока пишет-читает одно и то же приложение.
В случае с tiff я тоже отображу в памяти и буду использовать структуры, но без прагмы pack или опций компилятора.
0
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
12.06.2014, 22:26 16
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
Ты знаешь какое выравнивание на каких архитектурах оптимальнее?
А зачем? Бинарные файлы выравниваются на байт. Если вдруг зачем-то очень нужно - можно поменять.

Цитата Сообщение от Dmitriy_M Посмотреть сообщение
В продакшене тебе бывают случаи когда приложение поддерживается и развивается годами, и тут нужно поддерживать все версии форматов. И тут уже будет такого
Не понял о чем это.

Цитата Сообщение от Dmitriy_M Посмотреть сообщение
В случае с tiff я тоже отображу в памяти и буду использовать структуры, но без прагмы pack или опций компилятора.
Каким образом, учитывая что структуры в графических файлах (по крайней мере мне известных форматов ) выравниваются на байт? Так же вычитывая по одному полю?
0
5 / 6 / 4
Регистрация: 18.11.2009
Сообщений: 661
13.06.2014, 11:50  [ТС] 17
ну, господа вариант Pinokkio
C++ (Qt)
1
f.read((char*)&w,sizeof(TComp));
привел к сваливанию прогр на чтении.
Вот упрощенный код
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <QCoreApplication>
#include <QFile>
#include <iostream>
 
struct TComp {
  int tip;//тип 0-настольн,1-ноутбук,2-нетбук,3-КПК,4-смартфон,5-планшетн
  char Marka[15];
  char  Pr[20];
  int Vop;//объем ОП
  int Vgd;//объем ЖД
  int Price; //цена
  TComp *next;
            };
class ListComp
...
bool ListComp::ReadFile(char * fln)
{//чтение из файла
  QFile f(fln);  TComp *w;
  if(!f.exists()) return false;
  f.open(QIODevice::ReadOnly);
  while (!f.atEnd())
  {
     f.read((char*)&w,sizeof(TComp));
     std::cout << w->Marka << " " << w->Pr;
     Add(w);
  }
  f.close();
  return true;
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    ListComp *L=new ListComp(); int k=0;
 
    if(!L->ReadFile("d://_Progs//Qt//baza2.txt"))
        std::cout <<  "baza2.txt ne naidena";
    else {
        k=L->GetCount();std::cout <<"k="<<k;
         };
    return a.exec();
}
вставлена даже отладочная печать после чтения. И все равно до нее не доходит и валится
файл baza2.txt имеет содержимое (1 запись)
RS728 INTEL Celeron G530 4096 500 9990
специально выравнивал пробелы чтоб RS728 имело 15 поз, и 4096 было на 36 поз
0
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
13.06.2014, 12:21 18
Цитата Сообщение от eugrita Посмотреть сообщение
привел к сваливанию прогр на чтении.
Вот упрощенный код
Вы читаете по адресу не инициализированного указателя.

TComp *w - замените на TComp w

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

Добавлено через 9 минут
Цитата Сообщение от eugrita Посмотреть сообщение
RS728 INTEL Celeron G530 4096 500 9990
А, ну и читать Вы пытаетесь из текстового файла.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
 
#pragma pack(push,1)
struct Inventar
{
char Name[30];
double Cost;
char Type[30];
};
#pragma pack(pop)
 
#define MAX_RECORDS 20
int main()
{
  Inventar db_records[MAX_RECORDS]={0};
  FILE* db_file=fopen("base.txt","rb");
  if(db_file)
  {
     int record_no=0;
     while(record_no<MAX_RECORDS && fread(&db_records[record_no],sizeof(Inventar),1,db_file))
     {
        printf("%d %s %6.2f %s\n",record_no,db_records[record_no].Name,db_records[record_no].Cost,db_records[record_no].Type);
        record_no++;
     }     
     fclose(db_file);
     db_file=0;
  }
   
  srand( (unsigned)time( NULL ) );
  int rand_rec = 0;
  for(int i=0;i<MAX_RECORDS;i++)
   rand_rec = (double)rand() / (RAND_MAX + 1) * (MAX_RECORDS);
  printf("Change record %d\n",rand_rec);
  
  strncpy(db_records[rand_rec].Name,"Test Name",sizeof(db_records[rand_rec].Name)-1);
  db_records[rand_rec].Cost = 100.2;
  strncpy(db_records[rand_rec].Type,"Test Type",sizeof(db_records[rand_rec].Type)-1);
  
  db_file=fopen("base.txt","wb");
  if(db_file)
  {
     for(int rec_no=0;rec_no<MAX_RECORDS;rec_no++)
     {
        if(!fwrite(&db_records[rec_no],sizeof(Inventar),1,db_file))
        {
           printf("Database file write error\n");
           break;
        }
     }
     fclose(db_file);
  }
  else
  {
     printf("Database file open error\n");
  }
}
Примерно так решается похожая задача с хранением в бинарном файле.

Добавлено через 15 минут
UP.

И еще я как-то пропустил момент, когда массив стал односвязным списком.
0
5 / 6 / 4
Регистрация: 18.11.2009
Сообщений: 661
16.06.2014, 09:29  [ТС] 19
так мне и нужно читать из текстового файла а не из бинарного. Приехали. Так эта вся техника с read для текстового не годится? Я естественно за это время выделил память для кучи и ошибка исчезла. Но при чтении была фигня. В 1-и поле структуры вместо w.Marka="RS728 "
получалось почему-то w.Marka="RS728 INTEL Celeron G530 4096 500 шF" и т.п.
Надо было видимо не через read а через поток
C++ (Qt)
1
2
3
4
QDataStream operator <<(QDataStream &in, const TComp &w) 
{ in >>w.Marka; in >> w.Pr; in >> w.Vop; in >> w.Vgd; in >> w.Price; return in; 
}
или тупо в цикле чтения каждой записи писать 5 операторов потокового чтения
0
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
16.06.2014, 14:28 20
Цитата Сообщение от eugrita Посмотреть сообщение
так мне и нужно читать из текстового файла а не из бинарного. Приехали. Так эта вся техника с read для текстового не годится?
Годится любая техника, при правильном применении. ASCII строки без разницы как писать, числа нужно предварительно конвертировать в строку.

Тогда нужно делать сериализацию структуры в поток.

C++
1
2
3
QDataStream operator <<(QDataStream &in, const TComp &w) 
{ in >>w.Marka; in >> w.Pr; in >> w.Vop; in >> w.Vgd; in >> w.Price; return in; 
}
Да, примерно так. Только нужно учесть что оно читает до пробела, к примеру "INTEL Celeron" будет читаться как две строки. Если не устраивает - нужно писать в файл с разделителями.

UP, сорри, это я про стандартный поток, кутовыми не пользуюсь, возможно к ним это не относится.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
16.06.2014, 14:28

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

Запись и чтение структуры в/из файла
Столкнулся с очередной проблемой. Есть несколько участков кода: Структура &quot;Абонент&quot;: struct...

Запись и чтение структуры с файла
Привет всем.Столкнулся с проблема записи структуры в файл и чтения ее из файла.Вот сама структура:...

Запись/чтение структуры в файл
есть структура: struct OBYEKT { std::string neym; int nomer; }; std::vector &lt;OBYEKT&gt;...

Запись структуры и её чтение из файла
пробовал разными способами, ничего не работает, не записывает и не считывает...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.