goodking
|
|
« : 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
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #1 : 12-12-2013 17:25 » |
|
goodking, ну вообще если пишет в файл fwrite, то несложно догадаться, что читает fread - буквальный перевод с английского. Что значит не нашёл? Google что ли выключили?
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
goodking
|
|
« Ответ #2 : 12-12-2013 17:57 » |
|
Про fread знаю. Только как применить fread именно для случая двухмерного динамического массива? Не напишешь же fread(p,sizeof(State),rows*cols,f1);
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #3 : 12-12-2013 22:20 » |
|
goodking, почему нет?
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
sss
Специалист
Offline
|
|
« Ответ #4 : 13-12-2013 08:24 » |
|
Наверное упал в обморок от постигшей его истины
|
|
|
Записан
|
while (8==8)
|
|
|
goodking
|
|
« Ответ #5 : 13-12-2013 09:52 » |
|
Не, я в порядке То-есть все значения в массив заносятся за один раз? Я думал, что надо элементы по одному вытягивать из файла в цикле.
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #6 : 13-12-2013 10:52 » |
|
goodking, в C++ нет двумерных динамических массивов, насколько мне известно. Если у тебя массив массивов, то так не выйдет - придётся читать в цикле, по строке за раз, в каждый из массивов. Покажи, как ты массив создаёшь.
|
|
|
Записан
|
|
|
|
goodking
|
|
« Ответ #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
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #8 : 13-12-2013 12:50 » |
|
goodking, да, это массив массивов. Операции применимы только к непрерывному куску памяти. В данном случае к столбцу.
Только всё равно непонятно: fwrite и fread абсолютно зеркальные операции. Если работает fwrite, то работает и fread. Если не работает fread, значит не работает и fwrite.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
RXL
|
|
« Ответ #9 : 13-12-2013 14:51 » |
|
IO операции не работают со структурами и указателями. Они рассматривают буфер как плоский кусок памяти размером sizeof(State) * rows * cols. В тоже время p - массив указателей. Волшебства не бывает. Придется загружать каждый State персонально. Возможен и другой подход. Скажем, можно сделать State buffer[rows * cols]; fread(buffer, ...); и далее использовать как buffer[row * cols + col]
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
goodking
|
|
« Ответ #10 : 13-12-2013 20:42 » |
|
В тоже время p - массив указателей. Волшебства не бывает. Придется загружать каждый State персонально.
Это я уже понял. То есть создаю объект State, считываю в него один элемент из файла, потом заношу из объекта в ячейку д.массива. Только вопрос, как в функции fread после считывания переместить указатель на следующий элемент в файле? И еще, разве массив массивов и двумерный массив это не одно и то же?
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #11 : 13-12-2013 22:24 » |
|
Массив — непрерывная область памяти, последовательность однотипных элементов. Двухмерный массив — непрерывная область памяти, последовательность из однотипных массивов одного размера. Массив указателей — не двухмерный массив.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #12 : 13-12-2013 23:12 » |
|
goodking, массив в общем случае - это кусок памяти, в том числе и многомерный массив. Массив массивов - это разные куски памяти, связанные указателями подобно списочной структуре. Поэтому в массиве массивов некоторые из вложенных массивов могут быть NULL - отсутствовать, они могут создаваться и удаляться в произвольное время, они могут иметь произвольные размеры, никак не зависящие от соседей. В многомерном массиве с этим всё строго: всё создаётся и удаляется одновременно, всё имеет равный с соседями размер.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Вад
|
|
« Ответ #13 : 15-12-2013 00:00 » |
|
То есть создаю объект State, считываю в него один элемент из файла, потом заношу из объекта в ячейку д.массива. Только вопрос, как в функции fread после считывания переместить указатель на следующий элемент в файле?
Не обязательно по одному. Как уже выше сказал Dimka, у тебя есть непрерывные куски памяти (только строки, а не столбцы). Можно читать по одному, если очень хочется, но эффективнее это будет сделать более крупными кусками. Никуда не надо перемещать указатель в файле - он при чтении и так перемещается. Его можно перемещать произвольно (функцией fseek), но в твоём случае это не нужно. Показываю на твоём коде (сократил слегка): 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
|
|
« Ответ #14 : 16-12-2013 08:18 » |
|
Вад Супер, спасибо! Добавлено через 2 дня, 4 часа и 55 минут:Обращаюсь еще раз за помощью. Возникла необходимость сохранять еще два изображения формата bpm в рамках этого приложения. Возможно ли из записывать в тот же файл, если да, то как это сделать? Почему то не могу найти ничего по сохранению изображений в файл кроме SaveToFile.
|
|
« Последнее редактирование: 18-12-2013 13:13 от goodking »
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #15 : 18-12-2013 15:02 » |
|
goodking, ничего не понял. Куда сохранять? И чем не нравится SaveToFile? И кто потом будет вычитывать обратно эти несколько BMP из одного файла?
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
goodking
|
|
« Ответ #16 : 19-12-2013 10:50 » |
|
goodking, ничего не понял. Куда сохранять? И чем не нравится SaveToFile? И кто потом будет вычитывать обратно эти несколько BMP из одного файла?
Ну раньше я спрашивал о том, как сохранить данные из массива в файл. Теперь мне надо из этой же программы параллельно с массивом сохранять два BMP, с возможностью дальнейшего(одновременно с файлом, содержащим данные из массива) их чтения конечно. SaveToFile сохраняет каждый рисунок в отдельный файл, то-есть при сохранении у меня получается три разных файла - два рисунка и один бинарный с данными из массива. Вопрос как обьединить эти 3 файла в один.
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #17 : 19-12-2013 11:56 » |
|
goodking, а ты ищешь приключений на пятую точку опоры?
Технически записать три куска памяти в один файл - не проблема. Проблема потом узнать, с какого байта заканчивается один кусок и начинается другой внутри файла.
Кроме того сам BMP в программе обычно доступен через несколько вспомогательных структур, поэтому выудить его как непрерывную область памяти в правильном формате - отдельная задача.
Обе эти проблемы, учитывая твой уровень подготовки, загрузят тебя надолго.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
goodking
|
|
« Ответ #18 : 20-12-2013 17:11 » |
|
Ладно, пока отложу этот вопрос. Добавлено через 73 дня, 1 час, 17 минут и 38 секунд:Добрый день снова! Пришлось таки вернуться к этой теме. Необходимо сохранить в один файл структуру, и два графических файла. Вот что у меня получилось f1=fopen("project", "w+b"); saved sv;// объявляю структуру и сохраняю в нее данные sv.flag=flag; sv.pause=pause; sv.Aimb=Aimb; sv.Intruderb=Intruderb; sv.Guardb=Guardb; sv.naprolom=naprolom; sv.startsec=startsec; sv.obnaruj=obnaruj; sv.x11=x11; sv.y11=y11; sv.securx1=securx1; sv.secury1=secury1; sv.aimx1=aimx1; sv.aimy1=aimy1; sv.securedist=securedist; sv.thick=thick; sv.cols=cols; sv.rows=rows; sv.vzlom=vzlomdel; sv.imWidth=Bitmap->Width; sv.imHeight=Bitmap->Height; sv.pimWidth=Image1->Picture->Width; sv.pimHeight=Image1->Picture->Height; setmem(&sv.bitheader,sizeof(sv.bitheader),0); sv.bitheader=Bitmap->Handle;//Сохраняю данные из первого бмп sv.infobit.bmiHeader.biSize=sizeof(sv.infobit.bmiHeader); sv.infobit.bmiHeader.biBitCount=0; Graphics::TBitmap * Bitmap2= new Graphics::TBitmap; Bitmap2->Assign(Image1->Picture);//второго setmem(&sv.pbitheader,sizeof(sv.pbitheader),0); sv.pbitheader=Bitmap2->Handle; sv.pinfobit.bmiHeader.biSize=sizeof(sv.pinfobit.bmiHeader); sv.pinfobit.bmiHeader.biBitCount=0; 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);// заполняю BITMAPINFO if (ret!=0&&ret2!=0) { int buffsize=sv.infobit.bmiHeader.biSizeImage; sv.bufsize=buffsize; int buffsize2=sv.pinfobit.bmiHeader.biSizeImage; sv.pbufsize=buffsize2; fwrite(&sv,sizeof(saved),1,f1);//записываю структуру в файл BYTE *buff=new BYTE [buffsize]; BYTE *buff2=new BYTE [buffsize2]; 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);//здесь сохраняю данные в буфер BYTE buf; BYTE buf2; 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); } } else {ShowMessage("Ошибка записи в файл!"); return;}
Подскажите пожалуйста, в чем может быть ошибка, в буфер записываются пустые изображения.
|
|
« Последнее редактирование: 03-03-2014 18:28 от goodking »
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #19 : 27-02-2014 08:52 » |
|
goodking, ну, во-первых, где сама структура, где её объявление? Во-вторых, что-то мне очень подозрительными кажутся поля заголовков BMP в структуре. Надеюсь, ты осознаёшь, что хранение внутри структуры указателя на область памяти никак не означает автоматическое сохранение в файле всего куска памяти за указателем. Будет сохранён только сам указатель и ничего больше. И в таком виде это бесполезно. Превращение сложных вложенных структур в байтовый поток называется "сериализацией", обратный процесс "десериализацией", и это тема обширная.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
goodking
|
|
« Ответ #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
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #21 : 27-02-2014 10:18 » |
|
goodking, твой вызов GetDIBits оба раза (зачем?) заполняет структуру Info и ни разу не получает пикселы.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
goodking
|
|
« Ответ #22 : 27-02-2014 10:25 » |
|
вот здесь заполяю инфо для двух рисунков 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
Помогающий
Offline
|
|
« Ответ #23 : 28-02-2014 16:19 » |
|
А что возвращает GetLastError()
|
|
|
Записан
|
|
|
|
goodking
|
|
« Ответ #24 : 03-03-2014 09:10 » |
|
8- недостаточно памяти для обработки команды
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #25 : 03-03-2014 15:44 » |
|
goodking, А каких размеров BMP ты пытаешся читать, Просто ради интереса вопрос.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
Вад
|
|
« Ответ #26 : 03-03-2014 18:34 » |
|
goodking, если я не ошибаюсь, надо буфер создавать не размером с размер изображения (у тебя строки 53 и 55 - я поправил разметку в твоём сообщении), а прибавить к этому размер структуры BITMAPINFO, которая и будет записана туда в начало буфера, а уже как её часть (второй и последний член) пойдёт массив пикселей изображения: typedef struct tagBITMAPINFO { BITMAPINFOHEADER bmiHeader; RGBQUAD bmiColors[1]; } BITMAPINFO, *PBITMAPINFO;
|
|
« Последнее редактирование: 03-03-2014 18:36 от Вад »
|
Записан
|
|
|
|
goodking
|
|
« Ответ #27 : 04-03-2014 13:00 » |
|
Finch - bufsize= 1500000
Добавлено через 46 секунд: Вад, то есть структура и будет содержать буфер?
|
|
« Последнее редактирование: 04-03-2014 13:01 от goodking »
|
Записан
|
|
|
|
Вад
|
|
« Ответ #28 : 04-03-2014 19:20 » |
|
goodking, посмотри документацию на GetDIBits.
Это, в принципе, довольно стандартный подход для WinAPI и не только: структура, содержащая последним членом массив из 1 элемента, куда записывается блок данных переменного размера, и всё это записывается в общий динамический массив. Поэтому и памяти надо выделять на "структуру + размер блока данных - 1 элемент" (первый элемент ещё попадает в "заголовок"). Отсюда и ошибка "мало памяти": в начало, в любом случае, пишется структура-"заголовок", а данные - со смещением, и под них уже не остаётся места, если выделять памяти столько, сколько ты выделяешь. Мне, правда, непонятно, почему только на 2м изображении ошибка происходит - должна на обоих быть. Перечитал - похоже, неправ я - всё-таки, судя по документации туда просто буфер передаётся для битмапа. Тогда непонятно
|
|
« Последнее редактирование: 04-03-2014 19:34 от Вад »
|
Записан
|
|
|
|
goodking
|
|
« Ответ #29 : 05-03-2014 14:09 » |
|
Вад
Есть какие-то идеи, с чем это может быть связано?
|
|
|
Записан
|
|
|
|
|