将预处理标记转换为字符串

我正在寻找一种将预处理令牌转换为字符串的方法。

具体来说,我得到了:

#define MAX_LEN 16

我想用它来防止缓冲区溢出:

char val[MAX_LEN+1]; // room for \0
sscanf(buf, "%"MAX_LEN"s", val);

我对完成同样事情的其他方法持开放态度,但仅限于标准库。

91678 次浏览

我在网上找到了答案。

#define VERSION_MAJOR 4
#define VERSION_MINOR 47


#define VERSION_STRING "v" #VERSION_MAJOR "." #VERSION_MINOR

上述方法不起作用,但希望如此 说明了我想做什么, 也就是说,使 VERION _ STRING 结束为 “ v4.47”。

生成适当的数值形式 比如说

#define VERSION_MAJOR 4
#define VERSION_MINOR 47


#define STRINGIZE2(s) #s
#define STRINGIZE(s) STRINGIZE2(s)
#define VERSION_STRING "v" STRINGIZE(VERSION_MAJOR) \
"." STRINGIZE(VERSION_MINOR)


#include <stdio.h>
int main() {
printf ("%s\n", VERSION_STRING);
return 0;
}

已经有一段时间了,但这应该有用:

 sscanf(buf, "%" #MAX_LEN "s", val);

否则,它就需要“双倍扩张”的把戏:

 #define STR1(x)  #x
#define STR(x)  STR1(x)
sscanf(buf, "%" STR(MAX_LEN) "s", val);

请参阅“一个 href = “ http://www.dempile.com/cpp/faq/file _ and _ line _ error _ string.htm”rel = “ norefrer”> http://www.decompile.com/cpp/faq/file_and_line_error_string.htm 具体来说:

#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define AT __FILE__ ":" TOSTRING(__LINE__)

所以你的问题可以通过做 sscanf(buf, "%" TOSTRING(MAX_LEN) "s", val);

您应该使用双展开字符串化宏技巧

#define MAX_LEN    16
#define MAX_LEN_S "16"


char val[MAX_LEN+1];
sscanf(buf, "%"MAX_LEN_S"s", val);

保持同步。(这有点麻烦,但只要这两个定义紧挨在一起,你可能就会记得。)

事实上,在这种情况下,strncpy还不够吗?

strncpy(val, buf, MAX_LEN);
val[MAX_LEN] = '\0';

不过,如果是 printf,这会容易一些:

sprintf(buf, "%.*s", MAX_LEN, val);

虽然上面的一些“工作”,我个人建议只使用一个简单的字符串 API,而不是使用 libc 中的那些垃圾。有许多可移植的 API,其中一些也为了易于包含在您的项目中而进行了优化... ... 还有一些像 海关这样的 API 具有很小的空间开销和对堆栈变量的支持。

我的意见是,在我的示例中,要生成的格式是 %16s%16s%d

#include <iostream>


#define MAX_LEN 16


#define AUX(x) #x
#define STRINGIFY(x) AUX(x)


int main() {
char buffer[] = "Hello World 25";
char val[MAX_LEN+1];
char val2[MAX_LEN+1];
int val3;


char format[] = "%" STRINGIFY(MAX_LEN) "s" "%" STRINGIFY(MAX_LEN) "s" "%d";
int result = sscanf(buffer, format, val, val2, &val3);
std::cout<< val << std::endl;
std::cout<< val2 << std::endl;
std::cout<< val3 << std::endl;
std::cout<<"Filled: " << result << " variables" << std::endl;
std::cout << "Format: " << format << std::endl;
}

输出
output