URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 3476
[ Назад ]

Исходное сообщение
"Combined C/C++ (STL) for novice"

Отправлено ghost , 13-Окт-04 14:57 
Помогите понять начинающему как соединить С++ и С код в одной программе?
Есть С структура базы данных:
typedef struct{unsigned int field_number;
               char *field_type;
               unsigned int record_number;
               void *record;
               unsigned int QUANT;
               ....
              }t_db;
Т.к. длинна рекордов различна, то каждый рекорд представляет собой линейный масив из всех полей типа:
[размер данных][данные], сразу в unsigned int записано длину поля, а потом само поле (длинна одного слагаемого в массивах вычисляется на основании типа поля, а количество элементов на основе длинны поля и размера его элемента).
В С++ есть библиотека STL. В исходной С программе каждый QUANT рекордов сложен в своем линейном фрагменте памяти (некий прообраз контейнеров). Для удобства доступа к рекордам в массиве указателей *record содержаться указатели на все рекорды. Я хочу создать контейнер на QUANT рекордов с помощью STL. Проблема в моем незнании С++ (я пока запустил только Helo world) и необходимости подключения многих модулей С. Для меня пока не понятно две вещи - как в обмениваться указателями между С и С++ (записать указатели на рекорды из контейнера в указатели базы) и как управлять контейнером из С функции (к примеру добавлять/удалять рекорды и поля в них)?

P.S. Замечания предложения по организации самой базы только приветствуются. Другие же реализации баз вряд ли меня заинтересуют, т.к. данная база создается не как собственно база, а как мегаобъект для подключений другим моих программ (уникальные типы полей, уникальные  алгоритмы поиска, автоматическое наполнение базы новыми полями и связями между полями, поиски корреляций и автоматическая статистическая коррекция результатов).


Содержание

Сообщения в этом обсуждении
"Combined C/C++ (STL) for novice"
Отправлено genie , 14-Окт-04 01:58 
Problem s peredachei ukazatelei ne budet - C++, kak i C ispol'zuet odin i tot zhe podhod k adresnoi arifmetike. Edinstvennoe, o chem nado pomnit' - eto to, chto operatiry new/delete ne dolzhny peresekat'sya s ispol'zovaniem _alloc/free (muhi otdel'no, kotlety otdel'no).

Kak primer ispol'zovaniya konteinera: skazhem, QUANT u tebya - eto kluch v spiske (unikal'nyi dlya prostoty). Teper' ty mozhesh ob'yavit':

#include <map>

typedef std::map<unsigned int,t_db *> MYMAP;

i gde-to v kode napisat':
MYMAP myMap;
...
MYMAP::iterator it=myMap.find(index);
if(it!=myMap.end())
   pRecord=it->second;
else
   myMap.insert(make_pair(index,pRecord));


"Combined C/C++ (STL) for novice"
Отправлено ghost , 14-Окт-04 12:54 
Спасибо genie.
Мне надо  некоторое время, что бы разобраться с Вашим кодом, если будут вопросы я задам их чуть позже. Это что бы Вы не подумали, что Ваше письмо меня не заинтересовало.

"Combined C/C++ (STL) for novice"
Отправлено SergeiZz , 14-Окт-04 11:03 
>Есть С структура базы данных:
>typedef struct{unsigned int field_number;
>            
>   char *field_type;
>            
>   unsigned int record_number;
>            
>   void *record;
>            
>   unsigned int QUANT;
>            
>   ....
>            
>  }t_db;
Это база из QUANT записей? record -- массив записей? Тогда, что такое
record_number? А field_type -- это массив симболов, или строка?

>Т.к. длинна рекордов различна, то каждый рекорд представляет собой линейный масив из
>всех полей типа:
>[размер данных][данные], сразу в unsigned int записано длину поля, а потом само
>поле (длинна одного слагаемого в массивах вычисляется на основании типа поля,
>а количество элементов на основе длинны поля и размера его элемента).
База состоит из записей. Записи разной длины. Поля записи разной длины.
Поля различаются по типу (имени). Порядок полей в записи и их состав
различен для разных записей (крутое требование). Я правильно понимаю?
Теперь, что нужно сделать? Написать базу на C++, так, чтобы с ней можно
было работать из программы на C? Или, написать базу на C, так, чтобы можно
было применять к ней алгоритмы STL?

>Для меня пока не понятно
>две вещи - как в обмениваться указателями между С и С++
>(записать указатели на рекорды из контейнера в указатели базы) и как
>управлять контейнером из С функции (к примеру добавлять/удалять рекорды и поля
>в них)?
Подобные проблемы решаются с помощью промежуточных интерфейсов (обёрток),
но, чтобы говорить конкретно, мне нужно лучше понять задачу.

>P.S. Замечания предложения по организации самой базы только >приветствуются. Другие же реализации
>баз вряд ли меня заинтересуют
В смысле, использования готовых баз, вроде PostgresSQL?


"Combined C/C++ (STL) for novice"
Отправлено ghost , 14-Окт-04 12:49 
Здравствуйте Сергей.

>Это база из QUANT записей? record -- массив записей? Тогда, что такое
>record_number? А field_type -- это массив симболов, или строка?

QUANT - это длинна (в рекордах) одного блока данных базы. К примеру, в базе record_number=100 000 рекордов и QUANT=16 000, тогда база физически будет состоять из 100 000/16 000 + 1 линейных фрагментов памяти емкостью в 16 000 рекордов каждый, причем последний будет заполнен на 16 000 - 100 000%16 000. Рабочие нагрузки базы где-то 0 - 1 000 000 рекордов.  
Зачем это надо? Ну охота попробовать С++ в деле (Вы его тоже, кстати, хвалили) и я читал, что применение линейных массивов ускоряет работу сортировщиков и надеюсь на некую экономию той же памяти.  

>База состоит из записей. Записи разной длины. Поля записи разной длины.
>Поля различаются по типу (имени). Порядок полей в записи и их состав
>различен для разных записей (крутое требование). Я правильно понимаю?
>Теперь, что нужно сделать? Написать базу на C++, так, чтобы с ней
>можно
>было работать из программы на C? Или, написать базу на C, так,
>чтобы можно
>было применять к ней алгоритмы STL?

Все так кроме:
1. Порядок полей и их количество одинаково для всех рекордов (я думаю, что такая экономия памяти не стоит затрат на обработку рекордов при поиске), просто некоторые поля имеют нулевую длину.  
2. Написать базу на С (в С++ я совсем новичок) с использованием контейнеров STL.

>Подобные проблемы решаются с помощью промежуточных интерфейсов (обёрток),
>но, чтобы говорить конкретно, мне нужно лучше понять задачу.
А напрямую совсем нельзя? STL вроде имеет свой хороший интерфейс управления, и мне представлялось, что решив проблему с взаимной передачей указателей С <-> C++ можно работать с STL напрямую...

>В смысле, использования готовых баз, вроде PostgresSQL?
Именно. Я читал статьи о форматах запросов и функциональности таких штук и пришел к выводу, что большинство функций мне не нужны, а составление запросов значительно сложнее прямой работы с полями и рекордами. Проигрывая во времени написания своей базы, я выигрываю во времени написания программ с ней работающих - а они есть основная цель.


"Combined C/C++ (STL) for novice"
Отправлено SergeiZz , 14-Окт-04 14:09 
>Рабочие нагрузки базы где-то 0
>- 1 000 000 рекордов.
Так не бывает. Это весь диапазон, а каковы среднее и стандартное
отклонение?

>я читал, что применение линейных массивов ускоряет работу
>сортировщиков и надеюсь на некую экономию той же памяти.
Ну, опять же, не само применение ускоряет, а большинство приёмов
оптимизации используют...

>1. Порядок полей и их количество одинаково для всех рекордов (я думаю,
>что такая экономия памяти не стоит затрат на обработку рекордов при
>поиске), просто некоторые поля имеют нулевую длину.
А зачем тогда тип (имя) поля? Ведь, у него уже есть порядковый номер в
записи.

>2. Написать базу на С (в С++ я совсем новичок) с использованием
>контейнеров STL.
Формулировочка занятная... Но смысл ясен. Точнее: написать базу в стиле
C, а использовать и на C++, и на C.

>>Подобные проблемы решаются с помощью промежуточных интерфейсов (обёрток),
>>но, чтобы говорить конкретно, мне нужно лучше понять задачу.
>А напрямую совсем нельзя? STL вроде имеет свой хороший интерфейс
>управления, и мне представлялось, что решив проблему с взаимной передачей
>указателей С <-> C++ можно работать с STL напрямую...
В STL можно обращаться с обычными массивами. Я был под впечатлением
требования непостоянного списка полей.
Видимо, то, что Вы называете передачей указателей, это тот факт, что
обычные указатели суть итераторы STL.
Пример промежуточного итерфейса (который я фамильярно называю здесь
обёрткой):
Допустим, мы хотим выполнить алгоритм STL для списка из первых
полей каждой записи (которые друг за другом лежат в обычном массиве);
длина записей разная, и переходя к первому полю следующей записи, нужно
сперва вычислить его местоположение. Алгоритм STL требует в качестве
аргумента диапазон (пару итераторов). Так вот, нам и нужно написать
такой класс-итератор, для которого применение операции ++, вызывает
вычисление положения следующего элемента и переход к нему. Если мы это
проделаем, то сможем обращаться с нашим хитрым списком первых полей как
с просто массивом (упрощаю терминологию).

>>В смысле, использования готовых баз, вроде PostgresSQL?
>Именно. Я читал статьи о форматах запросов и функциональности таких штук и
>пришел к выводу, что большинство функций мне не нужны, а составление
>запросов значительно сложнее прямой работы с полями и рекордами. Проигрывая во
>времени написания своей базы, я выигрываю во времени написания программ с
>ней работающих - а они есть основная цель.
На C++ и проблема упрощения процедуры составления запросов решается
применением интерфейса-адаптера, скрыващего детали составления запроса от
прикладной программы. Ага! Вот Вы и стали сталкиваться с преимуществами
ООП по сравнению со структурным подходом.


"Combined C/C++ (STL) for novice"
Отправлено ghost , 14-Окт-04 14:53 
>Так не бывает. Это весь диапазон, а каковы среднее и стандартное
>отклонение?
Норму я оцениваю в 200 000 рекордов... но диапазон 0 - 100 000 отражает лишь спектр задач, с которыми программа будет работать, меняя сами базы.

>>1. Порядок полей и их количество одинаково для всех рекордов (я думаю,
>>что такая экономия памяти не стоит затрат на обработку рекордов при
>>поиске), просто некоторые поля имеют нулевую длину.
>А зачем тогда тип (имя) поля? Ведь, у него уже есть порядковый
>номер в
>записи.
Имя поля надо для ввода/вывода данных в форматах других баз и для нужд и удобства человека. Тип поля (как и его имя) задается раз в корневой структуре базы, а не в каждом рекорде, в виде char-кода.

>В STL можно обращаться с обычными массивами. Я был под впечатлением
>требования непостоянного списка полей.
Для такого надо с каждым рекордом тягать еще массив бит(байт) для флага присутствия по числу полей и обрабатывать их на предмет присутствия в рекорде. Штука не сложная в реализации и мы выиграем 31 бит или (3 байт) на рекорд. В то же время, если поле имеет непостоянную длинну мы должны будем добавить тот же unsigned int для его размера, т.е выигрыш -1 бит (байт). А база нуждается в первую очередь в непостоянных полях (кроме разве что id) для всех рекордов. Я не думаю, что такая реализация будет подходящей.

>Видимо, то, что Вы называете передачей указателей, это тот факт, что
>обычные указатели суть итераторы STL.
>Пример промежуточного итерфейса (который я фамильярно называю здесь
>обёрткой):
>Допустим, мы хотим выполнить алгоритм STL для списка из первых
>полей каждой записи (которые друг за другом лежат в обычном массиве);
>длина записей разная, и переходя к первому полю следующей записи, нужно
>сперва вычислить его местоположение. Алгоритм STL требует в качестве
>аргумента диапазон (пару итераторов). Так вот, нам и нужно написать
>такой класс-итератор, для которого применение операции ++, вызывает
>вычисление положения следующего элемента и переход к нему. Если мы это
>проделаем, то сможем обращаться с нашим хитрым списком первых полей как
>с просто массивом (упрощаю терминологию).

Ну это очень просто, на С я это делаю так:
unsigned int get_record_lenght(unsigned int field_number,unsigned int *record)
{
unsigned int j,lenght=0;

for (j=0;j<field_number;j++)
  {
  lenght+=record[0];
  record+=record[0]+sizeof(unsigned int);
  }
return lenght;
}

>На C++ и проблема упрощения процедуры составления запросов решается
>применением интерфейса-адаптера, скрыващего детали составления запроса от
>прикладной программы. Ага! Вот Вы и стали сталкиваться с преимуществами
>ООП по сравнению со структурным подходом.
Почему тогда форумы пестрят вопросами об ошибках в запросах к монстрам баз данных?



"Combined C/C++ (STL) for novice"
Отправлено ghost , 14-Окт-04 20:57 
Совсем забыл, функция доступа к произвольному полю рекорда:

unsigned int *get_field_address(unsigned int field,unsigned int *record)
{
unsigned int j;

for (j=0;j<field;j++)    
  record+=record[0]+sizeof(unsigned int);  
return record;
}

Мы не имеем указателей на обственно поля - они не нужны. В смысле затраты памяти будут field_number*record_number*sizeof(unsigned int) против record_number*sizeof(unsigned int) за field_number суммирований для доступу к полю. Если field_number=30, record_number=200 000, то мы экономим 23Mb. Если программа работает с полем, то надо один проход для создания массива указателей на нужное поле длинной меньше 1Mb. Учитывая, что база загружаеться, учитывая запросы приложения, нужные поля можно вынести в начало рекордов и придельно минимизировать затраты на доступ к данным.


"Combined C/C++ (STL) for novice"
Отправлено SergeiZz , 15-Окт-04 12:23 
>Совсем забыл, функция доступа к произвольному полю рекорда:
>
>unsigned int *get_field_address(unsigned int field,unsigned int *record)
>{
>unsigned int j;
>
>for (j=0;j<field;j++)
>  record+=record[0]+sizeof(unsigned int);
>return record;
>}
>
>Мы не имеем указателей на обственно поля - они не нужны. В
>смысле затраты памяти будут field_number*record_number*sizeof(unsigned int) против record_number*sizeof(unsigned int) за field_number
>суммирований для доступу к полю. Если field_number=30, record_number=200 000, то мы
>экономим 23Mb. Если программа работает с полем, то надо один проход
>для создания массива указателей на нужное поле длинной меньше 1Mb. Учитывая,
>что база загружаеться, учитывая запросы приложения, нужные поля можно вынести в
>начало рекордов и придельно минимизировать затраты на доступ к данным.

Я немного другое имел в виду. Допустим есть алгоритм на последовательности
элементов, например, один из алгоритмов STL, например, тот же поиск
find(). Как его применить к последовательности первых полей записей?
Пишем функцию, которая реализует алгоритм, а место записей вычисляем так,
как Вы описали (если это типичная работа программы, то это место нужно
оптимизировать, чтобы не вычислять лишний раз местоположение). А если
алгоритм уже реализован для обыкновенного массива (упрощяю для ясности),
то как его не переписывать?, он на вход требует массив, а у нас хитрая
последовательность. И что, если нам потом потребуется тот же алгоритм, но
не на первых/энных полях, а на первом, втором, первом, втором?


"Combined C/C++ (STL) for novice"
Отправлено ghost , 15-Окт-04 13:34 
>Я немного другое имел в виду. Допустим есть алгоритм на последовательности
>элементов, например, один из алгоритмов STL, например, тот же поиск
>find(). Как его применить к последовательности первых полей записей?
>Пишем функцию, которая реализует алгоритм, а место записей вычисляем так,
>как Вы описали (если это типичная работа программы, то это место нужно
>
>оптимизировать, чтобы не вычислять лишний раз местоположение). А если
>алгоритм уже реализован для обыкновенного массива (упрощяю для ясности),
>то как его не переписывать?, он на вход требует массив, а у
>нас хитрая
>последовательность. И что, если нам потом потребуется тот же алгоритм, но
>не на первых/энных полях, а на первом, втором, первом, втором?
Не уверен, что правильно Вас понял, но если Вы имеете в виду использование встроенных в STL функций обработки массивов, то достаточно создать массив указателей на нужные поля и передать его в алгоритм. Такой прием не покатит при операциях по перемещению данных, тут надо работать исключительно с целым рекордом. Дело в том, что мои С функции рассматривают рекорд как линейную последовательность и будут вылетать в случае манипуляций с размещением фрагментов рекордов.

"Combined C/C++ (STL) for novice"
Отправлено SergeiZz , 15-Окт-04 15:23 
>Не уверен, что правильно Вас понял, но если Вы имеете в виду
>использование встроенных в STL функций обработки массивов, то достаточно создать массив
>указателей на нужные поля и передать его в алгоритм.
На создание массива уйдёт и время и место. Да и не получится с
указателями, если алгоритм обрабатывает числовую последовательность.

>Такой прием
>не покатит при операциях по перемещению данных, тут надо работать исключительно
>с целым рекордом. Дело в том, что мои С функции рассматривают
>рекорд как линейную последовательность и будут вылетать в случае манипуляций с
>размещением фрагментов рекордов.
Приём итератора-адаптера прокатит и при перемещении данных...
Я хотел привести общий и одновременно простой пример. Наверное, просто
Вам нужно подольше поработать с STL, привыкнуть мыслить в её стиле.
Я, видимо, поторопился с абстрактным примером.


"Combined C/C++ (STL) for novice"
Отправлено ghost , 15-Окт-04 15:40 
>На создание массива уйдёт и время и место. Да и не получится

>указателями, если алгоритм обрабатывает числовую последовательность.
А иначе никак - поля разной длинны, и их позиции надо рассчитывать каждый раз заново или вынести в отдельный массив указатели (значения).
Я, правда, пока не вижу подходящих алгоритмов (не относящихся к управлению памятью) в STL для работы с подобными объектами.

>Приём итератора-адаптера прокатит и при перемещении данных...
>Я хотел привести общий и одновременно простой пример. Наверное, просто
>Вам нужно подольше поработать с STL, привыкнуть мыслить в её стиле.
>Я, видимо, поторопился с абстрактным примером.
Это да, STL подключить пока не удалось :(.



"Combined C/C++ (STL) for novice"
Отправлено SergeiZz , 15-Окт-04 17:42 
>>На создание массива уйдёт и время и место. Да и не получится
>>с
>>указателями, если алгоритм обрабатывает числовую последовательность.
>А иначе никак - поля разной длинны, и их позиции надо рассчитывать
>каждый раз заново или вынести в отдельный массив указатели (значения).
О том и речь, что можно... У нас есть алгоритм, работающий только с
массивом (правильно говорить: "с диапазоном", но я упрощаю терминологию),
но у нас нет массива, а, чтобы получить новый элемент нашей
последовательности, его ещё нужно вычислить/найти, нужно ли переписывать
алгоритм? -- не нужно, мы же пишем, на C++, а не на C...
Здесь мне трудно посоветовать Вам какую-то литературу -- её видимо нет в
природе. Мне приходится по совместительству читать студенетам (это я
однажды описался, но мне понравилось это слово -- очень точное)
объектно-ориентированное программирование на 4-ом курсе физфака -- так и
пришлось самому писать "некий текст" (как я его называю), а то ведь как
им это на лекциях рассказывать -- осатанеть же можно. Если хотите почить
этот пёрл изящной словесности, то могу выслать, или весь, или выдрать
страницы про STL; он на русском (разговорном) в pdf, напишите мне на
zbl@gmail.ru -- вышлю c++guide-2.2.1.tar.bz2 227 килобайт.

>Я, правда, пока не вижу подходящих алгоритмов (не относящихся к управлению памятью)
>в STL для работы с подобными объектами.
Вся STL предназначена для работы с такими объектами... Ну сами посудите:
например, find() -- стоило бы его помещать в отдельную библиотеку, его
реализация из двух строк состоит. Ага! Второй раз Вы столкнулись с
преимуществом объектного подхода над структурным (правда STL -- не
объектно-ориентированная библиотека, в строгом смысле этого слова, но,
конечно, она предназначена для использования в объктно-ориентированных
программах).

>STL подключить пока не удалось :(.
// C++
#include <cstdlib>
#include <iostream>
#include <string>
// STL
#include <vector>
using namespace std;
int main(){
    vector<int> vi;
    for( unsigned int k= 0; k < 10; k++ ) vi.push_back( k );
    for( unsigned int k= 0; k < vi.size(); k++ )
        cout << "[" << k << "] " << vi[k] << endl;
    return EXIT_SUCCESS;
}

bash$ c++ -Wall -o helloSTL helloSTL.c++
bash$ ./helloSTL
Не проверялось.


"Combined C/C++ (STL) for novice"
Отправлено ghost , 26-Окт-04 13:16 
Здравствуйте.

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

Я переписал базу, ориентировав ее на использование контейнеров. База написана на С, и к моменту, когда вы ответите уже будет работать (я надеюсь). Я создал свой вариант контейнера (тоже на С) для хранения объектов, так что подключить STL будет легко. Сейчас я использую 3 функции для организации хранения данных в контейнере:
//This function init container
char alloc_container(unsigned int container_capacity,unsigned int max_object_lenght,float estimated_object_increasing,t_container *container);

//This function add object to container
char add_object_to_container(unsigned int object_lenght,void *object_address,t_container *container);

//This function replace record in container
char replace_object_in_container(unsigned int object_displacement,unsigned int old_object_lenght,unsigned int new_object_length,void *new_object,t_container *container);

и структуру самого контейнера (все как в STL)
//It is a container structure
typedef struct {
                unsigned int container_size;         //really used size
                unsigned int container_capacity;     //asked size of element
                unsigned int max_object_lenght;      //maximal lenght of one object in container
                unsigned int objects_number;         //number of objects in container
                float estimated_object_increasing;   //size of container grouth after its overflow
               }t_container;                         //container
Данные дописываться в конец (первый свободный байт после размера контейнера).
Я сравню скорости обоих решений (надеюсь, STL будет быстрее).

Если это не долго, то напишите как вызвать STL по шаблонам этих функций из С программы?
Я отсылал Вам 2 письма с просьбой прислать Ваши лекции на yakovenko_a@ukr.net, но ответа так и не пришло. Если не трудно, то перешлите их мне.
Заранее благодарен.


"Combined C/C++ (STL) for novice"
Отправлено SergeiZz , 27-Окт-04 10:37 
>Я создал свой вариант контейнера (тоже на С) для хранения объектов,
На сколько я вижу, лишний труд: можно было обойтись и старой реализацией базы.

>так что подключить STL будет легко. Сейчас я использую 3 функции
>для организации хранения данных в контейнере:
>и структуру самого контейнера (все как в STL)
>Я сравню скорости обоих решений (надеюсь, STL будет быстрее).
Если на C реализовать контейнеры STL, то они не будут контейнерами STL, и
сравнивать будет нечего. Если есть желание проверить эффективность
реализации STL, то лучше написать тестовую программку, решающую
простенькую задачку, на C и на STL и сравнить. Но, вообще-то, это пустое
занятие, хотя и интересное для досуга. Пустое, потому что это уже
многократно проделали сами разработчики STL.

>Если это не долго, то напишите как вызвать STL по шаблонам этих
>функций из С программы?
Вах-вах... это ни к чему совершенно.
Наверно надо задачку упростить до безобразия, а уж Вы бы потом её решение
переиначивали на свою хитробазу, а то, я гляжу, слишком много лишнего
труда получается.
Вот моя формулировка, уточните, если что не так:
Дан линейный массив целых чисел, который на самом деле есть набор записей
переменной длины; значение первого поля записи -- количество полей в ней.
int db[]= {
        5, 1, 2, 0, 0, 0,
        3, 1, 2, 0,
        4, 1, 2, 0, 0 };
Одна из задач: сложить значения первых полей каждой записи (1 + 1 + 1 == 3),
используя алгоритм acumulate() из STL.
Если формулировка Вас устраивает, то приведу решение.

>Я отсылал Вам 2 письма с просьбой прислать Ваши лекции на yakovenko_a@ukr.net,
>но ответа так и не пришло. Если не трудно, то перешлите
>их мне.
Выслал с другого ящика.


"Combined C/C++ (STL) for novice"
Отправлено ghost , 27-Окт-04 17:59 
Труд был не лишним:
1. Я понял причину организации (и стратегию реализации) некоторых типов итераторов в STL и доброй половины алгоритмов.  
2. База принципиально поменяла формат - она сможет работать и в тех случаях, когда размер базы не помещается в оперативку.
3. Уже мои контейнеры ускорили загрузку 200 000 - рекордового текстового файла (600М) где-то на 30%. Потребление памяти уменьшалось почти в 2 (!) раза (последний факт взят из системного монитора, и понять его причины я пока не могу).

Да, идея сравнения на такой простой задаче выглядит заманчиво. Разработчики, конечно, все пробовали, но мои коды далеко не так оптимальны, как код профессионалов и потому такое сравнение имеет смысл.
Только я предлагаю не читать файл, а генерировать рандомно поток данных, которые будет размещать STL и мое С решение. Тут один вопрос, эффективность моего алгоритма сильно зависит от параметра ожидаемого роста контейнера и предела его роста перед созданием нового контейнера, а как быть с STL?

За лекции большое спасибо, читаю пока с увлечением. К примеру с vim я никогда не работал, а KDeveloper есть далеко не везде.


"Combined C/C++ (STL) for novice"
Отправлено SergeiZz , 28-Окт-04 11:30 
>Труд был не лишним:
Вам виднее.

>1. Я понял причину организации (и стратегию реализации) некоторых типов итераторов в
>STL и доброй половины алгоритмов.
А как с вопросом, что такое итератор есть?

>2. База принципиально поменяла формат - она сможет работать и в тех
>случаях, когда размер базы не помещается в оперативку.
Это проблема ОС а не прикладной программы.

>Только я предлагаю не читать файл, а генерировать рандомно поток данных, которые
>будет размещать STL и мое С решение. Тут один вопрос, эффективность
>моего алгоритма сильно зависит от параметра ожидаемого роста контейнера и предела
>его роста перед созданием нового контейнера, а как быть с STL?
Не понял вопроса.

>За лекции большое спасибо, читаю пока с увлечением. К примеру с vim
>я никогда не работал, а KDeveloper есть далеко не везде.
Я сам когда-то начал с KDevelop, и считаю, что для начинающих (при
соблюдении определённых условий) лучше принять такую последовательность
изучения: gvim(emacs, nedit, cooledit,...) -> make -> autoconf -> gtdesigner -> kdevelop.


"Combined C/C++ (STL) for novice"
Отправлено ghost , 28-Окт-04 14:28 
>А как с вопросом, что такое итератор есть?
Не уверен, что в STL именно так, но похоже итератор - это такой хитрый указатель, который сам по себе ничего не значит, но позволяет получить данные, зная адрес контейнера и что-то связанное с размерами объектов.
У себя я брал за итератор функцию вычисления смещения от начала контейнера, если размеры объектов записаны в массив. Такая функция независима от указателя на контейнер и позволяет работать с объектами как обычная адресная арифметика.

>Не понял вопроса.
Похожие параметры должны быть и в STL, но какие их значения там?

Да, vim похоже достаточно удобный для работы. Ищу похожие команды и в KDeveloper. :)


"Combined C/C++ (STL) for novice"
Отправлено SergeiZz , 29-Окт-04 12:36 
>>А как с вопросом, что такое итератор есть?
>Не уверен, что в STL именно так, но похоже итератор - это
>такой хитрый указатель, который сам по себе ничего не значит, но
>позволяет получить данные, зная адрес контейнера и что-то связанное с размерами
>объектов.
>У себя я брал за итератор функцию вычисления смещения от начала контейнера,
>если размеры объектов записаны в массив. Такая функция независима от указателя
>на контейнер и позволяет работать с объектами как обычная адресная арифметика.
Есть понятие итератора вообще и итеретора STL. Так вот обычная функция не
может быть итератором STL (но может быть итератором с точки зрения другой
библиотеки).

>>Не понял вопроса.
>Похожие параметры должны быть и в STL, но какие их значения там?
С трудом понимаю вопрос. Формулируйте такие вещи как задачу: есть
контейнер, например, вектор; мы заполняем его потоком данных; количество
данных приблизительно известно; как оптимизировать использование
памяти? Ответ: воспользоватся предварительным резервированием, reserve().
Выполнение этой опереции для вектора не приведёт к немедленному
выделению памяти, но вектор будет испольрзовать полученную информацию,
так разумно, как только это удалось реализовать разработчикам STL.

>Да, vim похоже достаточно удобный для работы. Ищу похожие команды и в
>KDeveloper. :)
Когда не найдёте, имейте в виду, что vi/vim существует 30 лет. За этот
гиганский промежуток времени в нём сохранилось только то, что действительно
упрощает и ускоряет разработку. Vim понастоящему "средство быстрой
разработки". Но он имеет недостатки, главный из которых -- сложность в
изучении.


"Combined C/C++ (STL) for novice"
Отправлено ghost , 29-Окт-04 13:16 
>С трудом понимаю вопрос. Формулируйте такие вещи как задачу: есть
>контейнер, например, вектор; мы заполняем его потоком данных; количество
>данных приблизительно известно; как оптимизировать использование
>памяти? Ответ: воспользоватся предварительным резервированием, reserve().
>Выполнение этой опереции для вектора не приведёт к немедленному
>выделению памяти, но вектор будет испольрзовать полученную информацию,
>так разумно, как только это удалось реализовать разработчикам STL.

Ага, это уже интересно. Вы имеете ввиду что функция reserve() поместит контейнер не в первую попавшеюся область памяти, с подходящим размером, а в зону, где возможен некоторый рост длинны без копирования содержимого памяти? А как объяснить системе (без прямого выделения) что помещать в эту зону ничего не надо (если можно поместить куда-то еще)? Достаточно ли для этого резервировать память в конце ОЗУ (я читал, что malloc выделяет первый попавшийся достаточный фрагмент идя от начала ОЗУ до ее конца)?
Я с Вами соглашусь в другом - глупо гонятся за профессионалами. STL выглядит очень полезной и заманчивой библиотекой. Но что мне делать со своей базой? Она написана на С и уже работает. Она умеет разбивать базу на набор контейнеров и работать с ними отдельно, ее жалко выбрасывать, даже если учитывать, что переписывания на С++ уже рабочего кода не отнимет много времени. Да и процессы подключаемые к ней будут написаны на С - там очень интенсивные вычисления, но относительно небольшая длинна исходного кода + они тоже уже работают. Как совместить два хороших, родственных языка в одном приложении (хотя бы на уроне подключаемых процессов с общими полями данных)?

И еще вопрос о vim.
Он хорош, если параллельно открыто 2-3 файла, а если весь проект из 20-25 файлов, причем одновременно редактировать надо где-то половину из них. В КД есть панелька с именами файлов - просто кликнешь, а в vim есть что-то такое? (Sorry, если там все описано, а я еще просто не дочитал).
Спасибо.


"Combined C/C++ (STL) for novice"
Отправлено klalafuda , 28-Окт-04 15:33 
>Я сам когда-то начал с KDevelop, и считаю, что для начинающих (при
>соблюдении определённых условий) лучше принять такую последовательность
>изучения: gvim(emacs, nedit, cooledit,...) -> make -> autoconf -> gtdesigner -> kdevelop.

для начинающих я бы точно убрал autoconf из числа пайщиков акционеров :) для хорошо понимающего процесс программиста autoconf может сослужить хорошую службу. для всех остальных - это Смерть. равно как и для последующих пользователей криво сделанных configure.

// wbr


"Combined C/C++ (STL) for novice"
Отправлено SergeiZz , 29-Окт-04 11:26 
>>Я сам когда-то начал с KDevelop, и считаю, что для начинающих (при
>>соблюдении определённых условий) лучше принять такую последовательность
>>изучения: gvim(emacs, nedit, cooledit,...) -> make -> autoconf -> gtdesigner -> kdevelop.
>
>для начинающих я бы точно убрал autoconf из числа пайщиков акционеров :)
Соглашусь с уточнением в том смысле, что если человек не планирует делать свой код проектом open source. В противном случае ему стоит хотя бы знать, что такое autoconf, какую проблему он решает и уметь составить configure из
набора стандартных макросов, входящего в дистрибутив Red Hat. Потом,
добравщийся до решения проблем, для решения которых предназначен autoconf,
наверно, уже не начинающий, а продолжающий.

"Combined C/C++ (STL) for novice"
Отправлено klalafuda , 29-Окт-04 12:04 
>Соглашусь с уточнением в том смысле, что если человек не планирует делать
>свой код проектом open source. В противном случае ему стоит хотя
>бы знать, что такое autoconf, какую проблему он решает и уметь
>составить configure из
>набора стандартных макросов, входящего в дистрибутив Red Hat. Потом,
>добравщийся до решения проблем, для решения которых предназначен autoconf,
>наверно, уже не начинающий, а продолжающий.

согласен. я лишь имел ввиду, что для новичка autoconf - это не самое лучшее решение. тем более, что afaiu человеческой документации на autotools как не было так и нет -> "каждый пишет как он дышит" (c)..

ps: но на фоне кустарных писулек a'la configure autotools все-таки выигрывают. это конечно зло, но оно тут живет уже давно и как-то но обкатано :) взять, хотя бы, openssl.. поубывафф бы!

// wbr


"Combined C/C++ (STL) for novice"
Отправлено SergeiZz , 29-Окт-04 12:45 
>"каждый пишет как он дышит" (c)..
(c) Игорь Облаков? Или это было известно до него?

>ps: но на фоне кустарных писулек a'la configure autotools все-таки выигрывают. это
>конечно зло, но оно тут живет уже давно и как-то но
>обкатано :) взять, хотя бы, openssl.. поубывафф бы!
Я тут, как не трудно видеть, обожаю трепаться на глобальные темы. Так вот,
первый раз вижу, чтобы кто-то был согласен с утверждением: "Если живёт, то
уже достойно внимания, как бы уродливо, как бы криво не было". Удивлён.


"Combined C/C++ (STL) for novice"
Отправлено klalafuda , 29-Окт-04 13:25 
>>"каждый пишет как он дышит" (c)..
>(c) Игорь Облаков? Или это было известно до него?

afair это таки Булат Окуджава.. ;)

>>ps: но на фоне кустарных писулек a'la configure autotools все-таки выигрывают. это
>>конечно зло, но оно тут живет уже давно и как-то но
>>обкатано :) взять, хотя бы, openssl.. поубывафф бы!
>Я тут, как не трудно видеть, обожаю трепаться на глобальные темы. Так
>вот,
>первый раз вижу, чтобы кто-то был согласен с утверждением: "Если живёт, то
>уже достойно внимания, как бы уродливо, как бы криво не было". Удивлён.

ключевое слово - если действительно живет. при всех недостатках autotools (основным и главным из которых являются его горе-пользователи) он таки работает. и при грамотно написанном скрипте он работает вполне прилично. при всем прочем, autotools все-таки поддерживаются и развиваются, что весьма и весьма немаловажно. so применительно к данному продукту термин "как-то но живет" вполне употребим.

самое забавное начинается, когда вам нужно сделать cross-build какого-то пакета. скажем, с NetBSD/i386 на Linux/arm32 (Intel PXA25x). вот тут начинаются все веселости и приседания.

хороший и простой пример - thttpd. базируется на autoconf. процесс сборки банален - ставим cross-build gcc на Linux/arm32 + Linux emulation, задаем нужные кросс CC и пр. переменные окружения и запускаем родной configure. на выходе получаем рабочий Makefile, который действительно собирает проект без всяких проблем. просто прелесть!

средний пример - samba. тут все веселее бо в процессе сборки собираются служебные приложения, используемые при самой сборке. по понятным причинам configure с исправленными CC & K тут уже не прокатывает :( приходится приседать.

отвратительный пример - OpenSSL. он вообще построен на базе своего, наколеночного доморощенного движка a'la configure, который застрелиться можно заставлять использовать конкретно заданные cc, ld и пр. кросс-сборка родными средствами превращается в шаманский танец с исправлением движка, долгим и нудным тестированием и пр. хотя был бы там autoconf все могло бы быть на порядок проще.

если оценивать autoconf с точки зрения сравнения с другими подходами к управлению сборкой проекта, зачастую, все выглядит далеко не так уж и плохо :) в плане что бывает гооораздо хуже. so уж лучше все-таки какой-никакой но autoconf, чем чьи-то кривые руки.

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

// wbr


"Combined C/C++ (STL) for novice"
Отправлено ghost , 29-Окт-04 13:18 
>С трудом понимаю вопрос. Формулируйте такие вещи как задачу: есть
>контейнер, например, вектор; мы заполняем его потоком данных; количество
>данных приблизительно известно; как оптимизировать использование
>памяти? Ответ: воспользоватся предварительным резервированием, reserve().
>Выполнение этой опереции для вектора не приведёт к немедленному
>выделению памяти, но вектор будет испольрзовать полученную информацию,
>так разумно, как только это удалось реализовать разработчикам STL.

Ага, это уже интересно. Вы имеете ввиду что функция reserve() поместит контейнер не в первую попавшеюся область памяти, с подходящим размером, а в зону, где возможен некоторый рост длинны без копирования содержимого памяти? А как объяснить системе (без прямого выделения) что помещать в эту зону ничего не надо (если можно поместить куда-то еще)? Достаточно ли для этого резервировать память в конце ОЗУ (я читал, что malloc выделяет первый попавшийся достаточный фрагмент идя от начала ОЗУ до ее конца)?
Я с Вами соглашусь в другом - глупо гонятся за профессионалами. STL выглядит очень полезной и заманчивой библиотекой. Но что мне делать со своей базой? Она написана на С и уже работает. Она умеет разбивать базу на набор контейнеров и работать с ними отдельно, ее жалко выбрасывать, даже если учитывать, что переписывания на С++ уже рабочего кода не отнимет много времени. Да и процессы подключаемые к ней будут написаны на С - там очень интенсивные вычисления, но относительно небольшая длинна исходного кода + они тоже уже работают. Как совместить два хороших, родственных языка в одном приложении (хотя бы на уроне подключаемых процессов с общими полями данных)?

И еще вопрос о vim.
Он хорош, если параллельно открыто 2-3 файла, а если весь проект из 20-25 файлов, причем одновременно редактировать надо где-то половину из них. В КД есть панелька с именами файлов - просто кликнешь, а в vim есть что-то такое? (Sorry, если там все описано, а я еще просто не дочитал).


"Combined C/C++ (STL) for novice"
Отправлено SergeiZz , 29-Окт-04 16:54 
>Вы имеете ввиду что функция reserve() поместит контейнер
>не в первую попавшеюся область памяти, с подходящим размером, а в
>зону, где возможен некоторый рост длинны без копирования содержимого памяти? А
>как объяснить системе (без прямого выделения) что помещать в эту зону
>ничего не надо (если можно поместить куда-то еще)? Достаточно ли для
>этого резервировать память в конце ОЗУ (я читал, что malloc выделяет
>первый попавшийся достаточный фрагмент идя от начала ОЗУ до ее конца)?
Это всё детали реализации, на которые не стоит полягаться. Сегодня может
быть так, завтра -- иначе.

>Я с Вами соглашусь в другом - глупо гонятся за профессионалами. STL
>выглядит очень полезной и заманчивой библиотекой. Но что мне делать со
>своей базой? Она написана на С и уже работает. Она умеет
>разбивать базу на набор контейнеров и работать с ними отдельно, ее
>жалко выбрасывать, даже если учитывать, что переписывания на С++ уже рабочего
>кода не отнимет много времени. Да и процессы подключаемые к ней
>будут написаны на С - там очень интенсивные вычисления, но относительно
>небольшая длинна исходного кода + они тоже уже работают. Как совместить
>два хороших, родственных языка в одном приложении (хотя бы на уроне
>подключаемых процессов с общими полями данных)?
Вы, наверно, пролистнули одно место выше с задачей про массив из целых
чисел. Я о том и хотел поговорить: как, не переписывая базу, с ней
работать из C++ программы. Только, стоит речь вести об упрощённом
примере, а не о реальной задаче -- иначе потратим лишнее время/усилия.

>И еще вопрос о vim.
>Он хорош, если параллельно открыто 2-3 файла, а если весь проект из
>20-25 файлов, причем одновременно редактировать надо где-то половину из них. В
>КД есть панелька с именами файлов - просто кликнешь, а в
>vim есть что-то такое? (Sorry, если там все описано, а я
>еще просто не дочитал).
Здесь есть особенность vim (как и текстового интерфейса по сравнению с
графическим): не будет постоянно видно списка открытых буферов (в
Emacs видно). Конечно, есть возможность это реализовать средствами vim (он
может всё), но трудно, а главное -- не нужно. Если хотите посмотреть
список буферов, есть
:ls
Если хотите переключиться куда-то, то нужно сначала сообразить, куда, а
потом ввести команду-кондидат для автозаполнения. Например, чтобы в списке
prog1_blabla.c++ prog2_albalb.c++ prog3_ablabl.c++ ... перейти ко второй
позиции, нужно ввести
:b *2*
и нажать на Tab. Можно показать список кандидатов на автозаполнение,
быстро выбрать элемент этого списка, ну и всё-всё-всё. Только, всё-таки
это очень напрягает привыкших к граф. интерфейсу.


"Combined C/C++ (STL) for novice"
Отправлено ghost , 29-Окт-04 18:09 
>Вы, наверно, пролистнули одно место выше с задачей про массив из целых
>
>чисел. Я о том и хотел поговорить: как, не переписывая базу, с
>ней
>работать из C++ программы. Только, стоит речь вести об упрощённом
>примере, а не о реальной задаче -- иначе потратим лишнее время/усилия.

ОК, вот код С программы:
#include "container.h"

//6s of AthlonXP1700 and 150M RAM undew Windows
int main()
{
unsigned int object[11],i,count,object_lenght;
const unsigned int number[]={0,1,2,3,4,5,6,7,8,9};
t_container *container;


if (!(alloc_container(0,0.1,&container))) return FALSE;

for (count=0;count<500000;count++)
  for (i=0;i<10;)
    {
    memcpy(&object,&i,sizeof(unsigned int));
    memcpy((void*)((unsigned int)object+sizeof(unsigned int)),number,object_lenght=sizeof(unsigned int)*++i);
    if (!(add_object_to_container(object_lenght,object,&container))) goto ERROR;
    }
printf ("All %d object stored successfuly\n",count);

return TRUE;
ERROR:
printf ("Only %d object (from 500 000) stored successfuly\n",count);
return FALSE;
}


Вот container.h

#include "system.h"
//It is a container structure
typedef struct {
                unsigned int size;                   //really used size
                unsigned int capacity;               //asked size
                float estimated_object_increasing;   //number of container grouth (in parts of total objects in container) after its overflow
               }t_container;                         //container
    

//This function init container
char alloc_container(unsigned int container_capacity,float estimated_object_increasing,t_container **container);

//This function add object to container
char add_object_to_container(unsigned int object_lenght,void *object_address,t_container **container);

//This function replace record in container
char replace_object_in_container(unsigned int object_displacement,unsigned int old_object_lenght,unsigned int new_object_length,void *new_object,t_container *container);
>Здесь есть особенность vim (как и текстового интерфейса по сравнению с
>графическим): не будет постоянно видно списка открытых буферов (в
>Emacs видно). Конечно, есть возможность это реализовать средствами vim (он
>может всё), но трудно, а главное -- не нужно. Если хотите посмотреть
>
>список буферов, есть
>:ls
>Если хотите переключиться куда-то, то нужно сначала сообразить, куда, а
>потом ввести команду-кондидат для автозаполнения. Например, чтобы в списке
>prog1_blabla.c++ prog2_albalb.c++ prog3_ablabl.c++ ... перейти ко второй
>позиции, нужно ввести
>:b *2*
>и нажать на Tab. Можно показать список кандидатов на автозаполнение,
>быстро выбрать элемент этого списка, ну и всё-всё-всё. Только, всё-таки
>это очень напрягает привыкших к граф. интерфейсу.

Да есть немного - руки к мышке тянутся, но терпеть можно. Привыкаю потихоньку :).
А вот КД есть автодополнение команд (особенно для структур со множеством вложений), а vim такая функция есть?


"Combined C/C++ (STL) for novice"
Отправлено ghost , 30-Окт-04 19:51 
STL работает в 2 раза быстрее моей реализации (я правда обломился размещать свои контейнеры в "верхних слоях" памяти). Ну, еще пол секунды уйдет на копирование данных в обьект... А в STL используют realloc для перевыделения памяти или malloc-memcpy-free или что-то свое?
Вот в чем жесткий минус объектов вообще - не чувствуешь затрат как в С.
В STL несколько типов контейнеров, которые подходят по-разному для разных задач, но что стоят преобразования одного в другой и как сравнить два решения: операция в лоб с исходным типом или конвертация->оптимальная операция->конвертация.
Абсолютно реальная задача есть контейнер длинны begin-end с N объектами, нам надо увеличить размер M объекта. По определенным соображениям (затраты на разыменования к примеру) у нас основним хранилищем данных будет вектор. Есть три решения переконвертить контейнер в list, сделать копию в list или работать с вектором. Какие должны быть N, M, begin-end и сколько изменений объектов ожидать что бы выбрать тот или другой алгоритм?
Вообщем вопросов пока много, но некое представление уже есть, спасибо Сергей.

#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>

using namespace std;

//3s AthlonXP1700 and 120M memory
int main()
{
unsigned int i,count,k;
const unsigned int number[]={0,1,2,3,4,5,6,7,8,9};
vector<unsigned int>cntr;


for (count=0;count<500000;count++)
  for (i=0;i<10;i++)
    {
    cntr.push_back(i*sizeof(unsigned int));
    for (k=0;k<i+1;k++)
      cntr.push_back(number[k]);
    }
cout << "All " << count << " objects stored successfuly\n"  << endl;

return  EXIT_SUCCESS;
}


"Combined C/C++ (STL) for novice"
Отправлено SergeiZz , 02-Ноя-04 16:34 
>А в STL используют realloc для
>перевыделения памяти или malloc-memcpy-free или что-то свое?
Не интересовался, опять же потому, что это сильно зависит от реализации.
STL, кстати, позволяет подставить свой алгоритм распределения памяти
(с помощью аллокаторов).

>Вот в чем жесткий минус объектов вообще - не чувствуешь затрат как
>в С.
А вот в чём жёсткий минус C -- не чувствуешь затрат как в ассемблере...

>Абсолютно реальная задача есть контейнер длинны begin-end с N объектами, нам надо
>увеличить размер M объекта. По определенным соображениям (затраты на разыменования к
>примеру) у нас основним хранилищем данных будет вектор.
Странные соображения: во всех контейнерах STL доступ -- это разыменование
указателя. Если часто удаляем/добавляем в середину, то нужно использовать list.
Мне опять не понятно -- контейнер написан на STL, или это хитро
размеченный линейный массив, или это написанный на C контейнер STL?


"Combined C/C++ (STL) for novice"
Отправлено ghost , 02-Ноя-04 17:14 
Ну с аллокаторами я пока не хочу завязываться - чуть лучше разберусь с дефолтным STL, потом очередь дойдет и до аллокаторов.

Ну ассемблер это уже для особых случаев, а так С достаточно  оказателен в отношении затрат.

Простите за неразборчивые выражения мысли. Под  контейнерами мы будем понимать контейнеры STL. Можно работать с char вектором, запоминая где-то и в unsigned int длинны обьектов. Но задача кажеться стандартной - содержать массив обьектов произвольной длинны. Меня интересует, как заставить библиотеку работать, когда четкой параметризации шаблонов контейнеров нет.
Конкретная задача.
Поле базы несет информацию о координатах атомов. Это означает список из триплетов типа float (x,y,z). Но у разных соединений разное количество атомов и длинна списка соответственно разная. Как мне поместить координаты в контейнер, что бы операция ++ и -- передвигала итератор не на один триплет, а на столько триплетов, сколько  атомов в соединении и что бы остальные операции доступа, удаления извлечения тоже узнавали конкретный список, а не отдельный набор из трех координат.
Спасибо.