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

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: 1 2 [Все]   Вниз
  Печать  
Автор Тема: Как записать vector в файл  (Прочитано 46507 раз)
0 Пользователей и 1 Гость смотрят эту тему.
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
Помогающий

ua
Offline Offline

« Ответ #1 : 27-06-2006 20:02 » 

По моему, тут так просто не будет. Скорей всего только поелементная запись либо по индексу либо через итератор.
Записан
zz
Гость
« Ответ #2 : 27-06-2006 20:22 » 

Тогда вопрос:
А как лучше всего решать эту задачу?
Надо работать с массивом, длина которого изначально неизвестна.
Кроме того его требуется сохранять в файле / загружать из файла.
Это что же, надо как раньше, char *vect; / malloc / realloc / fread / fwrite?
Есть ли способ проще (например, в C++ есть что-нибудь для этого)?
Записан
Sands
Помогающий

ua
Offline 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
Деятель
Команда клуба

ru
Offline 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
Деятель
Команда клуба

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

« Ответ #7 : 28-06-2006 15:54 » 

Цитата: zz
IMHO делать это в цикле по одному байту - не самое оптимальное решение по скорости
Откуда такое мнение? Файловые операции уже лет 20, если не более, обычно буферизируются. Записать в файловый поток не означает вызывать движение головок диска и ожидание программы. Файловые потоки имеют манипуляторы flush (сброс буфера на диск), endl (конец строки и автоматический flush), а также сбрасывают буфера при своём закрытии. Операция << вывода в поток не является записью на диск, а является записью в буфер потока. Сброс буфера на диск реализуется как блочная операция. Если же речь идёт о современных HD, то они имеют встроенные кэши мегабайтных размеров.

Далее, исполнение операции записи outfilestream << vec может быть реализовано через перегрузку оператора << потока. Однако такая реализация внутри всё равно содержит цикл. Считать, что, если программист в своём коде видит не цикл, а  вызов фукции, такая операция быстрее явного цикла в коде - это самообман.
« Последнее редактирование: 28-06-2006 16:02 от dimka » Записан

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

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

« Ответ #8 : 28-06-2006 16:00 » 

Цитата: acc15
Я что-то не пойму...
Разве 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
Деятель
Команда клуба

ru
Offline 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
Деятель
Команда клуба

ru
Offline 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
Деятель
Команда клуба

ru
Offline 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
Деятель
Команда клуба

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

« Ответ #22 : 29-06-2006 06:36 » 

Цитата: zz
Прошу прощения, если отвлекаю вопросами не по существу - особо жестких требований к быстродействию нет.
Просто хочу, чтобы программа была написана хорошим силем, а создавать циклы там, где можно без них обойтись (тем более в ущерб производительности) - IMHO не есть хороший стиль программирования.
Так я и думал. Улыбаюсь Хороший стиль - это не писать того, чего не требуется, и писать как можно меньше кода без ущерба для архитектуры. Что же касается производительности, то существуют понятия "микрооптимизации" и "макрооптимизации". При этом многие полагают, что первое губит второе. Т.е. код, оптимизированный по скорости исполнения, становится нечитабельным и плохо модифицируемым.

100 000 int - это на 32-хбитной платформе 400 000 байт - меньше полумегабайта. Для десктопов или серверов, память которых измеряется уже гигабайтами, пытаться экономить байты - это пустая трата времени. Для других устройств полмегабайта может быть существенным размером, и там в самом деле нужна оптимизация. "Много" у разных людей имеет разное значение. У нас, например, люди системы многоканального видеонаблюдения делают, так их хоть байтовые, хоть блочные операции записи на диск не устраивают - тормозят файловые системы, поэтому работают с "сырым" диском - увеличение производительности примерно в 2-3 раза. Объёмы данных, естественно, десятки гигабайт.

Организовывать блочную запись, где размер блока подогнан под размер дискового кластера - это, конечно, увеличение быстродействия. Однако такое решение привязывает программу к конкретному диску или классу дисков. На других дисках/разделах/файловых системах эта "оптимизация" не сработает, а, может быть, даже будет источником падения производительности. Хорошее решение - это решение, универсальность или специальность которого соотнесены с задачами программы.

Цитата: zz
Вообще как-то не верится, что в 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
Деятель
Команда клуба

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

« Ответ #24 : 29-06-2006 16:21 » 

Anchorite, а более ранних? Далеко не все ещё используют GCC 3.4.2 или VC++ 2005.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Anchorite
Гость
« Ответ #25 : 30-06-2006 02:33 » 

Не могу сказать ничего определенного. Жаль
Записан
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #26 : 03-07-2006 17:50 » 

Добрый день!
Используй BOOST::SERIALIZE и будет тебе счастье. На сайте, www.boost.org есть пример с записью в файл. vectora сериализуются автоматически.
Записан

Странно всё это....
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #27 : 04-07-2006 18:42 » 

Добрый день!
Используй BOOST::SERIALIZE и будет тебе счастье. На сайте, www.boost.org есть пример с записью в файл. vectora сериализуются автоматически.
Ладно согласен фигню сморозил Улыбаюсь

проше использовать алгоритм copy получающий итераторы начала и конца вектора плюс итератор от ostream
или воспользоватся тем фактом что вектор гарантированно один не прерывный блок данных и сохранить его соотвествующем образом
Записан

Странно всё это....
LP
Помогающий

ru
Offline 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 Улыбаюсь
Просто я привел пример в общем виде, что бы было понятнее Улыбаюсь
Записан
Михалыч
Команда клуба

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

« Ответ #30 : 06-07-2006 12:21 » 

Цитата
Какие я вижу пути решения:
1. Использовать указатель char * (он же массив)
Недостаток: потребуестя периодически менять размер выделенной под него памяти, т.е. делать realloc.

2. Использовать vector
Недостаток: неудобно сохранять его в файл (надо делать цикл).

3. Искать другие пути
Пока не знаю, что: другие классы C++ или еще что-нибудь

Как-то бросилось в глаза соотношение пунктов 1 и 2... А кто сказал, что для вектора этого не понадобится? Особенно с учетом обсуждения, что vector из STL хранит данные последовательно.
Ему еще как надо будет переаллоцировать память, если в него все "не влезает". Либо резервировать опять же придется кусок неизвестного заранее (читай большого) размера Улыбаюсь
Записан

Поживем - увидим... Доживем - узнаем... Выживу - учту  Улыбаюсь
Dimka
Деятель
Команда клуба

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

« Ответ #31 : 07-07-2006 09:01 » 

Цитата: Михалыч
Ему еще как надо будет переаллоцировать память, если в него все "не влезает". Либо резервировать опять же придется кусок неизвестного заранее (читай большого) размера
Дело в том, что он это делает автоматически - не нужно реализовывать это вручную самому программисту.

И в этом противоречие: с одной стороны автор темы декларирует желание сделать оптимально по скорости и памяти, с другой - элегантно с точки зрения архитектуры. При этом из содержания задачи, как я понял, приоритет одного над другим не очевиден. Я в таких случаях выбираю элегатность кода - чтобы потом его можно было бы легко понять и модифицировать. Времена жутких дефицитов вычислительных ресурсов и замысловатых, зато оптимальных кодов "ad hoc" уже прошли - настали времена сложных программных решений, в которых главное - ясность и удобность архитектуры, максимум повторно используемого кода и минимум затрат ручного труда. Но если задача требует того, приходится иногда приносить в жертву удобство, модифицируемость и расширяемость архитектуры программы ради оптимизации по использованию ресурсов.
Записан

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

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

« Ответ #32 : 07-07-2006 12:05 » 

Цитата
Но если задача требует того, приходится иногда приносить в жертву удобство, модифицируемость и расширяемость архитектуры программы ради оптимизации по использованию ресурсов.
Мой профессиональный случай. Микроконтроллеры Улыбаюсь Для них "времена жутких дефицитов вычислительных ресурсов" не прошли пока Улыбаюсь Хотя жить стало намного проще и веселее Улыбаюсь
Не далее, как неделю назад беседовал с одним молодым специалистом. Был и долгий разговор о "вкусностях" и современностях С++. Все бы хорошо... Только он слишком безапеляционно ратовал за STL. Дал я ему для удовлетворения любопытства небольшую программу, в которой все было написано с использованием динамически выделяемых массивов. Никаких векторов, никокой STL. И попросил - на, перепиши все это, вместо массивов - вектора и списки, что тебе удобней, то и воткни...Молодец, переделал быстро и качественно. Благо не очень трудно было. Надо было видеть, насколько широко были вытаращены его глаза, когда он получил результат после компиляции Улыбаюсь Объем исполняемого кода вырос в 1,83 раза Улыбаюсь Почти в 2... Естественно, ради чистоты эксперимента в обоих случаях компилировалось все без какой-либо оптимизации. Однако, он этого не ожидал. Почему? Не знаю Улыбаюсь  На вопрос, а не хочет ли он заодно убедиться во сколько раз упадет эффективность работы программы, он ответил - я пока подумаю Улыбаюсь
Я все это к чему веду - я бы тоже с огромным удовольствием выбрал бы элегантность кода, да жизнь не позволяет иногда. Приходится сочинять собственные "элегантные" решения Улыбаюсь Это я уже к решению, которое предлагал acc15.
Записан

Поживем - увидим... Доживем - узнаем... Выживу - учту  Улыбаюсь
Dimka
Деятель
Команда клуба

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

« Ответ #33 : 07-07-2006 16:52 » 

Цитата: Михалыч
Я все это к чему веду - я бы тоже с огромным удовольствием выбрал бы элегантность кода, да жизнь не позволяет иногда. Приходится сочинять собственные "элегантные" решения
Угу. Только автор так и не сознался, какую прикладную задачу и на каком железе решает. А откуда упомянутые тобой молодые люди берутся - не знаю. Не люблю экстремизм и абсолютизм Улыбаюсь.
Записан

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

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

« Ответ #34 : 07-07-2006 18:06 » 

Кто же их любит? Улыбаюсь А молодых людей полно всяких повидалось Улыбаюсь Этот конкретный - из другого отдела, у себя таких не держим Улыбаюсь За автора не скажу, а мне зачастую приходится иметь дело с железом например таких характеристик - микроконтроллер 5066 Octagon Systems -проц. AMD 5х86/133 МГц, ОЗУ - 4 Мб, 1-2Мб бортовой флэш... Особо и не разбежишься Улыбаюсь И это еще не самый дохлый вариант Улыбаюсь
Записан

Поживем - увидим... Доживем - узнаем... Выживу - учту  Улыбаюсь
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #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)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #37 : 10-07-2006 16:54 » 

LogRus ты ошибся.
Я думаю слова Страуструпа можно считать стандартом.
Цитата
1==sizeof(char)<=sizeof(short)<=sizeof(int)<=sizeof(long)

 Улыбаюсь
можно, но специально смотрел раздел 3.9.1 так сказано что не меньше чем необходимо. и также сказано, что специфично для реализации.
НО я допускаю, что ничего не понимаю в англицком языке. Ага
Дома к сожалению нет стандарта, так-что процитировать не могу.
Записан

Странно всё это....
Dimka
Деятель
Команда клуба

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

« Ответ #38 : 10-07-2006 18:13 » 

Цитата: LogRus
Дома к сожалению нет стандарта, так-что процитировать не могу.
К сожалению, имею лишь вторую редакцию стандарта от 2003 года.
Цитата: ISO/IEC 14882:2003(E) - 3.9.1
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.
и далее
Цитата: ISO/IEC 14882:2003(E) - 3.9.1
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
Помогающий

ru
Offline 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++ » Записан

Если эта надпись уменьшается, значит ваш монитор уносят
Страниц: 1 2 [Все]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines