Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Массив структур в файл, c++ 
:(
    Опции темы
LordNet
Дата 27.9.2005, 21:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 60
Регистрация: 23.3.2005

Репутация: нет
Всего: нет



Люди посоветуйти как лутчи произвести ввод/вывод массива структур в файл и из файла?
Зарание спасабо!!!
PM MAIL   Вверх
azesmcar
Дата 28.9.2005, 08:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Что то вроде этого.
Код

#include <stdio.h>

typedef struct {
  int a;
  char k;
  double v;
} my_struct;
     
void write_to_file(const char *pFileName, my_struct* slist, int nSize)
{
  FILE *fp = fopen( "structs.dat", "w" );
  fwrite( slist, nSize, sizeof( my_struct ), fp );
  fclose( fp );
}

void read_from_file( const char *pFileName, my_struct* slist, int nSize )
{
  FILE *fp = fopen( "structs.dat", "r" );
  fread( slist, nSize, sizeof( my_struct ), fp );
  fclose( fp );
}

int main()
{
  my_struct slist[10];
  write_to_file( "struct.dat", slist, 10 );
  read_from_file( "struct.dat", sl, 10 );
  return 0;
}


PM   Вверх
Denn
Дата 28.9.2005, 09:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 143
Регистрация: 6.8.2005

Репутация: нет
Всего: 2



если в структурах есть указатели, не так все просто.
PM MAIL ICQ   Вверх
azesmcar
Дата 28.9.2005, 09:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата
если в структурах есть указатели, не так все просто.


А кто говорил про указатели?
PM   Вверх
Denn
Дата 28.9.2005, 12:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 143
Регистрация: 6.8.2005

Репутация: нет
Всего: 2



это на тот случай, если у автора есть в структурах указатели, но он их не упамянул.
PM MAIL ICQ   Вверх
azesmcar
Дата 28.9.2005, 12:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата
это на тот случай, если у автора есть в структурах указатели, но он их не упамянул.


В принципе если есть указатели тогда фиг так легко отделаешся...как минимум описание структуры должно быть...универсальную функцию для этого написать будет сложновато...я бы даже сказал очень сложновато...
Добавлено @ 12:37
Надо будет пройтись по структуре, выяснить где у нее находятся динамические переменные, а где статические...а потом еще проверить а может динамическая переменная не инициализирована? а вдруг она уже удалена и программа полетит к чертовой матери...

Это не на пару строк тема...
Добавлено @ 12:40
Пока не представляю как можно выяснить что из себя представляет кусок памяти размером в 4 байта, переменную типа int или указатель...но задача интересная, можно на ней подумать...
PM   Вверх
Mayk
Дата 28.9.2005, 12:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



Цитата(azesmcar @ 28.9.2005, 16:35)

Пока не представляю как можно выяснить что из себя представляет кусок памяти размером в 4 байта, переменную типа int или указатель...но задача интересная, можно на ней подумать...

Не стоит. Элджер довольно не плохо обдумывал подобное в С++ Библиотеке программиста(оригназв "C++ for real programmers"). Что-либо утешительного Элджер не надумал.


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
azesmcar
Дата 28.9.2005, 15:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Ну почему же? можно поизвращяться...

Передать функции write_struct_to_file массив описивающий структуру...например

Код


typedef struct {
    int a;
    double t;
    char *k;
} my_struct;

my_struct obj;

obj.a = 5;
obj.t = 2.57;
strcpy( obj.k, "Hello world!!!" );

int struct_description[3][2];
struct_description[0][0] = 4; //размер первого member-а
struct_description[0][1] = 0; //тип первого member-а (0 - static, 1 - pointer)

struct_description[1][0] = 8; //размер второго member-а
struct_description[1][1] = 0; //тип второго member-а (0 - static, 1 - pointer)

struct_description[2][0] = strlen( obj.k ) ; //размер третьего member-а
struct_description[2][1] = 1; //тип третьего member-а (0 - static, 1 - pointer)



Но все равно НЕ ИНТЕРЕСНО smile
PM   Вверх
np9mi7
  Дата 30.9.2005, 01:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 553
Регистрация: 17.8.2003
Где: Volgograd, Russia

Репутация: 5
Всего: 10



Если в структуре нет указателей, то самый оптимальный (в смысле скорости) способ записи массива (линейного контейнера) - бинарный, через потоки ввода вывода;

Код

    template <class T> ostream& operator << (ostream& refStream, const vector <T>& refVector) throw ()
    {
        refStream.write (reinterpret_cast <const char*> (&refVector.front ()), refVector.size () * sizeof (T));
        //-----------------------------------------------------
        return refStream;
    }


Но тут возникает проблема считывания данных из потока (перед считыванием необходимо знать сколько объектов собираешся считать).

Вообще низкоуровневый вывод/вывод в С++ это не то, что необходимо использовать, используй все преимущества потоков ввода вывода, например:

Определи в некотором базовом классе две функции: bool ToStream (std::ostream&) const и bool FromStream (const std::istream&);, или (что более красиво), одну перегруженную функцию:

Код

struct IObject
{
    virtual bool Serialize (std::ostream&) const
    {
        assert (! "IObject not have implementation for method bool Serialize (std::ostream&) const!");
        //-----------------------------------------------------------
    }
    virtual bool Serialize (const std::istream&)
    {
        assert (! "IObject not have implementation for method bool Serialize (const std::istream&)!");
        //-----------------------------------------------------------
    }
    virtual ~IObject ()
    {
        //-----------------------------------------------------------
    }
};


Потом отнаследуй свои структуры (объекты) от данного интерфейса и реализуй его:
Код

struct Figures : public IObject
{
    float    m_flFloat;
    double    m_dbDouble;
    int        m_iInt;
    //-----------------------------------------------------------------------------------
    explicit Figures (const float flFloat = float (), const double dbDouble = double (), const int iInt = int ()) : IObject (), m_flFloat (flFloat), m_dbDouble (dbDouble), m_iInt (iInt)
    {
        //-----------------------------------------------------------
    }
    //-----------------------------------------------------------------------------------
    virtual bool Serialize (std::ostream& refOstream) const
    {
        refOstream << m_flFloat;
        //-----------------------------------------------------------
        refOstream << m_dbDouble;
        //-----------------------------------------------------------
        refOstream << m_iInt;
        //-----------------------------------------------------------
        return true;
    }
    virtual bool Serialize (const std::istream& refIstream)
    {
        refIstream >> m_flFloat;
        //-----------------------------------------------------------
        refIstream >> m_dbDouble;
        //-----------------------------------------------------------
        refIstream >> m_iInt;
        //-----------------------------------------------------------
        return true;
    }
    //-----------------------------------------------------------------------------------
};
, после всего для "полной совместимости" с потоками ввода/вывода можно добавить пару новых функций (перегруженных операторов)
Код

std::ostream& operator << (std::ostream& refStream, const IObject& refObject)
{
    refObject.Serialize (refStream);
    //---------------------------------------------------------------
    return refStream;
}
const std::istream& operator >> (const std::istream& refStream, IObject& refObject)
{
    refObject.Serialize (refStream);
    //---------------------------------------------------------------
    return refStream;
}

тебе необходимо положить линейный контейнер (массив) в поток (файл). Заполняем линейный контейнер:
Код

std::vector <Figures> vcFigures (5);                                    // в контейнере пять объектов (значения заданы конструктором по умолчанию)
std::ofstream ofStream ("figures.txt");                                                                // файл для вывода
std::copy (vcFigures.begin (), vcFigures.end (), 
    std::ostream_iterator <Figures> (ofStream, " "));                    // собственно запись в файл


При работе с объектами в С++ не используй низкоуровневый ввод/вывод - используй потоки ввода/вывода!
И забудь про массивы в С++, есть ведь линейные контейнеры!

Примечание: методы сериализации специально упрощены, необходимо добавить проверки свойства good () и.т.д.


--------------------
"Я точно знаю то, что ничего не знаю..." Сократ.
evolution project
PM MAIL WWW ICQ MSN   Вверх
Mad
Дата 30.9.2005, 01:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Эксперт
Сообщений: 656
Регистрация: 18.10.2004
Где: Одесса

Репутация: 7
Всего: 19



Цитата(np9mi7 @ 30.9.2005, 00:00)
самый оптимальный (в смысле скорости) способ записи массива (линейного контейнера) - бинарный, через потоки ввода вывода

Функции работы с потоками достаточно медленны по выполнению (в сравнении с буферизированным вводом/выводом) smile

Цитата(np9mi7 @ 30.9.2005, 00:00)
И забудь про массивы в С++, есть ведь линейные контейнеры!

опять имеем дело с потерей производительности, простой массив работает гораздо быстрей smile


а вот идея с перегрузкой довольно неплоха (причем тут можно даже с указателями справиться)
получиться примерно так :

Код

typedef struct tagSerializableStruct
{
     virtual void Save(FILE *pFile) = 0;
     virtual void Load(FILE *pFile) = 0;
} SerialazableStruct;

void LoadStructArray(FILE *pFile, SerializableStruct** pDest, int count)
{
    for(int i=0; i<count; i++)
    {
         pDest[i] = new NeedStructType;
         pDest[i]->Load(pFile);
    }
}

void SaveStructArray(FILE *pFile, SerializableStruct** pSrc, int count)
{
    for(int i=0; i<count; i++)
    {
         pDest[i]->Save(pFile);
    }
}


Правдо всеравно придеться определить все нужные типы структур smile так что это полу универсальность
В добавок можно еще перед самой структурой писать в файл ее тип (или по номеру или по имени) а при считывании проверять

Это сообщение отредактировал(а) Mad - 30.9.2005, 01:28


--------------------
user posted image
PM MAIL   Вверх
Mayk
Дата 30.9.2005, 07:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



Цитата(np9mi7 @ 30.9.2005, 05:00)
  refStream.write (reinterpret_cast <const char*> (&refVector.front ()), refVector.size () * sizeof (T));

юзать sizeof(t) не самая лучшая идея - выравнивание данных на диске нам не к чеме, ведь так? А эти #pragma... Ну вообщем имхо они не красивые.

Цитата(Mad @ 30.9.2005, 05:27)

опять имеем дело с потерей производительности, простой массив работает гораздо быстрей

Я тоже оптимизацию люблю smile
Хотя всё же vector достаточно быстр. Ну всё равно не так, как сишный. В с++ realloc нет smile

Цитата(Mad @ 30.9.2005, 05:27)
pDest[i] = new NeedStructType;
pDest[i]->Load(pFile);

Тогда уж лучше pDest[i] = NeedStructType::load(pFile);
типа виртуальный конструктор.

Цитата(Mad @ 30.9.2005, 05:27)
В добавок можно еще перед самой структурой писать в файл ее тип (или по номеру или по имени) а при считывании проверять

Можно поиграться с хэшированием(хэш ф-ция определяется опытным путем).
Код

#define hashfn(str, salt) (str[0]+salt)+(str[1]?str[1]-salt +...тд  : 0)
struct str{
    enum hash = hashfn(__FILE__, __LINE__);
};

не самый лучший вариант, но тоже вариант smile

Это сообщение отредактировал(а) Mayk - 30.9.2005, 07:19


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
np9mi7
Дата 30.9.2005, 08:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 553
Регистрация: 17.8.2003
Где: Volgograd, Russia

Репутация: 5
Всего: 10



Цитата
опять имеем дело с потерей производительности, простой массив работает гораздо быстрей
, в чем быстрее? Приведи пример.

Цитата
Функции работы с потоками достаточно медленны по выполнению (в сравнении с буферизированным вводом/выводом)
, немного тебя не понял. Приведи пример задачи на которой это реально можно ощутить...


--------------------
"Я точно знаю то, что ничего не знаю..." Сократ.
evolution project
PM MAIL WWW ICQ MSN   Вверх
Mad
Дата 30.9.2005, 09:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Эксперт
Сообщений: 656
Регистрация: 18.10.2004
Где: Одесса

Репутация: 7
Всего: 19



np9mi7
По поводу масивов и контейнеров.
Векторы - это динамические массивы и они предназначены для оптимизации использования памяти
Статические массивы - оптимизация производительности
При работе с дин. массивами добавляються дополнительные операции с перераспредилением памяти.

По поводу потоков, если ты посмотриш исходный код с++ библиотек, то увидиш, что внутри реализация сделанна через буфурные функции IO, плюс куча кода smile


--------------------
user posted image
PM MAIL   Вверх
np9mi7
Дата 30.9.2005, 11:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 553
Регистрация: 17.8.2003
Где: Volgograd, Russia

Репутация: 5
Всего: 10



Цитата
По поводу масивов и контейнеров.
Векторы - это динамические массивы и они предназначены для оптимизации использования памяти
Статические массивы - оптимизация производительности
При работе с дин. массивами добавляються дополнительные операции с перераспредилением памяти.
, Mad, это то понятно, ты пример приведи где это ощущается....????


--------------------
"Я точно знаю то, что ничего не знаю..." Сократ.
evolution project
PM MAIL WWW ICQ MSN   Вверх
Mayk
Дата 30.9.2005, 12:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



Цитата(np9mi7 @ 30.9.2005, 15:15)
Mad, это то понятно, ты пример приведи где это ощущается....????

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




--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1021 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.