| 
			| 
					
						| 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   Просто я привел пример в общем виде, что бы было понятнее   |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	|  |