Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
KiberDollar
0 / 0 / 1
Регистрация: 22.06.2011
Сообщений: 24
#1

Чтение и запись в файл динамического массива классов - C++

01.04.2016, 23:24. Просмотров 537. Ответов 12
Метки нет (Все метки)

Здравствуйте!

Столкнулся с проблемой во время написания программы, которая бы заносила определённые данные в файл, а потом считывала их оттуда. Считывание при этом должно вестись и при перезапуске программы.
Проблема состоит в том, что я не могу нормально записать данные в файл и соответственно их потом считать. Уже пробовал записать данные разными способами, но максимальных результатов достиг, когда смог всё записать, но не смог считать. Видел много тем и много методов реализации этой задачи, но я не могу нормально интегрировать их в свою программу.

Вот последняя версия кода, которую я смог родить:
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <iostream>
#include <fstream>
//#include <cstring>
using namespace std;
class Store
{
        public:
                char Name[20];
                short int Size;
                int Height;
                char Color[10];
                char ModNum[10];
        /*friend fstream& operator << (fstream& stream, Store& Shop)
        {
                stream<<Shop.Name;
                stream<<Shop.Size;
                stream<<Shop.Height;
                stream<<Shop.Color;
                stream<<Shop.ModNum;
                return stream;
        }
        friend fstream& operator >> (fstream& stream, Store& Shop)
        {
                stream>>Shop.Name;
                stream>>Shop.Size;
                stream>>Shop.Height;
                stream>>Shop.Color;
                stream>>Shop.ModNum;
                return stream;
        }               */
};
 
int main ()
{
        int i, N;
        string FileName;
        fstream FPin, FPout;
        //Store Cloth;
        char Choice;
        cout<<"Vvedite name faila\n";
        cin>>FileName;
        FPout.open(FileName.c_str(), ios_base::in);
        if (FPout==NULL)
        {
                FPout.close();
                cout<<"Faila s takim imenem net. Hotite sozdat fail? Y/N \n";
                cin>>Choice;
                if (Choice=='N') return 0;
                else
                {
                        FPin.open(FileName.c_str(), ios::out|ios::binary);
                        cout<<"\nVvedite kolichestvo zapisei:";
                        cin>>N;
                        Store *Cloth=new Store[N];
                        cout<<"\n Vvedite dannie tovara:\n";
                        cout<<"\nNaimenovanie\tRazmer\tRost\tCvet\tNomer modeli\n";
                        for (i=0; i<N; i++)
                        {
                                cin>>Cloth[i].Name>>Cloth[i].Size>>Cloth[i].Height>>Cloth[i].Color>>Cloth[i].ModNum;
                                //FPin<<Cloth[i].Name<<endl<<Cloth[i].Size<<endl<<Cloth[i].Height<<endl<<Cloth[i].Color<<endl<<Cloth[i].ModNum<<endl;
                        }
                        FPin.write(reinterpret_cast<char*>(Cloth),sizeof(Store)*N);
                        FPin.close();
                        delete []Cloth;
                }
        }
        FPout.open(FileName.c_str(), ios::in|ios::binary);
        Store *Cloth=new Store[2];
        FPin.read((char*)Cloth,sizeof(Store)*2);
        cout<<"\nNaimenovanie\tRazmer\tRost\tCvet\tNomer modeli\n";
        for (i=0; i<2; i++)
        //while (!FPout.eof())
        {
               /* FPout>>Cloth[i].Name; cout<<Cloth.Name<<"\t";
                FPout>>Cloth.Size; cout<<Cloth.Size<<"\t";
                FPout>>Cloth.Height; cout<<Cloth.Height<<"\t";
                FPout>>Cloth.Color; cout<<Cloth.Color<<"\t";
                FPout>>Cloth.ModNum; cout<<Cloth.ModNum<<endl;    */
                cout<<Cloth[i].Name<<"\t"<<Cloth[i].Size<<"\t"<<Cloth[i].Height<<"\t"<<Cloth[i].Color<<"\t"<<Cloth[i].ModNum<<endl;
        }
        FPout.close();
        delete []Cloth;
    system("PAUSE");
    return 0;
}
При выводе я хочу реализовать динамическое считывание, так как в файле неопределённое количество данных, но пока что при выводе я обозначаю 2 экземпляра класса, так тестировал программу только двумя записями.

Прошу подсказать что я делаю не так или объяснить на пальцах каким методом было бы лучше использовать. Я не давно начал изучать С++ и поэтому некоторые методы, которые я видел остались для меня не понятными.
Спасибо.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.04.2016, 23:24
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Чтение и запись в файл динамического массива классов (C++):

Запись и чтение объектов разных классов в один файл
Здравствуйте. Изучаю С++ по Лафоре. Дошёл до места, где объясняется, как...

Запись динамического массива в файл (не правильно выводит данные)
Выделяю память под массив, заполняю его числами. int *mem_arr; int i;...

Запись массива в файл/чтение из файла
1) ввести с клавиатуры матрицу ( размером 4*4 или 5*5) и записать в файл; 2)...

Запись массива в файл и его чтение
Помогите, пожалуйста: надо записать в файл массив из, например, 10 элементов,...

Запись массива в файл и чтение из файла
Программа массив генерирует все ок, а вот с записью массива и чтением его - у...

Запись структурного массива в файл и чтение из него
Есть структурный массив: struct { char NAME,SKILLNAME; int...

12
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
7009 / 3302 / 451
Регистрация: 04.12.2011
Сообщений: 9,141
Записей в блоге: 5
01.04.2016, 23:59 #2
KiberDollar, имеет смысл перегружать операторы ввода вывода с базовыми классами ostream и istream. При этом можно вывести с-строку в поток, но загрузить её из потока оператором >> нельзя. Он не перегружен для типа char *. Зато можно использовать метод getline:
C++
1
2
3
4
5
6
7
8
9
10
//friend не нужен так как это метод экземпляра
istream& operator >> (istream &is)
        {
                getline(is, Name);
                stream>>Shop.Size;
                stream>>Shop.Height;
                stream>>Shop.Color;
                getline(is, ModNum);                
                return is;
        }
1
KiberDollar
0 / 0 / 1
Регистрация: 22.06.2011
Сообщений: 24
02.04.2016, 16:53  [ТС] #3
А можно обойтись без getline? Просто дальше эти данные надо будет обрабатывать и делать по ним выборку.
0
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
7009 / 3302 / 451
Регистрация: 04.12.2011
Сообщений: 9,141
Записей в блоге: 5
02.04.2016, 17:00 #4
Цитата Сообщение от KiberDollar Посмотреть сообщение
А можно обойтись без getline? Просто дальше эти данные надо будет обрабатывать и делать по ним выборку.
А как одно с другим связано? Вы можете читать хоть посимвольно, - как напишете, так и будет.
1
KiberDollar
0 / 0 / 1
Регистрация: 22.06.2011
Сообщений: 24
02.04.2016, 17:40  [ТС] #5
Не могли бы вы подсказать, как можно связать
C++
1
2
3
4
5
6
7
8
        for (i=0; i<2; i++)
        {
                FPout>>Cloth[i].Name;     cout<<Cloth.Name<<"\t";
                FPout>>Cloth[i].Size;     cout<<Cloth.Size<<"\t";
                FPout>>Cloth[i].Height;   cout<<Cloth.Height<<"\t";
                FPout>>Cloth[i].Color;    cout<<Cloth.Color<<"\t";
                FPout>>Cloth[i].ModNum;   cout<<Cloth.ModNum<<endl;
        }
И

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Store
{
        public:
                char Name[20];
                short int Size;
                int Height;
                char Color[10];
                char ModNum[10];
        istream& operator >> (istream &stream)
        {
                getline(stream,Name);
                getline(stream,Size);
                getline(stream,Height);
                getline(stream,Color);
                getline(stream,ModNum);
                return stream;
        }
};
Или мы можем как-то использовать функцию read у файловой переменной?
0
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
7009 / 3302 / 451
Регистрация: 04.12.2011
Сообщений: 9,141
Записей в блоге: 5
02.04.2016, 19:32 #6
Цитата Сообщение от KiberDollar Посмотреть сообщение
getline(stream,Size);
Не уж-то это можно скомпилировать?
Вот с использование строк std::string. Оно ровнее и логичнее:
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
struct Enimal
{
string ownerName;
string enimalName;
int enimalAge;
 
Enimal()
:ownerName(""),enimalName(""),enimalAge(0){}
Enimal(string ownerName_,string enimalName_, int enimalAge_)
:ownerName(ownerName_),enimalName(enimalName_),enimalAge(enimalAge_)
{}
Enimal(const Enimal &rhs)
:ownerName(rhs.ownerName),enimalName(rhs.enimalName),enimalAge(rhs.enimalAge)
{}
 
friend
ostream& operator<<(ostream& os, Enimal &enimal)
{
os<<enimal.ownerName<<endl;
os<<enimal.enimalName<<endl;
os<<enimal.enimalAge<<endl;
return os;
}
 
friend
istream &operator>>(istream& is,  Enimal &enimal)
{
is>>enimal.ownerName;
is>>enimal.enimalName;
is>>enimal.enimalAge;
return is;
}
void print()
{
cout<<ownerName<<endl;
cout<<enimalName<<endl;
cout<<enimalAge<<endl;
}
};
 
int main(int argc, char* argv[])
{
Enimal initArray[]=
{
    Enimal("Tom", "Rex", 4),
    Enimal("Tim", "Matilda", 1),
    Enimal("Mike", "Harry", 3),
    Enimal("Vasya", "Polly", 2),
    Enimal("Vasya", "Dolly", 1),
    Enimal("Vasya", "Lariska", 1),
    Enimal("Vasya", "Sharick", 18),
    Enimal("Vasya", "Kesha", 1)
};
 
size_t size_initArray=sizeof(initArray)/sizeof(initArray[0]);
const char *fname="enimals";
ofstream os(fname, ios::out); 
for(size_t i=0; i<size_initArray; ++i) os<<initArray[i];
os.close();
 
vector<Enimal> enimals;
ifstream is(fname, ios::in);
Enimal enimal;
if(!is){
cout<<"Fail to file open!";
}else
while(is>>enimal)
{
enimals.push_back(enimal);
}
cout<<"Following objects are loaded from file ""<<fname<<"" :"<<endl;
for(vector<Enimal>::iterator it = enimals.begin(); it!=enimals.end(); it++)
(*it).print();
 
cout<<endl;
system("pause");
return 0;
}
1
KiberDollar
0 / 0 / 1
Регистрация: 22.06.2011
Сообщений: 24
02.04.2016, 20:17  [ТС] #7
Уф =)
Спасибо, конечно, но вы пользуетесь слишком сложными для восприятия конструкциями. Я уже видел некоторые примеры, как запись в файл производилась с помощью вектора, но пока особо в этом не разбирался, так как, боюсь, что не смогу объяснить преподавателю зачем я его использовал =)
Но всё равно спасибо за потраченное время =)
0
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
7009 / 3302 / 451
Регистрация: 04.12.2011
Сообщений: 9,141
Записей в блоге: 5
02.04.2016, 21:18 #8
Цитата Сообщение от KiberDollar Посмотреть сообщение
запись в файл производилась с помощью вектора,
Тут с помощью вектора оно читается. Если не нравится вектор, - читайте в массив или в n-e количество переменных. Вектор для чтения из файла удобен тем, что Вам не нужно знать заранее сколько объектов там лежит. Но, как знаете.
1
KiberDollar
0 / 0 / 1
Регистрация: 22.06.2011
Сообщений: 24
03.04.2016, 01:33  [ТС] #9
Спасибо!!! У меня всё получилось, но теперь у меня встал ещё один вопрос. Теперь у тебя всё нормально записывается и считывается из файла, но осталась нерешённая проблема с динамическим созданием массива при чтении из файла.

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <iostream>
#include <fstream>
using namespace std;
class Store
{
        public:
                char Name[20];
                short int Size;
                int Height;
                char Color[10];
                char ModNum[10];
};
istream& operator >> (istream &stream, Store& Shop)
        {
                stream>>Shop.Name;
                stream>>Shop.Size;
                stream>>Shop.Height;
                stream>>Shop.Color;
                stream>>Shop.ModNum;
                return stream;
        }
ostream& operator << (ostream& stream, Store& Shop)
        {
                stream<<Shop.Name<<endl;
                stream<<Shop.Size<<endl;
                stream<<Shop.Height<<endl;
                stream<<Shop.Color<<endl;
                stream<<Shop.ModNum;
                return stream;
        }
 
int main ()
{
        int i, N;
        string FileName;
        fstream FPin, FPout;
        char Choice;
        cout<<"Vvedite name faila\n";
        cin>>FileName;
        FPout.open(FileName.c_str(), ios_base::in);
        if (FPout==NULL)
        {
                FPout.close();
                cout<<"Faila s takim imenem net. Hotite sozdat fail? Y/N \n";
                cin>>Choice;
                if (Choice=='N') return 0;
                else
                {
                        FPin.open(FileName.c_str(), ios::out);
                        cout<<"\nVvedite kolichestvo zapisei:";
                        cin>>N;
                        Store *Cloth=new Store[N];
                        cout<<"\n Vvedite dannie tovara:\n";
                        cout<<"\nNaimenovanie\tRazmer\tRost\tCvet\tNomer modeli\n";
                        for (i=0; i<N; i++)
                        {
                                cin>>Cloth[i].Name>>Cloth[i].Size>>Cloth[i].Height>>Cloth[i].Color>>Cloth[i].ModNum;
                                FPin<<Cloth[i];
                        }
                        FPin.close();
                        delete []Cloth;
                        return 0;
                }
        }
        //Store *Cloth=new Store[2];
        Store Cloth[2];
        cout<<"\nNaimenovanie\tRazmer\tRost\tCvet\tNomer modeli\n";
        i=0;
        while (!FPout.eof())
        {
                FPout>>Cloth[i];
                cout<<Cloth[i].Name<<"\t"<<Cloth[i].Size<<"\t"<<Cloth[i].Height<<"\t"<<Cloth[i].Color<<"\t"<<Cloth[i].ModNum<<endl;
                i++;
        }
        FPout.close();
        delete []Cloth;
    system("PAUSE");
    return 0;
}
Пока что я создаю 2 экземпляра (для теста). Не могли бы вы подсказать как можно реализовать динамический массив для неопределённого количества экземпляров?
0
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
7009 / 3302 / 451
Регистрация: 04.12.2011
Сообщений: 9,141
Записей в блоге: 5
03.04.2016, 09:42 #10
Лучший ответ Сообщение было отмечено KiberDollar как решение

Решение

Цитата Сообщение от KiberDollar Посмотреть сообщение
но осталась нерешённая проблема с динамическим созданием массива при чтении из файла.
Если вектор всё же не подходит ,то остаётся узнать количество экземпляров, которое можно сложить из записи в файле. Размер файла состоит из размеров n записей и + из размеров n групп символов форматирования. Остаётся найти n и создать динамический массив.
Костыль:
Можно создать любой массив - больше предполагаемого, а при считывании считать сколько раз считалось.
1
KiberDollar
0 / 0 / 1
Регистрация: 22.06.2011
Сообщений: 24
03.04.2016, 14:54  [ТС] #11
А если я считаю всё в вектор, то я смогу потом, например, сделать выборку этих данных по значению в определённом поле?

Добавлено через 2 часа 44 минуты
Спасибо за помощь!! Всё работает как надо!

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <iostream>
#include <fstream>
using namespace std;
class Store
{
        public:
                char Name[20];
                short int Size;
                int Height;
                char Color[10];
                char ModNum[10];
};
istream& operator >> (istream &stream, Store& Shop)
        {
                stream>>Shop.Name;
                stream>>Shop.Size;
                stream>>Shop.Height;
                stream>>Shop.Color;
                stream>>Shop.ModNum;
                return stream;
        }
ostream& operator << (ostream& stream, Store& Shop)
        {
                stream<<Shop.Name<<"\t";
                stream<<Shop.Size<<"\t";
                stream<<Shop.Height<<"\t";
                stream<<Shop.Color<<"\t";
                stream<<Shop.ModNum<<endl;;
                return stream;
        }
 
int main ()
{
        int i, N;
        string FileName;
        fstream FPin, FPout;
        char Choice;
        cout<<"Vvedite name faila\n";
        cin>>FileName;
        FPout.open(FileName.c_str(), ios_base::in | ios_base::binary);
        if (FPout==NULL)
        {
                FPout.close();
                cout<<"Faila s takim imenem net. Hotite sozdat fail? Y/N \n";
                cin>>Choice;
                if (Choice=='N') return 0;
                else
                {
                        FPin.open(FileName.c_str(), ios::out);
                        cout<<"\nVvedite kolichestvo zapisei: ";
                        cin>>N;
                        Store *Cloth=new Store[N];
                        cout<<"\n Vvedite dannie tovara:\n";
                        cout<<"\nNaimenovanie\tRazmer\tRost\tCvet\tNomer modeli\n";
                        for (i=0; i<N; i++)
                        {
                                cin>>Cloth[i].Name>>Cloth[i].Size>>Cloth[i].Height>>Cloth[i].Color>>Cloth[i].ModNum;
                                FPin<<Cloth[i];
                        }
                        FPin.close();
                        delete []Cloth;
                        return 0;
                }
        }
        FPout.seekg(ios_base::end);
        N=FPout.tellg()*5;
        FPout.seekg(ios_base::beg-1);
        Store *Cloth=new Store[N];
        cout<<"\nNaimenovanie\tRazmer\tRost\tCvet\tNomer modeli\n";
        N=0;
        while (FPout>>Cloth[N])
        {
                cout<<Cloth[N].Name<<"\t"<<Cloth[N].Size<<"\t"<<Cloth[N].Height<<"\t"<<Cloth[N].Color<<"\t"<<Cloth[N].ModNum<<endl;
                N++;
        }
        FPout.close();
        cout<<"\nResultati viborki: \n";
        for (i=0; i<N; i++)
        {
                if (stricmp(Cloth[i].Name,"Kostum")==0 && Cloth[i].Size>=52)
                        cout<<Cloth[i].Name<<"\t"<<Cloth[i].Size<<"\t"<<Cloth[i].Height<<"\t"<<Cloth[i].Color<<"\t"<<Cloth[i].ModNum<<endl;
        }
        //delete []Cloth;
    system("PAUSE");
    return 0;
}
Единственное, что не понятно, почему на строку delete []Cloth; в конце программы компилятор ругается. Но если её закомментировать, то всё в порядке =) Может быть код в целом не совсем удачный, но работает =) Спасибо за потраченное время. Тема исчерпана.
0
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
7009 / 3302 / 451
Регистрация: 04.12.2011
Сообщений: 9,141
Записей в блоге: 5
03.04.2016, 16:39 #12
Лучший ответ Сообщение было отмечено KiberDollar как решение

Решение

Цитата Сообщение от KiberDollar Посмотреть сообщение
Единственное, что не понятно, почему на строку delete []Cloth;
объявление Cloth не в той области видимости. Память уже утекла и не достать её. Правда, сама main должна освободить все ресурсы. Но для порядку надо бы где-то вначале main объявить:
C++
1
Store *Cloth;
а там где выделяете, - просто:
C++
1
Cloth=new Store[N];
тогда вконце:
C++
1
delete [] Cloth;
должно сработать.
1
KiberDollar
0 / 0 / 1
Регистрация: 22.06.2011
Сообщений: 24
03.04.2016, 17:14  [ТС] #13
Да =) Так и есть. Теперь всё совершеннее =)
0
03.04.2016, 17:14
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.04.2016, 17:14
Привет! Вот еще темы с решениями:

Запись/чтение массива структур в бинарный файл
#include &lt;iostream&gt; #include &lt;fstream&gt; using namespace std; struct test ...

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

Запись в файл и последующее чтение массива типа char
Добрый вечер! Я должен сделать элементарную программу: в текстовом файле...

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


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

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

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