zz
Гость
|
|
« : 27-06-2006 19:51 » |
|
У меня вопрос: Всю жизнь писал на простом C (stdio, fopen, fread и т.п.), решил переходить на C++ - STL.
Имею vector <char> vect; Требуется сохранить его в файл (в любом формате, например, двоичном, чтобы можно было его потом загрузить обратно). Как это грамотно сделать? (Через ofstream или еще как-нибудь). file << vect; - не работает - пишет: 'operator<<' not implemented in type 'ofstream' for arguments of type 'vector<char,allocator<char> >'
Хотелось бы как-нибудь сделать это быстро - за одну операцию записи.
|
|
« Последнее редактирование: 06-12-2007 18:45 от Алексей1153++ »
|
Записан
|
|
|
|
Sands
Помогающий
Offline
|
|
« Ответ #1 : 27-06-2006 20:02 » |
|
По моему, тут так просто не будет. Скорей всего только поелементная запись либо по индексу либо через итератор.
|
|
|
Записан
|
|
|
|
zz
Гость
|
|
« Ответ #2 : 27-06-2006 20:22 » |
|
Тогда вопрос: А как лучше всего решать эту задачу? Надо работать с массивом, длина которого изначально неизвестна. Кроме того его требуется сохранять в файле / загружать из файла. Это что же, надо как раньше, char *vect; / malloc / realloc / fread / fwrite? Есть ли способ проще (например, в C++ есть что-нибудь для этого)?
|
|
|
Записан
|
|
|
|
Sands
Помогающий
Offline
|
|
« Ответ #3 : 27-06-2006 21:23 » |
|
Можно и как раньше, но можно и вектор использовать. А при записи можеш либо в цикле по вектору бежать vector<char> Str; .... for(int i=0;i<Str.size();i++) { file<<Str[i]; }
или можеш перед записью выделить кусок памяти по текущему размеру вектора, перегнать туда все елементы вектора, а потом через fwrite писать их в файл. P.S. По-моему ты не там пытаешся економить. Операции чтения/записи в подобного рода задачах надо делать в лоб. Хотя если кто даст метод получше буду только благодарен
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #4 : 28-06-2006 07:27 » |
|
Во-первых, malloc и free не стоит использовать - есть new и delete, которые помимо выделения памяти ещё вызывают и конструктор с деструктором.
Во-вторых, realloc тоже не надо использовать. vector имеет переменный размер в run-time, и через push_back, pop_back и другие его методы можно добавлять в него новые элементы. Соответственно, можно и удалять элементы.
В-третьих, при работе с файлами лучше использовать потоки ifstream и ofstream, работа с которыми аналогична работе с cin, cout.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
zz
Гость
|
|
« Ответ #5 : 28-06-2006 15:05 » |
|
realloc тоже не надо использовать. vector имеет переменный размер в run-time
Так я об этом и говорю, именно поэтому я и хотел использовать vector. при работе с файлами лучше использовать потоки ifstream и ofstream, работа с которыми аналогична работе с cin, cout.
В этом, собственно, и заключался первоначальный вопрос: Хотелось бы как-нибудь сделать это быстро - за одну операцию записи.
IMHO делать это в цикле по одному байту - не самое оптимальное решение по скорости
|
|
|
Записан
|
|
|
|
acc15
Гость
|
|
« Ответ #6 : 28-06-2006 15:50 » |
|
Я что-то не пойму... Разве fwrite(vect,vect.size(),0,f); не прокатит?... зачем обязательно использовать STL когда в каких то вариантах и старые добрые RTL функции намного лучше?
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #7 : 28-06-2006 15:54 » |
|
IMHO делать это в цикле по одному байту - не самое оптимальное решение по скорости Откуда такое мнение? Файловые операции уже лет 20, если не более, обычно буферизируются. Записать в файловый поток не означает вызывать движение головок диска и ожидание программы. Файловые потоки имеют манипуляторы flush (сброс буфера на диск), endl (конец строки и автоматический flush), а также сбрасывают буфера при своём закрытии. Операция << вывода в поток не является записью на диск, а является записью в буфер потока. Сброс буфера на диск реализуется как блочная операция. Если же речь идёт о современных HD, то они имеют встроенные кэши мегабайтных размеров. Далее, исполнение операции записи outfilestream << vec может быть реализовано через перегрузку оператора << потока. Однако такая реализация внутри всё равно содержит цикл. Считать, что, если программист в своём коде видит не цикл, а вызов фукции, такая операция быстрее явного цикла в коде - это самообман.
|
|
« Последнее редактирование: 28-06-2006 16:02 от dimka »
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #8 : 28-06-2006 16:00 » |
|
Я что-то не пойму... Разве fwrite(vect,vect.size(),0,f); не прокатит?... зачем обязательно использовать STL когда в каких то вариантах и старые добрые RTL функции намного лучше? Что-то я не пойму... Вы об ООП представление имеете? Вектор - это объект. Занимаемая им память не есть прямое хранилище чисел типа массива. Размер объекта vector и vector.size() - это разные количества, более того, несопоставимые. К тому же содержимое объекта не обязательно хранится как последовательный участок памяти, а может быть, например, списком адресов на внутренние объекты, расположенные в памяти где угодно.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
acc15
Гость
|
|
« Ответ #9 : 28-06-2006 16:06 » |
|
Считать, что, если программист в своём коде видит не цикл, а вызов фукции, такая операция быстрее явного цикла в коде - это самообман. Есть исключения... - memcpy,memset и т.д. и это не самообман... т.к. на ассемблере под конкретную платформу... Доли секунд, но всё же это уже не самообман. А если требуется сделать миллионы memcpy? это уже 1-2 секунды. Вектор - это объект. Занимаемая им память не есть прямое хранилище чисел типа массива. Размер объекта vector и vector.size() - это разные количества, более того, несопоставимые. К тому же содержимое объекта не обязательно хранится как последовательный участок памяти, а может быть, например, списком адресов на внутренние объекты. Это я знал когда Hello world писал. STL сам не пользуюсь, т.к. имею собств. классы для таких целей, которые сделаны т.к. мне удобнее... Поэтому такая вот ошибочка вышла =) Но вообще мне кажется что речь идет именно о массиве, а не о классе "vector". Если я не прав, то кроме как именно побайтовой записи в файл другого варианта нету, т.к. данные дефрагментированы в памяти.
|
|
« Последнее редактирование: 28-06-2006 16:16 от acc15 »
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #10 : 28-06-2006 16:17 » |
|
Есть исключения... - memcpy,memset и т.д. и это не самообман... т.к. на ассемблере под конкретную платформу... Доли секунд, но всё же это уже не самообман. А если требуется сделать миллионы memcpy? это уже 1-2 секунды. Если на уровне железа поддерживаются блочные операции, то да. Но речь идёт о вполне прикладной задаче, причём о её реализации на таком высоком уровне, что на уровне исходного кода последовательная или блочная работа железа явно не выражается, да и не должна выражаться. Специфика платформы в описании задачи не указана, следовательно, решение должно быть универсальным.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
zz
Гость
|
|
« Ответ #11 : 28-06-2006 18:17 » |
|
Что касается исходного вопроса Пока сделал так же, как и всегда (на чистом C): Вот это - в основном цикле (в принципе, одна строчка): if(vectsize%1024==0)vect=(char *)realloc(vect,vectsize+1024); // . . . vectsize++;
При этом запись в файл: if(fwrite(vect,1,vectsize,out)!=vectsize) sprintf(statemsg,"Невозможно записать в файл с именем %s",filename);
Если писать это на STL/C++ (этот код пишу из головы, но по-моему, должно быть так): if(vectsize%1024==0)vect.resize(vectsize+1024); Запись в файл (в принципе, тоже одна строчка): vector<char> Str; .... for(int i=0;i<Str.size();i++) { file<<Str[i]; }
Просто как-то возиться с realloc надоело, но получается C++ ничего более простого предложить не может Код упростился примерно настолько же, насколко и усложнился. Вопрос:Посоветуйте, можно ли как-нибудь проще - необязательно через STL. Пока думаю насчет AnsiString, но у меня, вообще говоря, двоичные данные, может быть и '\0' и вообще не знаю, поможет ли Что касается побайтовой работы с файлами:Действительно, разница не столь велика, как я думал Вот это копирует файл 700 Mb (побайтово) за 1мин 42 сек: int main(int argc, char* argv[]) { if(argc!=3)return 1; char c; ifstream i(argv[1],ios::in |ios::binary); ofstream o(argv[2],ios::out|ios::binary); while(i.get(c))o.put(c); return 0; }
А вот это - файл 696 Mb (блоками) - за 1 мин 05 сек: int main(int argc, char* argv[]) { char buf[2048]; int size; FILE *i,*o; if((i=fopen(argv[1],"rb"))==NULL)return 1; if((o=fopen(argv[2],"wb"))==NULL)return 1; while((size=fread(buf,1,2048,i))!=0)fwrite(buf,1,size,o); return 0; }
Вообще я раньше проводил подобные эксперименты (только побайтово - через fgetc/fputc) - скорость отличалась в 5-10 раз. P.S: Но основной вопрос все-таки в том, как грамотно работать с массивом (или вектором, или еще не знаю чем) и при этом легко сохранять его на диск.
|
|
« Последнее редактирование: 06-12-2007 18:46 от Алексей1153++ »
|
Записан
|
|
|
|
acc15
Гость
|
|
« Ответ #12 : 28-06-2006 18:28 » |
|
Всё же определись: с массивом или классом vector? как варианты могу предложить наследование класса vector добавив ф-ции сохранения/загрузки в/из файл(а)... А вообще смотря что тебе надо... Если нужна производительность забудь про vector...
|
|
« Последнее редактирование: 28-06-2006 18:34 от acc15 »
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #13 : 28-06-2006 18:32 » |
|
Может проще описать свою задачу, чтобы отвечающим было понятно, что вообще требуется сделать?
Как работать с векторами и потоками, уже объяснялось. А вот это стремление вставить блочные операции совершенно непонятно. В STL есть классы работы с массивами, обеспечивающие максимальную производительность за счёт снижения удобства работы с ними. Но всякий класс надлежит применять в соответствии с решаемой задачей. Задача же в данном случае неопределена.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
zz
Гость
|
|
« Ответ #14 : 28-06-2006 19:03 » |
|
Прошу прощения, по ходу обсуждения вопрос немного переформулировался: Задача: Хранить большое количество (изначально неизвестное) чисел (в диапазоне от -128 до 127), которые поступают в процессе работы программы. При этом необходимо иметь произвольный доступ к каждому прочитанному ранее числу. Кроме того, необходимо в некоторый момент записать все эти числа в файл. А в некоторый другой момент - прочитать из файла.
Какие я вижу пути решения: 1. Использовать указатель char * (он же массив) Недостаток: потребуестя периодически менять размер выделенной под него памяти, т.е. делать realloc.
2. Использовать vector Недостаток: неудобно сохранять его в файл (надо делать цикл).
3. Искать другие пути Пока не знаю, что: другие классы C++ или еще что-нибудь
Вопрос: Какой из вариантов на Ваш взгляд кажется лучше, что можно сделать с недостатками (в п. 1, 2), или какие Вы видите другие пути?
|
|
|
Записан
|
|
|
|
acc15
Гость
|
|
« Ответ #15 : 28-06-2006 20:09 » |
|
Моё решение. Работай как с обычным массивом. Для изменения длины - SetLength (GetLength - понятно для чего) Возможно аналог данного класса есть и в стандартных библиотеках, но увы... на поиск и изучение работы с ним уйдет больше времени чем сделать свой... template <class T> class c_Array { protected: T *pPtr; unsigned long nCount; void Initialize() { pPtr = 0; nCount = 0; } public: c_Array() { Initialize(); } c_Array(unsigned long nCount) { Initialize(); SetLength(nCount); } c_Array(const c_Array &arr) { Initialize(); Copy(arr); } ~c_Array() { SetLength(0); } bool SetLength(unsigned long nNewCount,bool bDoResize = true) { if (nCount == nNewCount) return true; if (nNewCount == 0) { if (pPtr) { delete [] pPtr; pPtr = 0; } } else { if (pPtr) { T* pNewPtr = new T[nNewCount]; if (!pNewPtr) return false; if (bDoResize) for (unsigned long i=0;i<nCount && i<nNewCount;i++) pNewPtr[i] = pPtr[i]; pPtr = pNewPtr;
} else {
pPtr = new T[nNewCount]; if (!pPtr) return false;
} } nCount = nNewCount; return true; } unsigned long GetLength(void) { return nCount; } bool Add(T& item) { if (!SetLength(nCount+1)) return false; pPtr[nCount-1] = item; return true; } bool Insert(unsigned long nPos,const T& item) { if (nPos > GetLength()) return false; T* pNewPtr = new T[nCount+1]; if (!pNewPtr) return false; unsigned long i; for (i=0;i<nPos;i++) pNewPtr[i] = pPtr[i]; pNewPtr[nPos] = item; for (i=nPos+1;i<nCount+1;i++) pNewPtr[i] = pPtr[i-1]; if (pPtr) delete [] pPtr; pPtr = pNewPtr; nCount++; return true; } bool Remove(const unsigned long index) { if (index >= nCount) return false; if (nCount > 1) { T* pNewPtr = new T[nCount-1]; unsigned long i; for (i=0;i<index;i++) pNewPtr[i] = pPtr[i]; for (i=index+1;i<nCount;i++) pNewPtr[i-1] = pPtr[i]; delete [] pPtr; pPtr = pNewPtr; nCount--; return true; } else return SetLength(0,false); } bool CopyFrom(const T* source,const unsigned long count) { if (!source || !count) return false; for (unsigned long i=0;i<min(nCount,count);i++) pPtr[i] = source[i]; return true; } bool CopyTo(T* dest) const { if (!dest) return false; for (unsigned long i=0;i<nCount;i++) dest[i] = pPtr[i]; return true; }
void SetAll(const T& item) { for (unsigned long i=0;i<nCount;i++) pPtr[i] = item; } bool Set(const unsigned long index,const T& item) { if (index>=nCount) return false;
pPtr[index] = item; return true; } const T& Get(unsigned long index) const { if (index>=nCount) return pPtr[0];
return pPtr[i]; } bool Copy(const c_Array& x) { if (!SetLength(x.nCount,false)) return false; if (!CopyFrom(x.pPtr,x.nCount)) return false; return true; } operator T*() { return pPtr; } c_Array& operator=(const c_Array& x) { Copy(x); return *this; } };
т.е. пример который тебя конкретно интересует: запись: c_Array <char> abc(10); // 10 - размер изначально
abc.Add('X'); abc.Add('Y'); abc.Add('Z'); fwrite(abc,sizeof(char),abc.GetLength(),file);
или по другому ЗЫ: лучше используй что было раньше =) abc.SetLength(abc.GetLength()+1); abc[abc.GetLength()-1] = 'X'; abc.SetLength(abc.GetLength()+1); abc[abc.GetLength()-1] = 'Y'; abc.SetLength(abc.GetLength()+1); abc[abc.GetLength()-1] = 'Z'; fwrite(abc,sizeof(char),abc.GetLength(),file); чтение: abc.SetLength(размер который нужен, к примеру размер файла); fread(abc,sizeof(char),abc.GetLength(),file); Или другой вариант - наследование этого же класса: template <class T> class c_FileArray : public c_Array <T> {
public: long WriteToFile(FILE *f) { return fwrite(pPtr,sizeof(T),nCount,f); } long ReadFromFile(FILE *f) { return fread(pPtr,sizeof(T),nCount,f); } };
дальнейшее использование: запись: c_FileArray <char> farray; ... farray.Add('x'); farray.Add('y'); farray.Add('z'); // Добавляем некоторое количество... farray.WriteToFile(file); // записываем в файл ...
чтение: ... c_FileArray <char> farray;
farray.SetLength(кол-во элементов которое нужно будет считать из файла); farray.ReadFromFile(file); ...
или можно сделать операторами, тогда использовать можно именно так как ты хотел изначально: template <class T> class c_FileArray : public c_Array <T> {
public: long operator>>(FILE *f) { return fwrite(pPtr,sizeof(T),nCount,f); } long operator<<(FILE *f) { return fread(pPtr,sizeof(T),nCount,f); } };
т.е. дальше можно так: abc >> file; // запись abc << file; // чтение
и без i(o)fstream ов =) Вот собственно и всё...
|
|
« Последнее редактирование: 06-12-2007 18:47 от Алексей1153++ »
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #16 : 28-06-2006 21:07 » |
|
zz, Каковы требования к быстродействию? Что значит "большое количество"? Какое максимально допустимое значение? acc15, есть такое понятие, как повторное использование кода. Собственно поэтому STL предпочтительнее самописных решений. Объяснять почему - не в этой теме.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
acc15
Гость
|
|
« Ответ #17 : 28-06-2006 21:13 » |
|
интересно почему же они забыли про >> и << для файлов? =) найди ка мне такой вариант в твоём любимом STL
|
|
|
Записан
|
|
|
|
zz
Гость
|
|
« Ответ #18 : 28-06-2006 22:10 » |
|
acc15, Спасибо за код, однако думаю, что fwrite работать не будет по той же причине: Вектор - это объект. Занимаемая им память не есть прямое хранилище чисел типа массива. Размер объекта vector и vector.size() - это разные количества, более того, несопоставимые. К тому же содержимое объекта не обязательно хранится как последовательный участок памяти, а может быть, например, списком адресов на внутренние объекты, расположенные в памяти где угодно.
Т.к. pPtr - это указатель. Хотя, конечно, перегрузить операторы <<, >> для обращения к pPtr - проблем нет. dimka, Прошу прощения, если отвлекаю вопросами не по существу - особо жестких требований к быстродействию нет. Просто хочу, чтобы программа была написана хорошим силем, а создавать циклы там, где можно без них обойтись (тем более в ущерб производительности) - IMHO не есть хороший стиль программирования. Ориентировочно (с большим запасом) максимально допустимое количество - 100 000. Во всяком случае - точно в пределах разрядности int. Хотя, конечно, проще всего было бы написать: char vector[100000]; и не напрягаться, но это IMHO тоже не есть хороший стиль программирования. Вообще как-то не верится, что в C++ нет стандартных (или почти стандартных) средств для подобных задач - вроде бы, задача довольно естественная
|
|
|
Записан
|
|
|
|
acc15
Гость
|
|
« Ответ #19 : 28-06-2006 22:26 » |
|
zz, а может стоит попробовать ? =) Вдруг случайно заработает... так невзначай =) И я в примере не vector наследовал, так что он тут вообще не причем... читай внимательнее... pPtr указатель именно на массив а не вектор и данные массива идут в памяти последовательно...
Стандартных средств лично я не знаю... Но не проще ли написать своё раз и навсегда?
|
|
« Последнее редактирование: 28-06-2006 22:33 от acc15 »
|
Записан
|
|
|
|
zz
Гость
|
|
« Ответ #20 : 28-06-2006 23:08 » |
|
acc15, извинения, я был неправ Действительно, здесь: " fwrite(abc,sizeof(char),abc.GetLength(),file);" вызывается " operator T*()", который возвращает pPtr; А не работало бы это (вернее, не так работало) в случае " fwrite(&abc,sizeof(char),abc.GetLength(),file);"
|
|
|
Записан
|
|
|
|
Anchorite
Гость
|
|
« Ответ #21 : 29-06-2006 02:40 » |
|
Ну вы, блин, даете. Пример для вестора из char. // Пишем file.write(&vect[0], sizeof(char) * vect.size());
// Читаем (vectSize - число элементов читаемых из потока) vect.resize(vectSize); file.read(&vect[0], sizeof(char) * vectSize)
Но сразу же предупрежу - данный способ работает только для встроенных типов. Для каких-то самописных классов он не пойдет.
|
|
« Последнее редактирование: 29-06-2006 02:41 от Anchorite »
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #22 : 29-06-2006 06:36 » |
|
Прошу прощения, если отвлекаю вопросами не по существу - особо жестких требований к быстродействию нет. Просто хочу, чтобы программа была написана хорошим силем, а создавать циклы там, где можно без них обойтись (тем более в ущерб производительности) - IMHO не есть хороший стиль программирования. Так я и думал. Хороший стиль - это не писать того, чего не требуется, и писать как можно меньше кода без ущерба для архитектуры. Что же касается производительности, то существуют понятия "микрооптимизации" и "макрооптимизации". При этом многие полагают, что первое губит второе. Т.е. код, оптимизированный по скорости исполнения, становится нечитабельным и плохо модифицируемым. 100 000 int - это на 32-хбитной платформе 400 000 байт - меньше полумегабайта. Для десктопов или серверов, память которых измеряется уже гигабайтами, пытаться экономить байты - это пустая трата времени. Для других устройств полмегабайта может быть существенным размером, и там в самом деле нужна оптимизация. "Много" у разных людей имеет разное значение. У нас, например, люди системы многоканального видеонаблюдения делают, так их хоть байтовые, хоть блочные операции записи на диск не устраивают - тормозят файловые системы, поэтому работают с "сырым" диском - увеличение производительности примерно в 2-3 раза. Объёмы данных, естественно, десятки гигабайт. Организовывать блочную запись, где размер блока подогнан под размер дискового кластера - это, конечно, увеличение быстродействия. Однако такое решение привязывает программу к конкретному диску или классу дисков. На других дисках/разделах/файловых системах эта "оптимизация" не сработает, а, может быть, даже будет источником падения производительности. Хорошее решение - это решение, универсальность или специальность которого соотнесены с задачами программы. Вообще как-то не верится, что в C++ нет стандартных (или почти стандартных) средств для подобных задач - вроде бы, задача довольно естественная. В общем случае задача сериализации объектов не так тривиальна, как может казаться. Anchorite, да, где-то уже обсуждался вопрос о том, что vector из STL хранит данные последовательно. Правда, из того обсуждения я так и не понял, является ли это требованием стандарта или особенностью компиляторов на распространённых платформах. Поэтому я на всякий случай подобных решений не предлагаю. Пример из MSDN: // ios_streamsize.cpp // compile with: /EHsc #include <iostream> #include <fstream>
int main( ) { using namespace std; char a[16] = "any such text"; ofstream x( "test.txt" ); streamsize y = 6; x.write( a, y ); }
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Anchorite
Гость
|
|
« Ответ #23 : 29-06-2006 15:31 » |
|
Anchorite, да, где-то уже обсуждался вопрос о том, что vector из STL хранит данные последовательно. Правда, из того обсуждения я так и не понял, является ли это требованием стандарта или особенностью компиляторов на распространённых платформах. Поэтому я на всякий случай подобных решений не предлагаю. Это требование стандарта ISO/IEC 14882 Second edition 2003-10-15. Все компиляторы, с которыми я на настоящий момент работаю (MinGW GCC 3.4.2 и MSVS .NET 2005) ему соответствуют.
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #24 : 29-06-2006 16:21 » |
|
Anchorite, а более ранних? Далеко не все ещё используют GCC 3.4.2 или VC++ 2005.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Anchorite
Гость
|
|
« Ответ #25 : 30-06-2006 02:33 » |
|
Не могу сказать ничего определенного.
|
|
|
Записан
|
|
|
|
Антон (LogRus)
|
|
« Ответ #26 : 03-07-2006 17:50 » |
|
Добрый день! Используй BOOST::SERIALIZE и будет тебе счастье. На сайте, www.boost.org есть пример с записью в файл. vectora сериализуются автоматически.
|
|
|
Записан
|
Странно всё это....
|
|
|
Антон (LogRus)
|
|
« Ответ #27 : 04-07-2006 18:42 » |
|
Добрый день! Используй BOOST::SERIALIZE и будет тебе счастье. На сайте, www.boost.org есть пример с записью в файл. vectora сериализуются автоматически. Ладно согласен фигню сморозил проше использовать алгоритм copy получающий итераторы начала и конца вектора плюс итератор от ostream или воспользоватся тем фактом что вектор гарантированно один не прерывный блок данных и сохранить его соотвествующем образом
|
|
|
Записан
|
Странно всё это....
|
|
|
LP
Помогающий
Offline
|
|
« Ответ #28 : 04-07-2006 19:58 » |
|
проше использовать алгоритм copy получающий итераторы начала и конца вектора плюс итератор от ostream
Я тоже за этот вариант. void serialize(const std::string& filename, const std::vector<int>& vec) { std::ofstream file(filename.c_str()); std::ostream_iterator<int> beg(file, " "); std::copy(vec.begin(), vec.end(), beg); }
void deserialize(const std::string& filename, std::vector<int>& vec) { std::ifstream file(filename.c_str()); std::istream_iterator<int> beg(file), end; std::copy(beg, end, std::back_inserter(vec)); }
Anchorite, а более ранних? Далеко не все ещё используют GCC 3.4.2 или VC++ 2005.
Можно установить STL поновее. PS Кстати, Anchorite, sizeof(char) всегда 1.
|
|
|
Записан
|
Если эта надпись уменьшается, значит ваш монитор уносят
|
|
|
Anchorite
Гость
|
|
« Ответ #29 : 05-07-2006 02:27 » |
|
PS Кстати, Anchorite, sizeof(char) всегда 1. Конечно 1 Просто я привел пример в общем виде, что бы было понятнее
|
|
|
Записан
|
|
|
|
Михалыч
|
|
« Ответ #30 : 06-07-2006 12:21 » |
|
Какие я вижу пути решения: 1. Использовать указатель char * (он же массив) Недостаток: потребуестя периодически менять размер выделенной под него памяти, т.е. делать realloc.
2. Использовать vector Недостаток: неудобно сохранять его в файл (надо делать цикл).
3. Искать другие пути Пока не знаю, что: другие классы C++ или еще что-нибудь Как-то бросилось в глаза соотношение пунктов 1 и 2... А кто сказал, что для вектора этого не понадобится? Особенно с учетом обсуждения, что vector из STL хранит данные последовательно. Ему еще как надо будет переаллоцировать память, если в него все "не влезает". Либо резервировать опять же придется кусок неизвестного заранее (читай большого) размера
|
|
|
Записан
|
Поживем - увидим... Доживем - узнаем... Выживу - учту
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #31 : 07-07-2006 09:01 » |
|
Ему еще как надо будет переаллоцировать память, если в него все "не влезает". Либо резервировать опять же придется кусок неизвестного заранее (читай большого) размера Дело в том, что он это делает автоматически - не нужно реализовывать это вручную самому программисту. И в этом противоречие: с одной стороны автор темы декларирует желание сделать оптимально по скорости и памяти, с другой - элегантно с точки зрения архитектуры. При этом из содержания задачи, как я понял, приоритет одного над другим не очевиден. Я в таких случаях выбираю элегатность кода - чтобы потом его можно было бы легко понять и модифицировать. Времена жутких дефицитов вычислительных ресурсов и замысловатых, зато оптимальных кодов "ad hoc" уже прошли - настали времена сложных программных решений, в которых главное - ясность и удобность архитектуры, максимум повторно используемого кода и минимум затрат ручного труда. Но если задача требует того, приходится иногда приносить в жертву удобство, модифицируемость и расширяемость архитектуры программы ради оптимизации по использованию ресурсов.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Михалыч
|
|
« Ответ #32 : 07-07-2006 12:05 » |
|
Но если задача требует того, приходится иногда приносить в жертву удобство, модифицируемость и расширяемость архитектуры программы ради оптимизации по использованию ресурсов. Мой профессиональный случай. Микроконтроллеры Для них "времена жутких дефицитов вычислительных ресурсов" не прошли пока Хотя жить стало намного проще и веселее Не далее, как неделю назад беседовал с одним молодым специалистом. Был и долгий разговор о "вкусностях" и современностях С++. Все бы хорошо... Только он слишком безапеляционно ратовал за STL. Дал я ему для удовлетворения любопытства небольшую программу, в которой все было написано с использованием динамически выделяемых массивов. Никаких векторов, никокой STL. И попросил - на, перепиши все это, вместо массивов - вектора и списки, что тебе удобней, то и воткни...Молодец, переделал быстро и качественно. Благо не очень трудно было. Надо было видеть, насколько широко были вытаращены его глаза, когда он получил результат после компиляции Объем исполняемого кода вырос в 1,83 раза Почти в 2... Естественно, ради чистоты эксперимента в обоих случаях компилировалось все без какой-либо оптимизации. Однако, он этого не ожидал. Почему? Не знаю На вопрос, а не хочет ли он заодно убедиться во сколько раз упадет эффективность работы программы, он ответил - я пока подумаю Я все это к чему веду - я бы тоже с огромным удовольствием выбрал бы элегантность кода, да жизнь не позволяет иногда. Приходится сочинять собственные "элегантные" решения Это я уже к решению, которое предлагал acc15.
|
|
|
Записан
|
Поживем - увидим... Доживем - узнаем... Выживу - учту
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #33 : 07-07-2006 16:52 » |
|
Я все это к чему веду - я бы тоже с огромным удовольствием выбрал бы элегантность кода, да жизнь не позволяет иногда. Приходится сочинять собственные "элегантные" решения Угу. Только автор так и не сознался, какую прикладную задачу и на каком железе решает. А откуда упомянутые тобой молодые люди берутся - не знаю. Не люблю экстремизм и абсолютизм .
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Михалыч
|
|
« Ответ #34 : 07-07-2006 18:06 » |
|
Кто же их любит? А молодых людей полно всяких повидалось Этот конкретный - из другого отдела, у себя таких не держим За автора не скажу, а мне зачастую приходится иметь дело с железом например таких характеристик - микроконтроллер 5066 Octagon Systems -проц. AMD 5х86/133 МГц, ОЗУ - 4 Мб, 1-2Мб бортовой флэш... Особо и не разбежишься И это еще не самый дохлый вариант
|
|
|
Записан
|
Поживем - увидим... Доживем - узнаем... Выживу - учту
|
|
|
Антон (LogRus)
|
|
« Ответ #35 : 08-07-2006 06:28 » |
|
PS Кстати, Anchorite, sizeof(char) всегда 1. Конечно 1 Просто я привел пример в общем виде, что бы было понятнее sizeof(char) не всегда 1, он не меньше одного, это явно описано в стандарте, сказано что он достаточне для хранения минимального набора символов
|
|
|
Записан
|
Странно всё это....
|
|
|
acc15
Гость
|
|
« Ответ #36 : 10-07-2006 15:01 » |
|
LogRus ты ошибся. Я думаю слова Страуструпа можно считать стандартом. 1==sizeof(char)<=sizeof(short)<=sizeof(int)<=sizeof(long)
|
|
« Последнее редактирование: 10-07-2006 15:03 от acc15 »
|
Записан
|
|
|
|
Антон (LogRus)
|
|
« Ответ #37 : 10-07-2006 16:54 » |
|
LogRus ты ошибся. Я думаю слова Страуструпа можно считать стандартом. 1==sizeof(char)<=sizeof(short)<=sizeof(int)<=sizeof(long) можно, но специально смотрел раздел 3.9.1 так сказано что не меньше чем необходимо. и также сказано, что специфично для реализации. НО я допускаю, что ничего не понимаю в англицком языке. Дома к сожалению нет стандарта, так-что процитировать не могу.
|
|
|
Записан
|
Странно всё это....
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #38 : 10-07-2006 18:13 » |
|
Дома к сожалению нет стандарта, так-что процитировать не могу. К сожалению, имею лишь вторую редакцию стандарта от 2003 года. Objects declared as characters (char) shall be large enough to store any member of the implementation's basic character set. If a character from this set is stored in a character object, the integral value of the character object is equal to the value of the single character literal form of that character. It is implementation-defined whether a char object can hold negative values. и далее There are four signed integer types: "signed char", "short int", "int", and "long int." In this list, each type provides at least as much storage as those preceding it in the list. Plain ints have the natural size suggested by the architecture of the execution environment; the other signed integer types are provided to meet special needs. Если опечаток не сделал - так. Таким образом, вышеприведённое неравенство от луквого, т.е. Страуструпа. Ему никто не мешает иметь частное мнение, но компиляторы создаются согласно стандарту.
|
|
« Последнее редактирование: 06-12-2007 18:48 от Алексей1153++ »
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
LP
Помогающий
Offline
|
|
« Ответ #39 : 12-07-2006 08:21 » |
|
LogRus, смотри параграф 5.3.3/1 sizeof(char), sizeof(signed char) and sizeof(unsigned char) are 1; the result of sizeof applied to any other fundamental type (3.9.1) is implementation-defined. Насколько я знаю, по отношению к char, implementation-defined количество бит. Т.е. оно может быть 8, 9 и более. Думаю, именно это и имелось в виду в 3.9.1., но в любом случае sizeof char'a всегда 1.
|
|
« Последнее редактирование: 06-12-2007 18:49 от Алексей1153++ »
|
Записан
|
Если эта надпись уменьшается, значит ваш монитор уносят
|
|
|
|