Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2  Все   Вниз
  Печать  
Автор Тема: Двумерный динамический массив. Сохранение и считывание из файла.  (Прочитано 40336 раз)
0 Пользователей и 5 Гостей смотрят эту тему.
goodking
Постоялец

ua
Offline Offline
Пол: Мужской

« : 12-12-2013 15:53 » 

Подскажите пожалуйста, как реализовать ввод в файл, и дальнейшее считывание из него двумерного динамического массива.

Запись в файл делаю так:
Код:
f1=fopen("project11", "wb");

State s;

for(int i=0;i<rows;++i)
for(int z=0;z<cols;++z)
{
s=p[i][z];

fwrite(&s,sizeof(State),rows*cols,f1); }

fclose(f1);

Не знаю, корректно ли записываются данные в файл, т.к. способ считывать из файла не нашел.  Улыбаюсь
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 12-12-2013 17:25 » 

goodking, ну вообще если пишет в файл fwrite, то несложно догадаться, что читает fread - буквальный перевод с английского. Что значит не нашёл? Google что ли выключили?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
goodking
Постоялец

ua
Offline Offline
Пол: Мужской

« Ответ #2 : 12-12-2013 17:57 » 

Про fread знаю. Только как применить fread именно для случая двухмерного динамического массива? Не напишешь же
Код:
fread(p,sizeof(State),rows*cols,f1); 
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 12-12-2013 22:20 » 

goodking, почему нет?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
sss
Специалист

ru
Offline Offline

« Ответ #4 : 13-12-2013 08:24 » 

Наверное упал в обморок от постигшей его истины Отлично
Записан

while (8==8)
goodking
Постоялец

ua
Offline Offline
Пол: Мужской

« Ответ #5 : 13-12-2013 09:52 » 

Не, я в порядке  Ага
То-есть все значения в массив заносятся за один раз? Я думал, что надо элементы по одному вытягивать из файла в цикле.
Записан
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 13-12-2013 10:52 » 

goodking, в C++ нет двумерных динамических массивов, насколько мне известно. Если у тебя массив массивов, то так не выйдет - придётся читать в цикле, по строке за раз, в каждый из массивов.
Покажи, как ты массив создаёшь.
Записан
goodking
Постоялец

ua
Offline Offline
Пол: Мужской

« Ответ #7 : 13-12-2013 11:47 » 

Создаю вот так
Код:
State **p = 0;
....
try
         {
         p = new State *[rows];
         for(int i =0; i<rows;++i)
         {p[i]= new State [cols];}
         }
         catch (std::bad_alloc err){ShowMessage("Error"); exit(1);}

         fread(p,sizeof(State),rows*cols,f1);/*это попытка считать в массив из файла как посоветовали(безуспешная). Да, файл ранее открыт для  чтения*/
« Последнее редактирование: 13-12-2013 11:50 от goodking » Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 13-12-2013 12:50 » 

goodking, да, это массив массивов. Операции применимы только к непрерывному куску памяти. В данном случае к столбцу.

Только всё равно непонятно: fwrite и fread абсолютно зеркальные операции. Если работает fwrite, то работает и fread. Если не работает fread, значит не работает и fwrite.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #9 : 13-12-2013 14:51 » 

IO операции не работают со структурами и указателями. Они рассматривают буфер как плоский кусок памяти размером sizeof(State) * rows * cols. В тоже время p - массив указателей. Волшебства не бывает. Придется загружать каждый State персонально. Возможен и другой подход. Скажем, можно сделать
State buffer[rows * cols];
fread(buffer, ...);
и далее использовать как buffer[row * cols + col]
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
goodking
Постоялец

ua
Offline Offline
Пол: Мужской

« Ответ #10 : 13-12-2013 20:42 » 

В тоже время p - массив указателей. Волшебства не бывает. Придется загружать каждый State персонально.
Это я уже понял. То есть создаю объект State, считываю в него один элемент из файла, потом заношу из объекта в ячейку д.массива. Только вопрос, как в функции fread после считывания переместить указатель на следующий элемент в файле?

И еще, разве массив массивов и двумерный массив это не одно и то же?
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #11 : 13-12-2013 22:24 » 

Массив — непрерывная область памяти, последовательность однотипных элементов.
Двухмерный массив — непрерывная область памяти, последовательность из однотипных массивов одного размера.
Массив указателей — не двухмерный массив.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #12 : 13-12-2013 23:12 » 

goodking, массив в общем случае - это кусок памяти, в том числе и многомерный массив. Массив массивов - это разные куски памяти, связанные указателями подобно списочной структуре. Поэтому в массиве массивов некоторые из вложенных массивов могут быть NULL - отсутствовать, они могут создаваться и удаляться в произвольное время, они могут иметь произвольные размеры, никак не зависящие от соседей. В многомерном массиве с этим всё строго: всё создаётся и удаляется одновременно, всё имеет равный с соседями размер.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #13 : 15-12-2013 00:00 » 

То есть создаю объект State, считываю в него один элемент из файла, потом заношу из объекта в ячейку д.массива. Только вопрос, как в функции fread после считывания переместить указатель на следующий элемент в файле?

Не обязательно по одному. Как уже выше сказал Dimka, у тебя есть непрерывные куски памяти (только строки, а не столбцы). Можно читать по одному, если очень хочется, но эффективнее это будет сделать более крупными кусками. Никуда не надо перемещать указатель в файле - он при чтении и так перемещается. Его можно перемещать произвольно (функцией fseek), но в твоём случае это не нужно. Показываю на твоём коде (сократил слегка):
Код: (C++)
State * p = new State *[rows];
for(int i =0; i<rows;++i)
{
    p[i]= new State[cols]; // здесь ты выделяешь память под i-тую строку
    // а теперь просто читаем её из файла (с записью будет аналогично)
    fread(p[i], sizeof(State), cols, f1);
}
вот и всё.

А, нет, ещё одно. Чтобы открыть файл на чтение и на запись одновременно, надо открывать с атрибутом "rb+" или "wb+" (в первом случае файл должен существовать, во втором - нет, но содержимое существующего уничтожается при открытии), а не "wb" (см. документацию по параметрам fopen: http://msdn.microsoft.com/en-us/library/yeby3zcb.aspx). И fflush делать, если чтение из файла происходит после записи в него без повторного открытия.
« Последнее редактирование: 15-12-2013 00:03 от Вад » Записан
goodking
Постоялец

ua
Offline Offline
Пол: Мужской

« Ответ #14 : 16-12-2013 08:18 » 

Вад
Супер, спасибо!

Добавлено через 2 дня, 4 часа и 55 минут:
Обращаюсь еще раз за помощью. Улыбаюсь Возникла необходимость сохранять еще два изображения формата bpm в рамках этого приложения. Возможно ли из записывать в тот же файл, если да, то как это сделать? Почему то не могу найти ничего по сохранению изображений в файл кроме SaveToFile.
« Последнее редактирование: 18-12-2013 13:13 от goodking » Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #15 : 18-12-2013 15:02 » 

goodking, ничего не понял. Куда сохранять? И чем не нравится SaveToFile? И кто потом будет вычитывать обратно эти несколько BMP из одного файла?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
goodking
Постоялец

ua
Offline Offline
Пол: Мужской

« Ответ #16 : 19-12-2013 10:50 » 

goodking, ничего не понял. Куда сохранять? И чем не нравится SaveToFile? И кто потом будет вычитывать обратно эти несколько BMP из одного файла?
Ну раньше я спрашивал о том, как сохранить данные из массива в файл. Теперь мне надо из этой же программы параллельно с массивом сохранять два BMP, с возможностью дальнейшего(одновременно с файлом, содержащим данные из массива) их чтения конечно. SaveToFile сохраняет каждый рисунок в отдельный файл, то-есть при сохранении у меня получается три разных файла - два рисунка и один бинарный с данными из массива. Вопрос как обьединить эти 3 файла в один. Улыбаюсь
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #17 : 19-12-2013 11:56 » 

goodking, а ты ищешь приключений на пятую точку опоры?

Технически записать три куска памяти в один файл - не проблема. Проблема потом узнать, с какого байта заканчивается один кусок и начинается другой внутри файла.

Кроме того сам BMP в программе обычно доступен через несколько вспомогательных структур, поэтому выудить его как непрерывную область памяти в правильном формате - отдельная задача.

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

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
goodking
Постоялец

ua
Offline Offline
Пол: Мужской

« Ответ #18 : 20-12-2013 17:11 » 

Ладно, пока отложу этот вопрос. Улыбаюсь

Добавлено через 73 дня, 1 час, 17 минут и 38 секунд:
Добрый день снова! Улыбаюсь Пришлось таки вернуться к этой теме. Необходимо сохранить в один файл структуру, и два графических файла. Вот что у меня получилось
Код: (C++)
  1. f1=fopen("project", "w+b");
  2.  
  3.  saved sv;// объявляю структуру и сохраняю в нее данные
  4.  
  5. sv.flag=flag;
  6. sv.pause=pause;
  7. sv.Aimb=Aimb;
  8. sv.Intruderb=Intruderb;
  9. sv.Guardb=Guardb;
  10. sv.naprolom=naprolom;
  11. sv.startsec=startsec;
  12. sv.obnaruj=obnaruj;
  13. sv.x11=x11;
  14. sv.y11=y11;
  15. sv.securx1=securx1;
  16. sv.secury1=secury1;
  17. sv.aimx1=aimx1;
  18. sv.aimy1=aimy1;
  19. sv.securedist=securedist;
  20. sv.thick=thick;
  21. sv.cols=cols;
  22. sv.rows=rows;
  23. sv.vzlom=vzlomdel;
  24.  
  25. sv.imWidth=Bitmap->Width;
  26. sv.imHeight=Bitmap->Height;
  27.  
  28. sv.pimWidth=Image1->Picture->Width;
  29. sv.pimHeight=Image1->Picture->Height;
  30.  
  31. setmem(&sv.bitheader,sizeof(sv.bitheader),0);
  32.  
  33. sv.bitheader=Bitmap->Handle;//Сохраняю данные из первого бмп
  34. sv.infobit.bmiHeader.biSize=sizeof(sv.infobit.bmiHeader);
  35. sv.infobit.bmiHeader.biBitCount=0;
  36.  
  37. Graphics::TBitmap * Bitmap2= new Graphics::TBitmap;
  38. Bitmap2->Assign(Image1->Picture);//второго
  39.  
  40. setmem(&sv.pbitheader,sizeof(sv.pbitheader),0);
  41.  
  42. sv.pbitheader=Bitmap2->Handle;
  43. sv.pinfobit.bmiHeader.biSize=sizeof(sv.pinfobit.bmiHeader);
  44. sv.pinfobit.bmiHeader.biBitCount=0;
  45.  
  46.  
  47.  
  48. int ret = GetDIBits(Bitmap->Canvas->Handle,Bitmap->Handle,0,sv.imHeight,0,&sv.infobit,DIB_RGB_COLORS);
  49. int ret2 = GetDIBits(Bitmap2->Canvas->Handle,Bitmap2->Handle,0,sv.pimHeight,0,&sv.pinfobit,DIB_RGB_COLORS);// заполняю BITMAPINFO
  50. if (ret!=0&&ret2!=0)
  51. {
  52. int buffsize=sv.infobit.bmiHeader.biSizeImage;
  53. sv.bufsize=buffsize;
  54. int buffsize2=sv.pinfobit.bmiHeader.biSizeImage;
  55. sv.pbufsize=buffsize2;
  56.  
  57. fwrite(&sv,sizeof(saved),1,f1);//записываю структуру в файл
  58. BYTE *buff=new BYTE [buffsize];
  59. BYTE *buff2=new BYTE [buffsize2];
  60.  
  61. ret = GetDIBits(Bitmap->Canvas->Handle,Bitmap->Handle,0,sv.imHeight,buff,&sv.infobit,DIB_RGB_COLORS);
  62. ret2 = GetDIBits(Bitmap2->Canvas->Handle,Bitmap2->Handle,0,sv.pimHeight,buff2,&sv.pinfobit,DIB_RGB_COLORS);//здесь сохраняю данные в буфер
  63. BYTE buf;
  64. BYTE buf2;
  65.  
  66.  
  67.  
  68.  
  69. for(int i=0;i<buffsize;++i)
  70. {
  71. buf=buff[i];
  72. fwrite(&buf,sizeof(BYTE),1,f1);
  73. }
  74.  
  75. for(int i=0;i<buffsize2;++i)
  76. {
  77. buf2=buff2[i];
  78. fwrite(&buf2,sizeof(BYTE),1,f1);
  79. }
  80.  
  81. }
  82.  
  83. else {ShowMessage("Ошибка записи в файл!"); return;}
  84.  
  85.  

Подскажите пожалуйста, в чем может быть ошибка,  в буфер записываются пустые изображения.
« Последнее редактирование: 03-03-2014 18:28 от goodking » Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #19 : 27-02-2014 08:52 » 

goodking, ну, во-первых, где сама структура, где её объявление? Во-вторых, что-то мне очень подозрительными кажутся поля заголовков BMP в структуре. Надеюсь, ты осознаёшь, что хранение внутри структуры указателя на область памяти никак не означает автоматическое сохранение в файле всего куска памяти за указателем. Будет сохранён только сам указатель и ничего больше. И в таком виде это бесполезно. Превращение сложных вложенных структур в байтовый поток называется "сериализацией", обратный процесс "десериализацией", и это тема обширная.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
goodking
Постоялец

ua
Offline Offline
Пол: Мужской

« Ответ #20 : 27-02-2014 09:48 » 

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

Конечно. Запись массива байт рисунка в файл производится вот так в вышеприведенном коде.
Код:
for(int i=0;i<buffsize;++i)
{
buf=buff[i];
fwrite(&buf,sizeof(BYTE),1,f1);//первый рисунок
}

for(int i=0;i<buffsize2;++i)
{
buf2=buff2[i];
fwrite(&buf2,sizeof(BYTE),1,f1);// второй
}

Структура сохраняется и считывается нормально, вопрос не в ней. Ошибка в использовании функции GetDIBits как я понимаю.
« Последнее редактирование: 27-02-2014 09:53 от goodking » Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #21 : 27-02-2014 10:18 » 

goodking, твой вызов GetDIBits оба раза (зачем?) заполняет структуру Info и ни разу не получает пикселы.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
goodking
Постоялец

ua
Offline Offline
Пол: Мужской

« Ответ #22 : 27-02-2014 10:25 » new

вот здесь заполяю инфо для двух рисунков
Код:
int ret = GetDIBits(Bitmap->Canvas->Handle,Bitmap->Handle,0,sv.imHeight,0,&sv.infobit,DIB_RGB_COLORS);
int ret2 = GetDIBits(Bitmap2->Canvas->Handle,Bitmap2->Handle,0,sv.pimHeight,0,&sv.pinfobit,DIB_RGB_COLORS);

а здесь захватываю данные из рисунков
Код:
ret = GetDIBits(Bitmap->Canvas->Handle,Bitmap->Handle,0,sv.imHeight,buff,&sv.infobit,DIB_RGB_COLORS);
ret2 = GetDIBits(Bitmap2->Canvas->Handle,Bitmap2->Handle,0,sv.pimHeight,buff2,&sv.pinfobit,DIB_RGB_COLORS);


Добавлено через 1 день, 5 часов, 36 минут и 25 секунд:
Более точно - не корректно работает данный вызов функции

Код:
ret2 = GetDIBits(Bitmap2->Canvas->Handle,Bitmap2->Handle,0,sv.pimHeight,buff2,&sv.pinfobit,DIB_RGB_COLORS);

возвращает ноль.

Подскажите, в чем может быть проблема.
« Последнее редактирование: 28-02-2014 16:01 от goodking » Записан
Serguntii
Помогающий

ru
Offline Offline

« Ответ #23 : 28-02-2014 16:19 » 

А что возвращает GetLastError()
Записан
goodking
Постоялец

ua
Offline Offline
Пол: Мужской

« Ответ #24 : 03-03-2014 09:10 » 

8- недостаточно памяти для обработки команды
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #25 : 03-03-2014 15:44 » 

goodking, А каких размеров BMP ты пытаешся читать, Просто ради интереса вопрос.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #26 : 03-03-2014 18:34 » 

goodking, если я не ошибаюсь, надо буфер создавать не размером с размер изображения (у тебя строки 53 и 55 - я поправил разметку в твоём сообщении), а прибавить к этому размер структуры BITMAPINFO, которая и будет записана туда в начало буфера, а уже как её часть (второй и последний член) пойдёт массив пикселей изображения:
Код: (C++)
typedef struct tagBITMAPINFO {
  BITMAPINFOHEADER bmiHeader;
  RGBQUAD          bmiColors[1];
} BITMAPINFO, *PBITMAPINFO;
« Последнее редактирование: 03-03-2014 18:36 от Вад » Записан
goodking
Постоялец

ua
Offline Offline
Пол: Мужской

« Ответ #27 : 04-03-2014 13:00 » 

Finch - bufsize= 1500000

Добавлено через 46 секунд:
Вад, то есть структура и будет содержать буфер?
« Последнее редактирование: 04-03-2014 13:01 от goodking » Записан
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #28 : 04-03-2014 19:20 » 

goodking, посмотри документацию на GetDIBits.
Это, в принципе, довольно стандартный подход для WinAPI и не только: структура, содержащая последним членом массив из 1 элемента, куда записывается блок данных переменного размера, и всё это записывается в общий динамический массив. Поэтому и памяти надо выделять на "структуру + размер блока данных - 1 элемент" (первый элемент ещё попадает в "заголовок").
Отсюда и ошибка "мало памяти": в начало, в любом случае, пишется структура-"заголовок", а данные - со смещением, и под них уже не остаётся места, если выделять памяти столько, сколько ты выделяешь. Мне, правда, непонятно, почему только на 2м изображении ошибка происходит - должна на обоих быть.

Перечитал - похоже, неправ я - всё-таки, судя по документации туда просто буфер передаётся для битмапа. Тогда непонятно
« Последнее редактирование: 04-03-2014 19:34 от Вад » Записан
goodking
Постоялец

ua
Offline Offline
Пол: Мужской

« Ответ #29 : 05-03-2014 14:09 » 

Вад

Есть какие-то идеи, с чем это может быть связано?
Записан
Страниц: [1] 2  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines