我正在寻找一种将预处理令牌转换为字符串的方法。
具体来说,我得到了:
#define MAX_LEN 16
我想用它来防止缓冲区溢出:
char val[MAX_LEN+1]; // room for \0 sscanf(buf, "%"MAX_LEN"s", val);
我对完成同样事情的其他方法持开放态度,但仅限于标准库。
我在网上找到了答案。
#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; }
#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 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);
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
strncpy(val, buf, MAX_LEN); val[MAX_LEN] = '\0';
不过,如果是 printf,这会容易一些:
printf
sprintf(buf, "%.*s", MAX_LEN, val);
虽然上面的一些“工作”,我个人建议只使用一个简单的字符串 API,而不是使用 libc 中的那些垃圾。有许多可移植的 API,其中一些也为了易于包含在您的项目中而进行了优化... ... 还有一些像 海关这样的 API 具有很小的空间开销和对堆栈变量的支持。
我的意见是,在我的示例中,要生成的格式是 %16s%16s%d
%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; }
输出