C语言中如何使用宏连接多个字符串(#和##的用法)

最近在编写一个项目的代码时,需要在宏定义中连接多个字符串,具体来说就是,先定义一个软件版本号,然后再定义一个硬件版本号, 然后再将他们拼合起来生成一个综合版本号。这些动作我都希望在宏定义中直接完成,提供代码的可读性和可移植性。

类似于下面这样的:

#define SOFTWARE_VERSION     "Software:V1.00"
#define HARDWARE_VERSION     "Hardware:V1.00"
#define SYSTEM_VERSION       ????

如上,为了把SOFTWARE_VERSION和HARDWARE_VERSION连接起来,一般的程序猿应该都了解,其实办法很简单,就是使用“#”和“##”这两个特殊的宏转义字符。下面就对他们进行一下简单的介绍:

1、#:字符串

“#”的功能是将其后面的宏参数进行字符串化操作(Stringfication),简单说就是在对它所引用的宏变量,通过替换后在其左右各加上一个双引号。比如下面代码中的宏:

#define WARN_IF(EXP)                                  \
do {                                                  \
    if (EXP) {                                        \
        fprintf(stderr, "Warning: " #EXP "/n");       \
    }                                                 \
} while(0);

那么实际使用中会出现下面所示的替换过程:

WARN_IF (divider == 0);

被替换为

do {

    if (divider == 0) {
        fprintf(stderr, "Warning" "divider == 0" "/n");
    }

} while(0);

2、##:连接两个参数

“##”被称为连接符(concatenator),用来将两个Token连接为一个Token。注意这里连接的对象是Token就行,而不一定是宏的变量。比如你要做一个菜单项命令名和函数指针组成的结构体的数组,并且希望在函数名和菜单项命令名之间有直观的、名字上的关系。那么下面的代码就非常实用:

struct command
{
    char * name;
    void (*function) (void);
};

#define COMMAND(NAME) {NAME, NAME##_command}

// 然后你就用一些预先定义好的命令来方便的初始化一个command结构的数组了:

struct command commands[] = {
    COMMAND(quit),
    COMMAND(help),
    ...
}

COMMAND宏在这里充当一个代码生成器的作用,这样可以在一定程度上减少代码密度,间接地也可以减少不留心所造成的错误。我们还可以n个##符号连接 n+1个Token,这个特性也是#符号所不具备的。比如:

#define LINK_MULTIPLE(a,b,c,d) a##_##b##_##c##_##d

typedef struct _record_type LINK_MULTIPLE(name,company,position,salary);

// 这里这个语句将展开为:

//  typedef struct _record_type name_company_position_salary;

所以,上面提出的问题,自然就可以解决掉了。如下:

#define SOFTWARE_VERSION     "Software:V1.00"
#define HARDWARE_VERSION     "Hardware:V1.00"
#define SYSTEM_VERSION       SOFTWARE_VERSION##" "##HARDWARE_VERSION

但是,经过实际测试,以上的代码,只能用于KEIL/ADS/IAR等集成编译环境中。如果是在linux下,使用gcc编译器的话,上述代码就会出错,目前尚未查出具体原因。经过一番折腾后,发现gcc环境下,如果要连接多个字符串,直接使用空格连接就行了。所以将其改为如下语句就可以了:

#define SOFTWARE_VERSION     "Software:V1.00"
#define HARDWARE_VERSION     "Hardware:V1.00"
#define SYSTEM_VERSION       SOFTWARE_VERSION HARDWARE_VERSION

待续……..

要在存储多个字符串的同时找出出现次数最多的字符串,你可以使用一个数组来存储字符串,并使用另一个数组来记录每个字符串的出现次数。以下是一个示例代码: ```c #include <stdio.h> #include <string.h> #define MAX_STRINGS 10 #define MAX_LENGTH 100 int main() { char strings[MAX_STRINGS][MAX_LENGTH]; int count; int frequency[MAX_STRINGS] = {0}; int maxFrequencyIndex = 0; printf("请输入字符串的个数(最多%d个):", MAX_STRINGS); scanf("%d", &count); // 输入字符串 printf("请输入%d个字符串:\n", count); for (int i = 0; i < count; i++) { scanf("%s", strings[i]); } // 计算每个字符串的出现次数 for (int i = 0; i < count; i++) { for (int j = 0; j < count; j++) { if (strcmp(strings[i], strings[j]) == 0) { frequency[i]++; } } // 更新出现次数最多的字符串索引 if (frequency[i] > frequency[maxFrequencyIndex]) { maxFrequencyIndex = i; } } // 输出结果 printf("出现次数最多的字符串是:%s,出现次数为%d\n", strings[maxFrequencyIndex], frequency[maxFrequencyIndex]); return 0; } ``` 在这个示例,我们使用 `strings` 数组来存储多个字符串,`frequency` 数组来记录每个字符串的出现次数。我们还使用 `maxFrequencyIndex` 变量来记录出现次数最多的字符串的索引。 首先,程序要求用户输入字符串的个数,并根据输入的个数动态地存储相应数量的字符串。然后,程序遍历每个字符串使用嵌套循环计算每个字符串的出现次数,并更新 `maxFrequencyIndex` 变量以记录出现次数最多的字符串的索引。 最后,程序输出出现次数最多的字符串及其出现次数。 请注意,这个示例假设字符串的长度不会超过 `MAX_LENGTH`,且字符串不包含空格。如果需要处理更长的字符串或包含空格的字符串,你可能需要适当增加 `MAX_LENGTH` 的值,并使用其他方法来处理输入和比较字符串
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值