Здравствуйте. Я хочу сделать в программе на С статическую табличку для бинарного поиска данных. Табличку я формирую примерно так: Код (Text): unsigned int calc_hash(char const* s) { // ... } typedef struct { unsigned int hash; void* data; } node; int main() { node table[] = { {calc_hash("abc"), "xyz"}, {..}, ..}; } Поиск будет производиться по хешам node::hash. Хеши высчитывать compile-time, я так понимаю, не получится. Чтобы была возможность производить бинарный поиск по табличке необходимо её как-то упорядочить. Строить дерево в runtime'е не очень охота, т.к. все элементы таблицы известны на этапе компиляции. Можно, конечно, в runtime создать её, упорядочить и дальше работать с ней. Но мне хочется скинуть эту работу на компилятор, чтобы он в compile-time мне всё посчитал и сформировал табличку. Один из возможных вариантов - написать соответствующий bat скрипт.. Проблема в том, что всё это будет собираться под виндой, будь линух - можно было бы perl скрипт накатать. Писать на виндовом шеле не очень-то охота.
получится, если компилятор поддерживает constexpr из стандарта C++0x... можно на темплейтах, но тогда уже нужны будут темплейты с переменным числом параметров (тоже из C++0x) и строку придется задавать посимвольно, тк строка вроде как не может быть параметром шаблона... про сортировку таблицы во времени компиляции - это сложно... можно попробовать на шаблонах сделать, но опять же без поддержки стандарта C++0x видимо не обойтись... либо делаете pre-build step, на котором формируете таблицу в си-файл, затем этот файл автоматом должен подключаться к сборке...
Програмка на языке "C". То есть нужно програмку написать, которая будет запускаться во время компиляции и генерировать, например, хидер.
сами же вгоняете себя в бессмысленные рамки) именно так... можно даже больше, написать интерпретатор своего декларированного языка, которому во время компиляции будет скармливаться файл с описанием таблицы, и уже интерпретатор будет генерировать си-файл... для этого можно использовать скажем XML-парсер (один любой из миллионов), или же написать свой парсер своего языка разметки с использованием того же GNU Bison, или Boost::Spirit, или ANTLR... в последнем кстати для целей создания собственного языка разметки есть даже целое IDE, написанное на джаве...
srm Ну почему же? Запишите табличку в виде: Код (Text): abc xyz qwe asd бла-бла-бла ... После чего напишите препроцессор таблички: Код (Text): #include <stdio.h> #include "my-hash-module.h" int main () { char name[16], value[16]; printf ("node table[] = {\n"); while (!feof (stdin)) { scanf("%s%s", name, value); printf ("{0x%x, \"%s\"},\n", calc_hash(name), value); } printf ("};\n"); return 0; } Из Makefile преобразуете табличку из исходного вида в C, складываете в файлик mytable.c. И последний штрих: в модуле main.c пишете так: Код (Text): int main () { node table[] = # include "mytable.c" ; /* ... */ } Несколько уродливо, конечно, но это, хоть и простейший, но не единственный вариант. Можно вывести табличку в виде #define MY_TABLE {...}, и использовать в main макрос. Если очень хочется, то можно написать препроцессор для C, чтобы в main писать что-то типа: Код (Text): int main () { node table[] = %%{{"key1", "value1"} {"key2", "value2"} ... }%%; } Но такой препроцессор конечно же лучше писать уже не на C, а на Perl/Python/Ruby или другом языке в котором использование регекспов легко и приятно.
Rel Нет, это, на самом то деле, демагогия. Никому ненужные теоретизирования в чисто практической задаче. Ведь как ни назови кодогенерацию, всё равно она будет происходить при выполнении команды make. И мне честно говоря без разницы, выполняется ли мною написанный код кодогенерации в контексте процесса компилятора, или форкается компилятором и выполняется как самостоятельный процесс, или форкается процессом make. Какая разница? Или вы видите какие-то принципиальные отличия, которые оправдывют неукоснительное следование терминологии, предложенной вами?
А можно ли создать статическую табличку, например, такого вида: Код (Text): static int const N = 100; static int const arr[] = {0, 1, 2, 3, ... N}; ?
вот странный человек... в чем разница между #6 и: зачем третий раз предлагать то, что уже было предложено дважды? еще чет ругается... есть решения в лоб, а есть красивые решения... разница только в этом...
В голову приходит такая идея: Код (Text): template <int i_elem> struct static_arr : static_arr<i_elem - 1> { //static int const value = i_elem; int const value; static_arr<i_elem>() : value(i_elem) {} }; template <> struct static_arr<0> { //static int const value = 0; int const value; static_arr<0>() : value(0) {} }; int main() { static static_arr<255> const arr; static_arr<0> const* p_zero = static_cast< static_arr<0> const* >(&arr); int const* p_arr = &p_zero->value; static int const val = arr.value; for (int i = 0; i < 256; ++ i) { std::cout << i << " = " << p_arr[i] << std::endl; } }
только это си плюс плюс))) но вообще это почти то, что тебе нужно.. объяви только массив в структуре и сможен не разименовывать указатели...