C预处理器宏用于返回重复一定次数的字符串

有人知道任何C99预处理器魔法允许创建一个由另一个重复N次的字符串组成的字符串吗?

例如

STRREP( "%s ", 3 ) 

 "%s %s %s " 

经过预处理。

我能想到的唯一一件事就是这样

 #define STRREP( str, N ) STRREP_##N( str ) #define STRREP_0(str) "" #define STRREP_1(str) str #define STRREP_2(str) str str #define STRREP_3(str) str str str ... 

哪个效果很好,但是很难看,因为我必须手动为每个重复长度定义一个宏。 我想与variadic宏和宏一起使用它返回此处显示的宏参数的数量。

我的建议是使用提升。

例如

 #include  #include  #define Fold(z, n, text) text #define STRREP(str, n) BOOST_PP_REPEAT(n, Fold, str) int main(){ printf("%s\n", STRREP("%s ", 3));//STRREP("%s ", 3) -> "%s %s %s " return 0; } 

因为它是一个宏,N无论如何都是数字常量,这个怎么样?

 #include  #define REP0(X) #define REP1(X) X #define REP2(X) REP1(X) X #define REP3(X) REP2(X) X #define REP4(X) REP3(X) X #define REP5(X) REP4(X) X #define REP6(X) REP5(X) X #define REP7(X) REP6(X) X #define REP8(X) REP7(X) X #define REP9(X) REP8(X) X #define REP10(X) REP9(X) X #define REP(HUNDREDS,TENS,ONES,X) \ REP##HUNDREDS(REP10(REP10(X))) \ REP##TENS(REP10(X)) \ REP##ONES(X) int main(void) { printf(REP(9,0,7, "*")); // "*" repeated 907 times printf(REP(0,9,2, "#")); // "#" repeated 92 times printf(REP(0,0,1, "@")); // "@" repeated 1 times return 0; } 

不确定是否可以使用宏完成,但您可以使用以下function来完成:

 char *strrep(const char *str, int nrep) { if (nrep <= 0 || !str) return NULL; char *buf = malloc(strlen(str) * nrep + 1); if (!buf) return NULL; for (int i = 0; i < nrep; ++i) { strcat(buf, str); } return buf; } 

现在你可以使用它:

 char *r = strrep("%s", 3); if (r) { ... free(r); } 

UPD :如果你想避免malloc/free这是第一个代码的变种:

 /* .h */ #define STRREP_MAX_CHARS 1024 #define STRREP_INIT static char __strrep_buffer[STRREP_MAX_CHARS] #define STRREP(str, nrep) strrep(str, nrep) ? __strrep_buffer : "" char *strrep(const char *str, int nrep); /* .c */ STRREP_INIT; char *strrep(const char *str, int nrep) { if (nrep <= 0 || !str) return 0; if (strlen(str) * nrep >= STRREP_MAX_CHARS) return 0; memset(__strrep_buffer, 0, STRREP_MAX_CHARS); for (int i = 0; i < nrep; ++i) { strcat(__strrep_buffer, str); } return __strrep_buffer; } 

现在:

 printf("%s\n", STRREP("%s", 3)); 

OTOH,这看起来比第一个更丑。

我最近在__INCLUDE_LEVEL__预处理程序文字上发现了一个CPP c-preprocessor文件包含机制的递归方案,它自动处理 – 所以这个算法可能只适用于gcc?!?

  • 该算法在概念上是无限的,可以通过附加的文件间接扩展。
  • herin呈现的代码处理0-39202的ITERATION_COUNT
  • 通过ITERATION_SEPARATOR的注释/取消注释,您可以生成N个元素,或者包含N个连接的1个元素,适合字符串重复。
  • ITERATION_ELEMENT宏用作“重复元素”

您可以定期编译代码,无需任何其他定义。 代码中的宏调用是幂等的。

示例输出:

> gcc iterate.c -o iterate -Wall -s -O3 && ./iterate.exe

0-1591柜台

1592元素


iterate.c:

 #include  #include  int main(void) { const char * preproc_array[] = { #define ITERATION_COUNT 1592 //0-(199*197-1)39202 (maximum counter) #define ITERATION_SEPARATOR , //this macro, if active, determines wheather there exits N separate elements otherwise, if outcommented, just 1 element with N concatenations #define ITERATION_ELEMENT 0-__COUNTER__ Counter\n //the expanded macro as an arbitrary element #include "iterate.h" }; return !printf("%s%"PRIu32" Elements",preproc_array[ #ifndef NO_ITERATION_SEPARATOR __COUNTER__-1 #else 0 #endif ], sizeof(preproc_array)/sizeof(const char *)); } 

iterate.h:

 #define ITERATION_START 1 //start index of first inclusion #define ITERATION_LIMIT 199 //conforming to CPP preprocessor manual pg. 54 chapter 11.5, a limit of 200 is set arbitrary #define ITERATION(...) _ITERATION(__VA_ARGS__) #define _ITERATION(...) #__VA_ARGS__ ITERATION_SEPARATOR #ifndef ITERATION_SEPARATOR #define ITERATION_SEPARATOR #define NO_ITERATION_SEPARATOR #endif //here begins the recursive algorithm via preprocessor file inclusion, enable the warnings if you want to see how it loops through #if __INCLUDE_LEVEL__ <= ITERATION_COUNT/ITERATION_LIMIT //~ #warning DIV #define ITERATION_END ITERATION_COUNT/ITERATION_LIMIT+3 // + offset #include "loop.h" #define ITERATION_END ITERATION_LIMIT #include "loop.h" #include "iterate.h" #endif #if __INCLUDE_LEVEL__ == ITERATION_START //~ #warning MOD #define ITERATION_END ITERATION_COUNT%ITERATION_LIMIT+ITERATION_START #include "loop.h" #if ITERATION_COUNT % ITERATION_LIMIT #define ITERATION_END 3 // + offset #include "loop.h" #endif #endif //end of alogrithm 

loop.h:

 #if __INCLUDE_LEVEL__ < ITERATION_END #include "loop.h" ITERATION(ITERATION_ELEMENT) #undef ITERATION_END #endif