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

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

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.78
QWAN
56 / 55 / 1
Регистрация: 02.09.2008
Сообщений: 181
10.02.2011, 13:55     Дайте ссылку или пример на интересующий меня вопрос. #1
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 и почему.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
10.02.2011, 13:55     Дайте ссылку или пример на интересующий меня вопрос.
Посмотрите здесь:

Где найти borland С++, дайте ссылку C++
C++ Дайте ссылку на компилятор C++
дайте пожалуйста ссылку где скачать Turbo С++ C++
C++ Дайте пожалуйста рабочий пример регулярного выражения c++
C++ Дайте пожалуйста ссылку на сайт с командами
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
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
56 / 55 / 1
Регистрация: 02.09.2008
Сообщений: 181
10.02.2011, 14:15  [ТС]     Дайте ссылку или пример на интересующий меня вопрос. #3
За пример спасибо.
Цитата Сообщение от alex_x_x Посмотреть сообщение
можно и на указателях все, но лень было править
А можно хотябы на словах как это все должно происходить при использовании указателей или где почитать.
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
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
 Аватар для talis
789 / 541 / 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
Модератор
Эксперт С++
 Аватар для easybudda
9373 / 5423 / 914
Регистрация: 25.07.2009
Сообщений: 10,423
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
56 / 55 / 1
Регистрация: 02.09.2008
Сообщений: 181
10.02.2011, 15:20  [ТС]     Дайте ссылку или пример на интересующий меня вопрос. #7
Цитата Сообщение от talis Посмотреть сообщение
Указатель-то вы объявили, а сам массив не создали.
В функции ReadBuffer я и создавал сам массив
Buffer = new FRAGMENT[x];

В принципе программа нормально работала, пока я незахотел с помощю этой функции инициализировать еще один массив.
Тогда то я и понял что абсолютно ничего непонимаю и не только с операторами new и delete.
talis
 Аватар для talis
789 / 541 / 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
56 / 55 / 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
56 / 55 / 1
Регистрация: 02.09.2008
Сообщений: 181
10.02.2011, 16:12  [ТС]     Дайте ссылку или пример на интересующий меня вопрос. #10
Навсякий случай прикреплю програмку, так будет более понятно. Она работает, только на чсном слове.
Вложения
Тип файла: rar main_control.rar (2.6 Кб, 18 просмотров)
QWAN
56 / 55 / 1
Регистрация: 02.09.2008
Сообщений: 181
10.02.2011, 16:15  [ТС]     Дайте ссылку или пример на интересующий меня вопрос. #11
Цитата Сообщение от easybudda Посмотреть сообщение
если хотите сохранять в файл массив структур, лучше в структуре поле char *lpBuffer; сделать не указателем, а массивом
Дело в том что я незнаю в определенный момент размер этого массива. Он вычисляется по ходу работы.
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
10.02.2011, 16:19     Дайте ссылку или пример на интересующий меня вопрос. #12
QWAN, 64 Кб * 1024 = 65536 байт. Вы действительно думаете, что вам не хватит?

Добавлено через 17 секунд
Попробую вникнуть в вашу проблему...
QWAN
56 / 55 / 1
Регистрация: 02.09.2008
Сообщений: 181
10.02.2011, 16:29  [ТС]     Дайте ссылку или пример на интересующий меня вопрос. #13
Цитата Сообщение от talis Посмотреть сообщение
64 Кб * 1024 = 65536 байт. Вы действительно думаете, что вам не хватит?
Максимум что у меня получилось скопировать (по памяти) это прямоугольник 140 * 95. хотя он и немного меньше чем 64К. Причину я так и неустановил.
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
10.02.2011, 17:07     Дайте ссылку или пример на интересующий меня вопрос. #14
Посмотрел я вашу программу. Вам удалось записать прямоугольник в 400 байт. Это действительно немного меньше 64 килобайт
Существенные корректировки пометил как MY_EDIT: в комментарии. Решении проблем с вылетом пометил как SOLUTION:
Вообще, пол-программы пришлось перелопатить. Если что - спрашивайте.
Вложения
Тип файла: zip main.zip (3.2 Кб, 14 просмотров)
QWAN
56 / 55 / 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;

мне понравился, удаляется переменная из структуры.
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
10.02.2011, 18:47     Дайте ссылку или пример на интересующий меня вопрос. #16
Вариант с применением глобальной переменной
int arraySize;
мне понравился, удаляется переменная из структуры.
Это нормальная практика, когда рядом с динамически выделенным массивом лежит его размер.

int lpBufferSize; // MY_EDIT: размер буфера данных
Думаю, это лишняя переменная в структуре, она избыточна, достаточно ширины на высоты и sizeof (CHAR_INFO).
Да, данные возможно рассчитать. На самом деле, это вопрос баланса между производительностью и расходом памяти, на этот счёт некоторые программисты спорят до хрипоты: с одной стороны - лишние 4 байта на каждый элемент массива, с другой - каждый раз рассчитывать, лишние итерации. В данном случае это не критично, поэтому я руководствуюсь рекомендациями Бьерна Страуструпа: писать код, понятный человеку. Мне так было понятнее, но дело ваше .

Добавлено через 6 минут
Попробуйте посмотреть в сторону curses - очень умная библиотека, к тому же кроссплатформенная. Для Windows есть pdcurses.
QWAN
56 / 55 / 1
Регистрация: 02.09.2008
Сообщений: 181
10.02.2011, 19:01  [ТС]     Дайте ссылку или пример на интересующий меня вопрос. #17
Думаю чтобы использовать сторонние библиотеки я еще не дорос (мало знаний и опыта). Программирование для меня просто увлечение. Сейчас пытаюсь сделать простой ASCII редактор с панелью инструментов, окнами и каким-то проигывателем ASCII анимации. Заодно осваиваю и практикуюсь в програмировании. Насчет писать кросплатформенные програмки пока только мечтаю, но библиотеку Curses всеравно посмотрю.
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
10.02.2011, 19:33     Дайте ссылку или пример на интересующий меня вопрос. #18
Да, много же вы мучаться будете, если будете писать ASCII-редактор с панелью инструментов, используя стандарнтый вывод! Тогда вам что-то, кроме curses, просто противопоказано!
accept
4838 / 3237 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
11.02.2011, 04:11     Дайте ссылку или пример на интересующий меня вопрос. #19
Цитата Сообщение от QWAN
1 int lpBufferSize; // MY_EDIT: размер буфера данных

Думаю, это лишняя переменная в структуре, она избыточна
C++
1
2
3
4
5
6
struct  FRAGMENT {
    int counter;        // счетчик, показывает номер фрагмента
    int Size_X;         // размер фрагмента по Х
    int Size_Y;        // размер фрагмента по Y
    char *lpBuffer;        // здесь хранятся символы
};
каким образом программа будет определять, сколько символов хранится в lpBuffer ?
при сохранении символов в lpBuffer, каким образом программа будет определять, что не произошло переполнение lpBuffer ?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.02.2011, 10:17     Дайте ссылку или пример на интересующий меня вопрос.
Еще ссылки по теме:

MVC дайте пример C++
C++ Дайте ссылку, где можно разобраться с табуляцией?
C++ Дайте ссылку на Dshow

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

Или воспользуйтесь поиском по форуму:
QWAN
56 / 55 / 1
Регистрация: 02.09.2008
Сообщений: 181
11.02.2011, 10:17  [ТС]     Дайте ссылку или пример на интересующий меня вопрос. #20
Цитата Сообщение от accept Посмотреть сообщение
каким образом программа будет определять, сколько символов хранится в lpBuffer ? при сохранении символов в lpBuffer, каким образом программа будет определять, что не произошло переполнение lpBuffer ?
Уменя пока реализовано так:
C++
1
pBuffer->lpBuffer = new CHAR_INFO [RegionSize.X * RegionSize.Y];
Talis когда исправлял мою програмку, добавил переменную для для определения размера буфера.

Цитата Сообщение от talis Посмотреть сообщение
Это нормальная практика, когда рядом с динамически выделенным массивом лежит его размер. int lpBufferSize; // MY_EDIT: размер буфера данных Думаю, это лишняя переменная в структуре, она избыточна, достаточно ширины на высоты и sizeof (CHAR_INFO). Да, данные возможно рассчитать. На самом деле, это вопрос баланса между производительностью и расходом памяти, на этот счёт некоторые программисты спорят до хрипоты: с одной стороны - лишние 4 байта на каждый элемент массива, с другой - каждый раз рассчитывать, лишние итерации. В данном случае это не критично, поэтому я руководствуюсь рекомендациями Бьерна Страуструпа: писать код, понятный человеку. Мне так было понятнее, но дело ваше . Добавлено через 6 минут.
Yandex
Объявления
11.02.2011, 10:17     Дайте ссылку или пример на интересующий меня вопрос.
Ответ Создать тему
Опции темы

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