C 宏预处理器,用于在字符串中包含数字

C Macro Preprocessor to include a number in string

提问人:Kay 提问时间:9/26/2023 最后编辑:Jonathan LefflerKay 更新时间:9/26/2023 访问量:102

问:

我想将任意控制代码插入字符串中,但使用十进制数而不是十六进制()或oct()。举一个毫无意义但可以立即理解的例子,我很乐意有一个宏,比如 CC,这样我就可以形成一个字符串:x\ux\0x

// Decimal 10 and 13 are ASCII LF and CR resp.
char mystring[] = "This is line 1" CC(10) CC(13) "This is line 2";

最终,此代码将与自定义硬件上的其他非标准函数/行为一起使用。

十进制 C 预处理器

评论

1赞 Jonathan Leffler 9/26/2023
由于没有办法使用十进制转义序列(只有八进制或十六进制)在字符串中嵌入转义字符,因此您不能做任何您想做的事(当然不是理智的)。
2赞 HolyBlackCat 9/26/2023
没有简单的方法可以做到这一点,你也不应该这样做。只需使用 .这是其他人所期望的,也是你将在其他人的代码中看到的。\r\n
1赞 Fe2O3 9/26/2023
从您的评论到下面的答案:“通过慢速无线连接发送的显示数据中的控制代码”,并基于上面的示例字符串......研究“字节对编码”,或者另一种形式的数据压缩(例如:两端的规范霍夫曼编码)。您的目标是在两端都有可用处理能力的慢速连接上最大限度地提高吞吐量。明确的需求陈述将节省每个人的时间。
1赞 Lundin 9/26/2023
我认为你需要退后一步,专注于实际问题,这似乎是通过慢速无线链路发送字符串 - 而不是在 C 字符串中创建异国情调的转义序列。也许你应该问问如何做到最好——这听起来像是一个 electronics.stackexchange.com 的问题。我可以分享一些关于这个主题的经验。
0赞 Fe2O3 9/26/2023
你已经接受了@chqrlie的答案。只是一个建议:与其构建一个仅限于多个 SP 的自制协议,不如现在扩展它以包含要乘的字符。今天在商场看到的 tickertape LED 显示屏包括多个星号和多个等号......没有时间像现在这样进行功能蠕变......

答:

4赞 chqrlie 9/26/2023 #1

对于十进制数,没有通用的方法可以执行此操作,但如果代码数量有限,则可以使用令牌粘贴:

#include <stdio.h>

#define CC_13  "\x0D"
#define CC_10  "\x0A"

#define CONCAT(a, b)  a ## b
#define CC(n) CONCAT(CC_, n)

int main(void) {
    // Decimal 13 and 10 are ASCII CR and LF resp.
    char mystring[] = "This is line 1" CC(13) CC(10) "This is line 2";

    // simple macros are supported too
    #define CR 13
    #define LF 10

    printf("%s" CC(CR) CC(LF), mystring);
    return 0;
}

该宏可以与数字和简单宏一起使用,只要将相应的宏定义为字符串常量即可。如果缺少此定义,您将收到一条(有点隐晦的)错误消息。CCCC_xxx

如果您的目标是嵌入控制字节,那么上述操作应该没问题,尽管有点矫枉过正,因为您可以直接使用宏。CC_xxx

从注释中提供的额外信息来看,您似乎希望将二进制数据嵌入到字符串常量中作为内联命令的参数,这些命令本身被指定为控制代码:为此使用上述技巧会很麻烦,并且指定范围 1..255 之外的数字可能会导致问题,因为您将在这些字符串中嵌入可能被误解的 null 字节。

我建议您将这些参数作为数字字符串传递,以便在运行时在目标设备内进行解析。下面是一个示例:

#define STR(n)  #n
#define WHITESPACE(n)  "\x1B" STR(n) "F"

char sentence[] = "A big space between here" WHITESPACE(30) "and here."

您可以将此字符串发送到设备,设备处理程序将分析转义字节和 (for forward) 之间的可选数字参数,以向前移动多个像素。使用转义序列只是一个例子,您可以使用最适合您的任何约定,但它允许在服务器端使用以下命令轻松构造字符串:Fprintf

#include <stdio.h>

int main(void) {
    // Slide in a welcome message
    for (int i = 0; i < 100; i++) {
        char buf[80];
        // CR moves the cursor the beginning of the line
        // ESC K erases the rest of the line
        // ESC n F moves the cursor right by n pixels
        snprintf(buf, sizeof buf, "\r\033K\033%dFHello world!", 100 - i);
        send_device(buf);
        usleep(1000);
    }
    return 0;
}

评论

0赞 Kay 9/26/2023
不幸的是,我想要任何数字,因为我想将这些值用作控制代码的参数。例如:有一个附加一个数字的控制代码,以插入一个像素数的空白。WHITESPACEchar sentence[] = "A big space between here" WHITESPACE CC(30) "and here."
2赞 chqrlie 9/26/2023
@Kay:有很大的局限性,但恐怕 C 语言中没有通用的解决方案。另一种方法是在 ASCII 中嵌入参数:用作并在运行时将数字从数字转换为数字,而不是读取字节。#define WHITESPACE(n) "\x01(" #n ")"char sentence[] = "A big space between here" WHITESPACE(30) "and here."
0赞 Fe2O3 9/26/2023
在这里,我认为支持代码混淆是非常不鼓励的事情。
0赞 Kay 9/26/2023
@chqrlie 这是一个聪明的主意——失去了一些效率,但确实实现了这里其他人拒绝理解的目的。谢谢。
0赞 Fe2O3 9/26/2023
@Kay 您正在寻找的东西可以通过破解源代码来实现......继续,不标准......Gnu 已经预料到你了......printf()