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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.78
QWAN
58 / 57 / 1
Регистрация: 02.09.2008
Сообщений: 181
#1

Дайте ссылку или пример на интересующий меня вопрос. - C++

10.02.2011, 13:55. Просмотров 1192. Ответов 20
Метки нет (Все метки)

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
//Мне нужно сохранить информацию в массив структур FRAGMENT.
//Сруктура выглит так:
struct  FRAGMENT {
    int counter;        // счетчик, показывает номер фрагмента
    int Size_X;         // размер фрагмента по Х
    int Size_Y;        // размер фрагмента по Y
    char *lpBuffer;        // здесь хранятся символы
};
 
//Я обьявляю указатель на этот массив FRAGMENT.
FRAGMENT *mf;
 
//Дальше есть функция которая должна занести информацию в  мой массив структур.
//я описал эту функцию примерно так:
FRAGMENT *ReadBuffer(FRAGMENT *Buffer)
{
    int x;//как-то считается
    Buffer = new FRAGMENT[x];
    for(int i=0; i<x; i++)
    {
        Buffer[i].counter = i;
        //
        //
        Buffer[i].lpBuffer = new char[number];//number - какоето число
        //дальше вызывается функция которая занесла информацию в Buffer[i].lpBuffer
    }
    return Buffer;    
} 
 
//Вот так использовал функцию
mf = ReadBuffer(mf);
 
//Я уже понял что я что-то не так делаю, подскажите (просто на словах или ссылку на пример) как правильно организовать программу. Где поставить delete и почему.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
alex_x_x
бжни
2447 / 1652 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
10.02.2011, 14:06     Дайте ссылку или пример на интересующий меня вопрос. #2
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void ReadBuffer(FRAGMENT*& Buffer, int& x)
{
    // x как-то считается
    Buffer = new FRAGMENT[x];
    for(int i=0; i<x; i++)
    {
        Buffer[i].counter = i;
        //
        //
        Buffer[i].lpBuffer = new char[number];//number - какоето число
        //дальше вызывается функция которая занесла информацию в Buffer[i].lpBuffer
    }
} 
 
void ReleaseBuffer(FRAGMENT* Buffer, int x){
    for(int i=0; i<x; i++)
    {
        delete Buffer[i].lpBuffer;
    }
    delete[] Buffer;
}
можно и на указателях все, но лень было править
QWAN
58 / 57 / 1
Регистрация: 02.09.2008
Сообщений: 181
10.02.2011, 14:15  [ТС]     Дайте ссылку или пример на интересующий меня вопрос. #3
За пример спасибо.
Цитата Сообщение от alex_x_x Посмотреть сообщение
можно и на указателях все, но лень было править
А можно хотябы на словах как это все должно происходить при использовании указателей или где почитать.
alex_x_x
бжни
2447 / 1652 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
10.02.2011, 14:27     Дайте ссылку или пример на интересующий меня вопрос. #4
почитайте про утечки памяти
например
http://www.cyberguru.ru/programming/...mory-leak.html
http://cppworld.h16.ru/stdc/memory.htm
http://www.amse.ru/courses/cpp1/2009.10.19.html
http://www.intuit.ru/department/algorithms/staldata/27/

здесь надо понимать уровень на котором ведется разговор
первоначально важно понимать как правильно работать с указателями, когда можно и нужно их освобождать
далее идут вопросы как не нужно работать с указателями, когда не нужно, смарт поинтеры и так далее
определитесь с общими понятиями в них даются общие правила работы
talis
791 / 543 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
10.02.2011, 14:37     Дайте ссылку или пример на интересующий меня вопрос. #5
QWAN, вы писали:
C++
1
2
//Я обьявляю указатель на этот массив FRAGMENT.
FRAGMENT *mf;
Указатель-то вы объявили, а сам массив не создали.

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
FRAGMENT *mf = 0;
int mf_size = 0;
 
//...
void construct_fragment( int size )
{
   mf_size = size;
   mf = new FRAGMENT[ size ];
}
 
void delete_fragment()
{
   mf_size = 0;
   delete [] mf;
   mf = 0;
}
 
void cout_all_fragments()
{
   if(mf == 0) return; //нулевой указатель. объекта не существует.
 
   for( int i = 0; i < mf_size; i++ )
   {
      cout << mf[i].Size_X;
      //...
   }
}
В этом случае int counter вам не нужен (если, конечно, вы не связанный список делаете. А вы, вроде, не связанный список делаете )

На словах: указатель - переменная, хранящая в себе адрес какого-то объекта. То, что вы выделили 4 байта под указатель, ещё не значит, что выделили 32 байта под объект (или сколько он там у вас занимает) или 32*8 байт на массив объектов из 8 элементов.

Память выделяется динамически - (через "new", освобождается через "delete []" для массивов или "delete" для единичных объектов). Когда вы пишите "char * ptr;" вы создаёте указатель на объект(ы) типа char. Но вам ведь ещё сами объекты создать нужно, верно? "ptr = new char[256];" Когда они вам перестают быть нужны, удалите их: "delete [] ptr;". Так же хорошим тоном считается инициализировать указатели нулём и при удалении объектов, на которые они указывают, так же обнулять их.
easybudda
Эксперт CЭксперт С++
9465 / 5478 / 927
Регистрация: 25.07.2009
Сообщений: 10,500
10.02.2011, 14:38     Дайте ссылку или пример на интересующий меня вопрос. #6
QWAN, если хотите сохранять в файл массив структур, лучше в структуре поле char *lpBuffer; сделать не указателем, а массивом
C
1
char szBuffer[SOME_PREDEFINED_SIZE];
тогда получится что-то вроде
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
typedef struct  FRAGMENT {
    int counter;        // счетчик, показывает номер фрагмента
    int Size_X;         // размер фрагмента по Х
    int Size_Y;        // размер фрагмента по Y
    char szBuffer[SOME_PREDEFINED_SIZE];        // здесь хранятся символы
}fragment_t; // так привычнее и удобнее
 
...
 
fragment_t stat_fragments[NUMBER_OF_FRAGMENTS];
fragment_t * dyn_fragments = (fragment_t*)calloc(NUMBER_OF_FRAGMENTS, sizeof(fragment_t)); 
// на самом деле нужно проверить, удачно ли память выделилась
...
// чем-то как-то заполняем массив(ы)
// пишем в файл
FILE * f = fopen(FILE_NAME, "wb"); // то же замечание по поводу проверки
fwrite(stat_fragments, NUMBER_OF_FRAGMENTS, sizeof(fragment_t), f); 
// возвращённое значение должно ровняться NUMBER_OF_FRAGMENTS
fwrite(dyn_fragments, NUMBER_OF_FRAGMENTS, sizeof(fragment_t), f); 
// возвращённое значение должно ровняться NUMBER_OF_FRAGMENTS
fclose(f);
...
// чтение
f = fopen(FILE_NAME, "rb");
fread(stat_fragments, NUMBER_OF_FRAGMENTS, sizeof(fragment_t), f); 
// возвращённое значение должно ровняться NUMBER_OF_FRAGMENTS
fread(dyn_fragments, NUMBER_OF_FRAGMENTS, sizeof(fragment_t), f); 
// возвращённое значение должно ровняться NUMBER_OF_FRAGMENTS
fclose(f);
// и снова повторюсь - не забывайте проверять ВСЕ значения, возвращаемые функциями ввода-вывода
QWAN
58 / 57 / 1
Регистрация: 02.09.2008
Сообщений: 181
10.02.2011, 15:20  [ТС]     Дайте ссылку или пример на интересующий меня вопрос. #7
Цитата Сообщение от talis Посмотреть сообщение
Указатель-то вы объявили, а сам массив не создали.
В функции ReadBuffer я и создавал сам массив
Buffer = new FRAGMENT[x];

В принципе программа нормально работала, пока я незахотел с помощю этой функции инициализировать еще один массив.
Тогда то я и понял что абсолютно ничего непонимаю и не только с операторами new и delete.
talis
791 / 543 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
10.02.2011, 15:30     Дайте ссылку или пример на интересующий меня вопрос. #8
Да, действительно. Извините. Просто сбивает с толку
C++
1
FRAGMENT *ReadBuffer(FRAGMENT *Buffer)
Зачем тогда параметр? можно ведь
C++
1
2
3
4
5
6
FRAGMENT * ReadBuffer()
{
   FRAGMENT * Buffer = new FRAGMENT[x];
   //...
   return Buffer;
}
Но вообще обычно делают так:
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
bool ReadBuffer( FRAGMENT * Buffer, int size )
{
   if( Buffer == 0 || size == 0 )
      return false;
 
   for(int i = 0; i < size; i++)
   {
        Buffer[i].counter = i;
        //
        //
        Buffer[i].lpBuffer = new char[number];//number - какоето число
        //дальше вызывается функция которая занесла информацию в Buffer[i].lpBuffer
   }
 
   return true;
}
 
void foo()
{
   FRAGMENT * local_buffer = new FRAGMENT[15];
 
   if( false == ReadBuffer( local_buffer, 15 ) )
      cout << "Error reading buffer. Probably local_buffer is not initialized" << endl;
 
   delete [] local_buffer;
}
 
//или:
 
void bar()
{
   FRAGMENT local_buffer[15];
 
   if( false == ReadBuffer( local_buffer, 15 ) )
      cout << "This should not happen!!!" << endl;
}
QWAN
58 / 57 / 1
Регистрация: 02.09.2008
Сообщений: 181
10.02.2011, 16:09  [ТС]     Дайте ссылку или пример на интересующий меня вопрос. #9
Давайте начну сначала, я попробую расказать чего я хочу добиться от своей программы.
Допустим есть консольное приложение с большим буфером экрана (назовем ее плоскостью А). Я создаю дополнительную плоскость тоже большого размера, назовем ее Б. Чтобы скопировать с плоскости Б на плоскость А определенный прямоугольник символов с их атрибуми использую функции ReadConsoleOutput и WriteConsoleOutput. Эти функции имеют ограничение по размеру буффера 64К. Чтобы преодолеть это ограничение я придумал свою структуру FRAGMENT.

Массив из структур FRAGMENT тепер есть мой буффер, который может быть ограничен в принципе только размером свободной памяти компютера.
Я создаю указатель на мой буфер. Но размера я его еще незнаю. Функция
Код C++
1 FRAGMENT * ReadRectSurface(HANDLE hSurface, SMALL_RECT lpReadRegion, FRAGMENT *pBuffer)

должна была вычислить по заданному размеру прямоугольника:
1) количество элементов в массиве. ЕСЛИ оно меньше 64К то всего один элемент;
2) выделить для массива память;
3) если размер прямоугольника больше 64К, я пробую разбить прямоугольник построчно, если и этот размер больше 64К то выдать ошибку (можно былобы и далее дробить но пока этого достаточно). Иначе, выделить память размером в длину строки. На эту память указывает последний указатель в моей структуре.
C++
1
2
3
4
5
6
//стуктура предназначена для хранения части поверхности или всей поверхности если ее размер не превышает LIMIT
typedef struct _FRAGMENT {
    int counter;                // счетчик, показывает сколько фрагментов находится после текущего
    COORD dwBufferSize;         // размер фрагмента
    CHAR_INFO *lpBuffer;        // буфер данных, здесь хранятся символы
} FRAGMENT, *PFRAGMENT;
Осталось определить что передавть в функцию ReadRectSurface , что она должна возвращать, и где сделать очистку памяти.
QWAN
58 / 57 / 1
Регистрация: 02.09.2008
Сообщений: 181
10.02.2011, 16:12  [ТС]     Дайте ссылку или пример на интересующий меня вопрос. #10
Навсякий случай прикреплю програмку, так будет более понятно. Она работает, только на чсном слове.
Вложения
Тип файла: rar main_control.rar (2.6 Кб, 18 просмотров)
QWAN
58 / 57 / 1
Регистрация: 02.09.2008
Сообщений: 181
10.02.2011, 16:15  [ТС]     Дайте ссылку или пример на интересующий меня вопрос. #11
Цитата Сообщение от easybudda Посмотреть сообщение
если хотите сохранять в файл массив структур, лучше в структуре поле char *lpBuffer; сделать не указателем, а массивом
Дело в том что я незнаю в определенный момент размер этого массива. Он вычисляется по ходу работы.
talis
791 / 543 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
10.02.2011, 16:19     Дайте ссылку или пример на интересующий меня вопрос. #12
QWAN, 64 Кб * 1024 = 65536 байт. Вы действительно думаете, что вам не хватит?

Добавлено через 17 секунд
Попробую вникнуть в вашу проблему...
QWAN
58 / 57 / 1
Регистрация: 02.09.2008
Сообщений: 181
10.02.2011, 16:29  [ТС]     Дайте ссылку или пример на интересующий меня вопрос. #13
Цитата Сообщение от talis Посмотреть сообщение
64 Кб * 1024 = 65536 байт. Вы действительно думаете, что вам не хватит?
Максимум что у меня получилось скопировать (по памяти) это прямоугольник 140 * 95. хотя он и немного меньше чем 64К. Причину я так и неустановил.
talis
791 / 543 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
10.02.2011, 17:07     Дайте ссылку или пример на интересующий меня вопрос. #14
Посмотрел я вашу программу. Вам удалось записать прямоугольник в 400 байт. Это действительно немного меньше 64 килобайт
Существенные корректировки пометил как MY_EDIT: в комментарии. Решении проблем с вылетом пометил как SOLUTION:
Вообще, пол-программы пришлось перелопатить. Если что - спрашивайте.
Вложения
Тип файла: zip main.zip (3.2 Кб, 14 просмотров)
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
10.02.2011, 18:36     Дайте ссылку или пример на интересующий меня вопрос.
Еще ссылки по теме:
C++ Дайте пожалуйста рабочий пример регулярного выражения c++
Интерфейсы в с++ дайте кто нибудь годный рабочий пример C++
У меня вопрос C++
C++ Опять у меня к Вам вопрос
C++ Дайте ссылку на книгу "C++ For Dummies: Stephen R. Davis" 4е издание на английском

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

Или воспользуйтесь поиском по форуму:
QWAN
58 / 57 / 1
Регистрация: 02.09.2008
Сообщений: 181
10.02.2011, 18:36  [ТС]     Дайте ссылку или пример на интересующий меня вопрос. #15
Спасибо, за переделанную програмку. Пока только смотрю что переделали. Вопросы чуть позже напишу, когда более вникну.
Цитата Сообщение от talis Посмотреть сообщение
Вам удалось записать прямоугольник в 400 байт. Это действительно немного меньше 64 килобайт
.
Это только для пробы, прямоугольник только ведь 10х10.
sizeof (CHAR_INFO) равен 4 байтам, 65536 / 4 = 16384 ячейки cимволов. Если 200*82 = 16400 то уже превышен лимит. У меня раскрывая консольное окно на весь экран (22") получаю разрешение в символьных ячейках 240*95 = 22800, 22800 * 4 = 91200 байт.

Добавлено через 36 минут
Досмотрел програмку, спасибо большое за исправленные ошибки.
Код C++
1 int lpBufferSize; // MY_EDIT: размер буфера данных

Думаю, это лишняя переменная в структуре, она избыточна, достаточно ширины на высоты и sizeof (CHAR_INFO).

Вариант с применением глобальной переменной Код C++
1 int arraySize;

мне понравился, удаляется переменная из структуры.
Yandex
Объявления
10.02.2011, 18:36     Дайте ссылку или пример на интересующий меня вопрос.
Ответ Создать тему
Опции темы

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