Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于返回重复一定次数的字符串的C预处理器宏_C_Macros_C Preprocessor - Fatal编程技术网

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

用于返回重复一定次数的字符串的C预处理器宏,c,macros,c-preprocessor,C,Macros,C Preprocessor,有人知道有哪种C99预处理器魔法允许创建一个由另一个重复N次的字符串组成的字符串吗 例如 变成 "%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 ... 这

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

例如

变成

"%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
...

这很好,但很难看,因为我必须手动为每个重复长度定义一个宏。我想将其与可变宏和返回所示宏参数数的宏一起使用。

不确定是否可以使用宏来完成,但可以使用如下函数:

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;
}
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;
}

哦,这看起来比第一个更难看。

我的建议是使用助推

例如

#包括
#包括
#定义折叠(z、n、文本)文本
#定义STRREP(str,n)BOOST\u PP\u REPEAT(n,Fold,str)
int main(){
printf(“%s\n”,STRREP(“%s”,3));//STRREP(“%s”,3)->%s%s
返回0;
}

既然它是一个宏,而N是一个数值常量,那么这个呢

#include <stdio.h>

#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;
}
#包括
#定义REP0(X)
#定义REP1(X)X
#定义REP2(X)REP1(X)X
#定义REP3(X)REP2(X)X
#定义REP4(X)REP3(X)X
#定义REP5(X)REP4(X)X
#定义REP6(X)REP5(X)X
#定义REP7(X)REP6(X)X
#定义REP8(X)REP7(X)X
#定义REP9(X)REP8(X)X
#定义REP10(X)REP9(X)X
#定义代表(百、十、一、X)\
代表数百人(代表10(代表10(X)))\
代表十(代表十(X))\
代表人(X)
内部主(空)
{
printf(REP(9,0,7,“*”);/“*”重复907次
printf(REP(0,9,2,“#”);/“#”重复92次
printf(REP(0,0,1,“@”);/“@”重复1次
返回0;
}

我最近发现了一个递归方案,在自动处理的uuu INCLUDE_uuu级预处理器文本上使用了CPP c预处理器文件包含机制,所以这个算法可能只适用于gcc

  • 该算法在概念上是无限的,可以通过附加的文件间接寻址进行扩展
  • herin提供的代码处理0-39202之间的迭代计数
  • 使用迭代分隔符的注释/取消注释,您可以 生成N个元素,或1个元素与N个串联,适合字符串重复
  • 迭代元素宏用作“重复元素”

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

示例性输出:

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

0-1591计数器

1592要素


iterate.c:

#include <stdio.h>
#include <inttypes.h>

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 *));

}
#包括
#包括
内部主(空){
常量字符*预处理数组[]={
#定义迭代计数1592//0-(199*197-1)39202(最大计数器)
#定义迭代\分隔符,//如果此宏处于活动状态,则确定是否存在N个单独的元素;否则,如果未注释,则仅存在1个包含N个串联的元素
#定义迭代\u元素0-\u计数器\u计数器\n//将展开的宏定义为任意元素
#包括“iterate.h”
};
return!printf(“%s%”PRIu32“元素”,预处理数组[
#ifndef无迭代分隔符
__计数器\uuu1
#否则
0
#恩迪夫
],sizeof(预处理数组)/sizeof(常量字符*);
}
迭代.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
#定义迭代_开始1//开始第一次包含的索引
#定义迭代限制199//符合CPP预处理器手册第54页第11.5章的规定,200的限制是任意设置的
#定义迭代(…)\u迭代(\uu VA\u ARGS\uuu)
#定义_迭代(…)35; _VA_参数_u迭代_分隔符
#ifndef迭代\u分隔符
#定义迭代分隔符
#定义无迭代分隔符
#恩迪夫
//这里通过预处理器文件包含开始递归算法,如果您想查看它是如何循环的,请启用警告

#如果包括级别,我很确定这是不可能的。请看另一个类似的问题-谢谢你,@mattjgalloway。你似乎是对的。在纯C99中,使用预处理器无法实现可变递归长度。所以我的想法似乎是唯一(丑陋的!)。@Alex,这段代码是用C编写的。使用模板(比如利用C++)不使用C。它可以使用这样的预处理器。
BOOST\u PP\u REPEAT
BOOST\u PP\u LIMIT\u REPEAT
限制设置为
256
(对于1.48)。无论如何,+1表示解决方案。谢谢补充。我想只要普通256就够了。谢谢。从原则上讲,似乎没有比我做的更干净的方法了,我将坚持使用Boost标题,因为它看起来非常优雅。@Marcus S,是的,但即使你查看Boost内部,它也是不正常的。不过,总比从头开始做要好。好主意!我会保密的。谢谢。*屏幕上到处都是呕吐物*但是它很容易使用,尽管+1当然,它可以使用函数完成,但是我希望在编译时知道字符串。
#include <stdio.h>
#include <boost/preprocessor/repetition/repeat.hpp>

#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;
}
#include <stdio.h>

#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;
}
#include <stdio.h>
#include <inttypes.h>

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 *));

}
#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
#if __INCLUDE_LEVEL__   <   ITERATION_END
#include "loop.h"
ITERATION(ITERATION_ELEMENT)
#undef ITERATION_END
#endif