2015-09-23 2 views
2

Я хотел бы создать динамически в const char во время компиляции, как следующие:C препроцессор: динамический Const символ

const char reprx[] = "repr1\0repr2\0repr3\0repr4\0"; 

и с #define, чтобы указать количество времени строка reprX\0 повторяется в строке (путем замены X на значение приращения). Например, для 5:

const char reprx[] = "repr1\0repr2\0repr3\0repr4\0repr5\0"; 

Есть ли простой способ сделать это? (Без дополнительных библиотек)

+0

Что, с '# define', вы хотите указать это? неясно . – ameyCU

+0

Нет * простой * способ. Вы можете использовать библиотеку макросов предварительной обработки Boost (http://www.boost.org/doc/libs/1_59_0/libs/preprocessor/doc/), но я полагаю, что это считается «дополнительными библиотеками» – rici

+0

Dunno, если это считается «лишняя» библиотека, но m4 могла бы выполнить эту работу: http://www.gnu.org/software/m4/m4.html – Downvoter

ответ

3

Это может дать вам подсказку:

#include <stdio.h> 

#define repeat1(s) s"1\0" 
#define repeat2(s) repeat1(s)s"2\0" 
#define repeat3(s) repeat2(s)s"3\0" 
#define repeat4(s) repeat3(s)s"4\0" 
#define repeat5(s) repeat4(s)s"5\0" 
#define repeat6(s) repeat5(s)s"6\0" 
#define repeat7(s) repeat6(s)s"7\0" 
#define repeat8(s) repeat7(s)s"8\0" 
#define repeat9(s) repeat8(s)s"9\0" 

#define repeat(s, n) repeat##n(s) 

int main(void) 
{ 
    printf("%s\n", repeat("repr", 5)); 
    return 0; 
} 

Выход:

printf("%s\n", "repr""1\0""repr""2\0""repr""3\0""repr""4\0""repr""5\0"); 

Обратите внимание, что эта версия ограничена до 9 строк.

+1

Это самый простой способ. Однако мне пришлось удалить ## на каждом повторе, иначе у меня есть ошибка: не дает действительного токена предварительной обработки. (не знаю почему) Кроме того, чтобы использовать #define вместо численного значения, я определил помощника: #define REPEAT_HELPER (s, n) REPEAT ## n (s) #define REPEAT (s, n) REPEAT_HELPER (s, n). Мне бы хотелось не писать явно вложенный повтор, но кажется, что без дополнительных библиотек мы не могли бы сделать иначе. –

+0

@ dark0, вы правы, '##' необходимо удалить, отредактировано –

1

Самый простой способ сделать это - использовать специальный сценарий предварительной обработки, который вы можете интегрировать в свой процесс сборки.

Я не знаю, какие инструменты у вас есть, но вы можете легко использовать awk в качестве препроцессора. Если вы используете make, вы можете автоматически создать файл c из скелета: (смотрите ниже оригинального AWK сценария.)

file.c: file.c.in 
     awk '           \ 
     /^#define X/{        \ 
      for (i = 1; i <= $$3; ++i)     \ 
      s = s "\"repr"i"\\0\""     \ 
      }           \ 
     match($$0,/*const char \*reprx\[\] = /) { \ 
      $$0 = substr($$0, 1, RLENGTH) s ";"   \ 
     }            \ 
     1' $^ > [email protected] 

Пример:

$ cat file.c.in 
/* The beginning of the program */ 
#define X 7 
/* Some part of the program */ 
const char *reprx[] = "Will be replaced"; 
/* The rest of the program */ 

$ make -s file.c 
$ cat file.c 
/* The beginning of the program */ 
#define X 7 
/* Some part of the program */ 
const char *reprx[] = "repr1\0""repr2\0""repr3\0""repr4\0""repr5\0""repr6\0""repr7\0"; 
/* The rest of the program */ 

Поскольку немного затененная необходимостью избежать знаков доллара и окончаний линии, вот оригинальная программа awk:

awk '/^#define X/{ 
     for (i = 1; i <= $3; ++i) 
      s = s "\"repr"i"\\0\"" 
     } 
    match($0,/*const char \*reprx\[\] = /) { 
     $0 = substr($0, 1, RLENGTH) s ";" 
    } 
    1' 
+0

Спасибо за этот более продуманный способ. Его интересный я не знал awk. Но для этого требуется больше знаний, а не то, что я ищу;) –

+0

@ dark0: Это не должно быть awk, но awk - инструмент, почти всегда присутствующий даже на встроенных системах. Это помогает «make», когда вы используете внешние скрипты предварительной обработки; опять же, почти всегда есть какой-то инструмент make, а шаг предварительной обработки обычно не сложно добавить в конфигурацию сборки. Преимущество внешних препроцессоров заключается в том, что вам не нужно бороться с особенностями препроцессора C - например, вы можете делать циклы и выполнять арифметику простым способом - и у них нет ограничений, таких как «no more» чем 9 "(или 256 с boostpp). – rici

+0

Вы правы. Это самый эффективный способ сделать это. Я не знаю, как реализовать это, поскольку файлы make автоматически создаются с помощью IDE. Но я принимаю к сведению ваше решение и догадываюсь, что однажды я его буду использовать, если не сразу. –

Смежные вопросы