在宏中用下划线替换空格?

ein*_*ica 6 macros c-preprocessor

我可以编写一个单参数宏,它采用由空格分隔的单词/标记序列,并生成相同的序列,但每个单词/标记之间有下划线?

例如

MAGIC_MACRO(brave new  world)
Run Code Online (Sandbox Code Playgroud)

将评估为

brave_new_world
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 我不介意每个空白字符是否变成下划线,只是至少使用一个。
  • 如果我不能做到这一点,我至少想知道这是否可以用两个词来实现。

Kam*_*Cuk 1

我可以编写一个单参数宏,它采用由空格分隔的单词/标记序列,并生成相同的序列,但每个单词/标记之间有下划线?

当然,这是不可能的。预处理器中没有字符串操作实用程序。

哦,我在开玩笑呢。首先,你必须建立一个包含所有可能的单词组合的字典。为此,我们将有一本包含几个单词的小词典:

#define WORD_world  world,
#define WORD_new    new,
// etc.
Run Code Online (Sandbox Code Playgroud)

你可能会得到这个模式。然后让我们实现将执行以下操作的宏:

brave new  world                 // our starting argument
WORD_##brave new world           // add WORD_ to all arguments and join arguments with spaces
WORD_brave new world
brave, new world                 // expand WORD_brave macro
WORD_brave WORD_new world        // add WORD_ to all arguments and join arguments with spaces
brave, new, world                // expand WORD_* macros
WORD_brave WORD_new WORD_world   // add WORD_ to all arguments and join arguments with spaces
brave, new, world,               // expand WORD_* macros
     /* --- repeat above steps up to maximum words you need to handle --- */
brave_new_world                  // join arguments with `_` ignoring last empty one
Run Code Online (Sandbox Code Playgroud)

下面的代码:

// our dictionary
#define WORD_world  world,
#define WORD_new    new,
#define WORD_brave  brave,
#define WORD_hello  hello,
#define WORD_Hello  Hello,

// the classics
#define COMMA(...)  ,
#define FIRST(a, ...)  a

// apply function f for each argument recursively with tail
#define FOREACHTAIL_1(f,a)      f(a,)
#define FOREACHTAIL_2(f,a,...)  f(a,FOREACHTAIL_1(f,__VA_ARGS__)) 
#define FOREACHTAIL_3(f,a,...)  f(a,FOREACHTAIL_2(f,__VA_ARGS__)) 
#define FOREACHTAIL_4(f,a,...)  f(a,FOREACHTAIL_3(f,__VA_ARGS__)) 
#define FOREACHTAIL_N(_4,_3,_2,_1,N,...)  \
        FOREACHTAIL_##N
#define FOREACHTAIL(f,...) \
        FOREACHTAIL_N(__VA_ARGS__,4,3,2,1)(f,__VA_ARGS__)

// if there are two arguments, expand to true. Otherwise false.
#define IFTWO_N(_0,_1,N,...)     N
#define IFTWO(true, false, ...)  IFTWO_N(__VA_ARGS__, true, false)

// If empty, expand to true, otherwise false.
// https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/
#define IFEMPTY(true, false, ...)  IFTWO(true, false, COMMA __VA_ARGS__ ())

// Join arguments with `_`.
#define JOIN_U(a, b)      a##_##b
#define JOIN_TWO_IN(a,b)  IFEMPTY(FIRST, JOIN_U, b)(a, b)
#define JOIN_TWO(a,b)     JOIN_TWO_IN(a,b)
#define JOIN(...)         FOREACHTAIL(JOIN_TWO, __VA_ARGS__)

// Append WORD_ to each argument and join arguments with spaces.
#define WORD_             /* the last one expands to empty */
#define WORDS_TWO(a, b)   WORD_##a b
#define WORDS(...)        FOREACHTAIL(WORDS_TWO, __VA_ARGS__)

#define MAGIC_MACRO(a)  JOIN(WORDS(WORDS(WORDS(WORDS(WORDS(a))))))

MAGIC_MACRO(brave new  world)
MAGIC_MACRO(Hello world)
Run Code Online (Sandbox Code Playgroud)

生产:

brave_new_world
Hello_world
Run Code Online (Sandbox Code Playgroud)