Форум программистов, компьютерный форум CyberForum.ru

Подскажите как записать массив структур в файл - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.79
QWAN
56 / 55 / 1
Регистрация: 02.09.2008
Сообщений: 181
07.02.2011, 17:39     Подскажите как записать массив структур в файл #1
Написал програмку, которая копирует желаемый прямоугольник(массив символов с атрибутами) в указанное место на экарн.
Программа работает так как задуманно.
В функции ReadRectSurface я использую несколько раз оператор new и ниразу delite. Подскажите пожайлуста в каком месте я должен вставить операторы delite и почему именно в том месте.
Подскажите как записать массив структур FRAGMENT в файл и затем прочитать его из файла.

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#include <windows.h>
#include <iostream>
using namespace std;
 
// максимальный LIMIT 13300
const int LIMIT = 20;    // копируемый прямоугольник, ширина * высота = LIMIT
 
//стуктура предназначена для хранения части поверхности или всей поверхности если ее размер не превышает LIMIT
typedef struct _FRAGMENT {
    int counter;                // счетчик, показывает сколько фрагментов находится после текущего
    COORD dwBufferSize;         // размер фрагмента
    CHAR_INFO *lpBuffer;        // буфер данных, здесь хранятся символы
} FRAGMENT, *PFRAGMENT;
 
// ReadRectSurface считывает прямоугольник из указанной поверхности и заносит его в масив фрагментов
// если ширина копируемого прямоугольника превысить LIMIT, выдаст ошибку
// 1) HANDLE поверхности
// 2) указатель на масив FRAGMENT
// 3) копируемый прямоугольник
//-------------------------------------------------------------------------------------
FRAGMENT* ReadRectSurface(HANDLE hSurface, SMALL_RECT lpReadRegion, FRAGMENT *pBuffer)
{    
    //вычисляем размер копируемого прямоугольника
    COORD RegionSize;
    RegionSize.X = lpReadRegion.Right - lpReadRegion.Left + 1;    //ширина прямоуголника
    RegionSize.Y = lpReadRegion.Bottom - lpReadRegion.Top + 1;    //длина прямоугольника
 
    if(RegionSize.X > LIMIT)
    {
        {MessageBox(NULL, "ERROR RegionSize.X > LIMIT", "Console Error", MB_OK); return 0;}
        return 0;
    }
    
    else if (RegionSize.X * RegionSize.Y < LIMIT)//то в массив заносим только одит фрагмент
    {
        pBuffer = new FRAGMENT[1];
        pBuffer->counter = 1;
        pBuffer->dwBufferSize.X = RegionSize.X;
        pBuffer->dwBufferSize.Y = RegionSize.Y;        
        pBuffer->lpBuffer = new CHAR_INFO [RegionSize.X * RegionSize.Y];
        // Верхняя левая ячейка назначения временного буфера равна строка 0, колонка 0.
        COORD coordBufCoord = {0,0};
        // Скопируем блок из поверхности во временный буфер.
        if(!ReadConsoleOutput(
                                hSurface,            // HANDLE поверхности из которой читаем
                                pBuffer->lpBuffer,    // буфер, в который копируем
                                RegionSize,           // размер копируемого прямоугольника 
                                coordBufCoord,      // верхняя левая ячейка назначения
                                &lpReadRegion))     // источниковый прямоугольник экранного буфера        
            {MessageBox(NULL, "ERROR in ReadConsoleOutput", "Console Error", MB_OK); return 0;}                        
        return pBuffer;
    }
 
    else
    {
        pBuffer = new FRAGMENT[RegionSize.Y];        
        for(int i = 0; i < RegionSize.Y; i++)
        {
            pBuffer[i].counter = RegionSize.Y - i;
            pBuffer[i].dwBufferSize.X = RegionSize.X;
            pBuffer[i].dwBufferSize.Y = 1;            
            pBuffer[i].lpBuffer = new CHAR_INFO[RegionSize.X];
 
            // Верхняя левая ячейка назначения временного буфера равна строка 0, колонка 0.
            COORD coordBufCoord = {0,0};
 
            // Скопируем блок из поверхности во временный буфер.
            // Установим прямоугольник источника.
            SMALL_RECT srctReadRect;
            srctReadRect.Top = lpReadRegion.Top + i;    // 
            srctReadRect.Left = lpReadRegion.Left;
            srctReadRect.Bottom = lpReadRegion.Top + i; // 
            srctReadRect.Right = lpReadRegion.Right;            
            
            if(!ReadConsoleOutput(
                                    hSurface,                    // HANDLE поверхности из которой читаем
                                    pBuffer[i].lpBuffer,        // буфер, в который копируем
                                    pBuffer[i].dwBufferSize,       // количество колонок/строк
                                    coordBufCoord,              // верхняя левая ячейка назначения
                                    &srctReadRect))             // источниковый прямоугольник экранного буфера            
                {MessageBox(NULL, "ERROR in ReadConsoleOutput", "Console Error", MB_OK); return 0;}
        }
        return pBuffer;
    }
}
//-------------------------------------------------------------------------------------------------------------
bool WriteRectSurface(HANDLE hSurface, COORD position, FRAGMENT *pBuffer)
{
    // Верхняя левая ячейка назначения временного буфера равна строка 0, колонка 0.
    COORD coordBufCoord = {0,0};
    if(!pBuffer)
        {MessageBox(NULL, "ERROR in WriteRectSurface, pBuffer = NULL", "Console Error", MB_OK); return false;}    
    else if(pBuffer->counter == 0)
        {MessageBox(NULL, "ERROR in WriteRectSurface, pBuffer->counter == 0", "Console Error", MB_OK); return false;}
    else if(pBuffer->counter == 1)
    {        
        // Установим прямоугольник назначения.
        SMALL_RECT srctWriteRect;
        srctWriteRect.Top = position.Y;    // верхний левый: строчка 0, колонка 0
        srctWriteRect.Left = position.X;
        srctWriteRect.Bottom = position.Y + pBuffer->dwBufferSize.Y - 1; // нижний правый: строчка 1, колонка 79
        srctWriteRect.Right = position.X + pBuffer->dwBufferSize.X - 1;
 
        if(!WriteConsoleOutput(
                                hSurface,     // экранный буфер, в который будем записывать
                                pBuffer->lpBuffer,            // буфер, из которого копируем
                                pBuffer->dwBufferSize,         // размер колонки/строки chiBuffer
                                coordBufCoord,        // верхняя левая ячейка источника в chiBuffer
                                &srctWriteRect))      // прямоугольник назначения экранного буфера
            {MessageBox(NULL, "ERROR in WriteConsoleOutput", "Console Error", MB_OK); return false;}
        return true;
    }
    else 
    {
        for(int i = 0; i < pBuffer->counter; i++)
        {
            // Установим прямоугольник назначения.
            SMALL_RECT srctWriteRect;
            srctWriteRect.Top = position.Y + i;    
            srctWriteRect.Left = position.X;
            srctWriteRect.Bottom = position.Y + i; 
            srctWriteRect.Right = position.X + pBuffer->dwBufferSize.X - 1;
 
            if(!WriteConsoleOutput(
                                hSurface,     // экранный буфер, в который будем записывать
                                pBuffer[i].lpBuffer,            // буфер, из которого копируем
                                pBuffer->dwBufferSize,         // размер колонки/строки chiBuffer
                                coordBufCoord,        // верхняя левая ячейка источника в chiBuffer
                                &srctWriteRect))      // прямоугольник назначения экранного буфера
            {MessageBox(NULL, "ERROR in WriteConsoleOutput", "Console Error", MB_OK); return false;}            
        }
        return true;
    }
}
//---------------------------------------------------------------------------------------------------------------
int main()
{        
    for(int i = 0; i< 10;i++) //чет-то заполняем экрань
    cout<<i<<"ABCDEFGHIKLMNOPQRSTUVWXYZ"<<endl;
 
    //Меня интересует, как записать массив структур FRAGMENT в файл и затем прочитать из файла
    FRAGMENT *mf = 0;    //указатель на массив структур FRAGMENT
 
    HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
    SMALL_RECT ReadRegion1 = {0,0,9,9};    
 
    mf = ReadRectSurface(hStdout,ReadRegion1, mf);
    if(!mf)
        cout<<"Error"<<endl;
    if(mf->counter == 0)
    {
        cout<<"Create single fragment"<<endl;
        cout<<"mf->dwBufferSize.X - "<<mf->dwBufferSize.X<<endl;
        cout<<"mf->dwBufferSize.Y - "<<mf->dwBufferSize.Y<<endl;
    }
    else
    {
        cout<<"Create "<<mf->counter<<" fragments"<<endl;
        for(int i = 0; i< mf->counter; i++)
            cout<<"mf["<<i<<"].counter"<<mf[i].counter<<endl;        
    }
 
    //указываем позицию куда вывести скопированый прямоугольник (точка вставки, верний левй угол) 
    COORD poit = {40,0};
    if(!WriteRectSurface(hStdout,poit,mf))
        cout<<"Error in WriteRectSurface"<<endl;    
 
    getchar();
    return 0;
}
Добавлено через 10 минут
Если я правильно понимаю, масиив который я создал, я могу использовать еще несколько раз для вставки, поэтому его нужно удалять, когда он мне уже точно не потребуется, ну например перед выходом из программы.

Добавлено через 27 минут
Может как-то так записывать мою структуру в файл?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//запись структуры в бинарный файл
    char fileName[80];
    cout<<"Please enter the file name: ";
    cin>> fileName;
    ofstream fout(fileName, ios::binary);
    if(!fout)
    {
        cout<<"Unable to open " << fileName<<" for writing. \n";
        return (1);
    }
    for(int i=0; i<mf->counter; i++)
    {
        fout.write((char*)mf[i].counter, sizeof mf[i].counter);
        fout.write((char*)&mf[i].dwBufferSize , sizeof mf[i].dwBufferSize);
        fout.write((char*)mf[i].lpBuffer, mf[i].dwBufferSize.X * mf[i].dwBufferSize.Y * sizeof mf[i].lpBuffer);
    }
    fout.close();
Добавлено через 34 минуты
И как-то так считывать:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//чтение структуры из бинарного файла
    ifstream fin(fileName, ios::binary);
    if(!fin)
    {
        cout<<"Unable to open"<<fileName<<" for reading.\n";
        return (1);
    }
    FRAGMENT *new_mf = 0;
    fin.read((char*)new_mf->counter, sizeof new_mf->counter);
    for(int i = 0; i<new_mf->counter; i++)
    {
        fin.read((char*)new_mf[i].counter, sizeof new_mf[i].counter);
        fin.read((char*)&new_mf[i].dwBufferSize, sizeof new_mf[i].dwBufferSize);
        fin.read((char*)new_mf[i].lpBuffer, mf[i].dwBufferSize.X * mf[i].dwBufferSize.Y * sizeof new_mf[i].lpBuffer);
    }
    fin.close();
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
accept
4837 / 3236 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
08.02.2011, 09:28     Подскажите как записать массив структур в файл #2
надо в main() после записи вызвать функцию освобождения
для этого нужно знать, сколько элементов в выделенном массиве
всё выделенное должно быть освобождено
у тебя там вроде есть инфа о количестве элементов массива, но она неправильно сделана, так как каждый узел хранит ненужное значение, можно было сделать количество элементов снаружи

C++
1
2
3
4
struct Fragment {
    Coord dwBufferSize;         // размер фрагмента
    Char_info *lpBuffer;        // буфер данных, здесь хранятся символы
};
C++
1
2
3
4
struct Box {
    Fragment *ptr;
    int n;
};
Цитата Сообщение от QWAN
Может как-то так записывать мою структуру в файл?
твои структуры содержат указатели, поэтому данные из них не будут сохраняться (только адрес, хранящийся в указателе)
даже если у тебя структуры были бы без указателей, способ прямой записи/чтения был бы гарантирован только в пределах одного компа
QWAN
56 / 55 / 1
Регистрация: 02.09.2008
Сообщений: 181
08.02.2011, 10:51  [ТС]     Подскажите как записать массив структур в файл #3
accept, скажи пожайлуста в какую сторону хотябы искать как записать то что я копирую в массив.

Цитата Сообщение от accept Посмотреть сообщение
даже если у тебя структуры были бы без указателей, способ прямой записи/чтения был бы гарантирован только в пределах одного компа
Ты хотеш сказать что на разных компъютерах может отличатся размер моей структуры?

Добавлено через 38 минут

Добавлено через 23 секунды
Скорее всего для того чтобы сохранить указанный прямоугольник мне нужно создать дополнительный экранный буфер консоли по размерам копируемого прямоугольника, скопировать туда мой прямоугольник. Идалее вызвать функцию типа ReadFile.
Но судя по тому как она описывается http://www.vsokovikov.narod.ru/New_M...n_readfile.htm
Я сохраню в файл только символы без цвета и фона.
accept
4837 / 3236 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
09.02.2011, 08:37     Подскажите как записать массив структур в файл #4
Цитата Сообщение от QWAN
Ты хотеш сказать что на разных компъютерах может отличатся размер моей структуры?
может много чего различаться: выравнивание внутри структур, направление байтов в переменных, размеры базовых типов
если ты сохраняешь файл на одном компьютере, то на другом компе его нельзя загружать, может исказиться
fread(), fwrite() со структурами можно применять в пределах одного компа

нужно сохранять структуру по частям и загружать по частям
C++
1
2
3
4
struct Fragment {
    Coord dwBufferSize;         // размер фрагмента
    Char_info *lpBuffer;        // буфер данных, здесь хранятся символы
};
запиши это в виде текста в файл

1ая запись
первое значение записываешь в виде числа
дальше через разделитель записываешь содержимое буфера
дальше конец записи

2ая запись
первое значение записываешь в виде числа
дальше через разделитель записываешь содержимое буфера
дальше конец записи

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

Код
3
12 abcdeabcdeab;
3 abc;
8 abcdeabc;
Yandex
Объявления
09.02.2011, 08:37     Подскажите как записать массив структур в файл
Ответ Создать тему
Опции темы

Текущее время: 18:19. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru