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

发布于 2024-07-07 14:15:32 字数 255 浏览 6 评论 0原文

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

具体来说,我在某个地方得到了:

#define MAX_LEN 16

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

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

我愿意接受其他方法来完成同样的事情,但仅限标准库。

I'm looking for a way to convert a preprocessor token to a string.

Specifically, I've somewhere got:

#define MAX_LEN 16

and I want to use it to prevent buffer overrun:

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

I'm open to other ways to accomplish the same thing, but standard library only.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

左秋 2024-07-14 14:15:32

请参阅使用FILELINE 报告错误

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

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

See Using FILE and LINE to Report Errors:

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

So your problem can be solved by doing
sscanf(buf, "%" TOSTRING(MAX_LEN) "s", val);.

人心善变 2024-07-14 14:15:32

我在网上找到了答案。 ( https://gcc.gnu.org/onlinedocs/gcc -3.4.3/cpp/Stringification.html

<块引用>
<前><代码>#define VERSION_MAJOR 4
#define VERSION_MINOR 47

#define VERSION_STRING“v”#VERSION_MAJOR“。” #VERSION_次要

上面的方法不起作用,但希望如此
说明了我想做的事情,
即使 VERSION_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) \
“。” 字符串化(VERSION_MINOR)

#include;
int main() {
printf ("%s\n", VERSION_STRING);
返回0;
}

I found an answer online. ( https://gcc.gnu.org/onlinedocs/gcc-3.4.3/cpp/Stringification.html )

#define VERSION_MAJOR 4
#define VERSION_MINOR 47

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

The above does not work but hopefully
illustrates what I would like to do,
i.e. make VERSION_STRING end up as
"v4.47".

To generate the proper numeric form
use something like

#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;
}
我最亲爱的 2024-07-14 14:15:32

这应该可行:

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

如果不行,则需要“双重扩展”技巧:

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

This should work:

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

If not, it'll need to "double expansion" trick:

 #define STR1(x)  #x
 #define STR(x)  STR1(x)
 sscanf(buf, "%" STR(MAX_LEN) "s", val);
稀香 2024-07-14 14:15:32

您应该使用双扩展字符串化宏技巧。 或者只是拥有一个

#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);

You should use the double-expansion stringification macro trick. Or just have a

#define MAX_LEN    16
#define MAX_LEN_S "16"

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

and keep it in sync. (That's a bit of a bother, but as long as the definitions are right next to each other, you'll probably remember.)

Actually, in this particular case, wouldn't strncpy suffice?

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

If it were printf, though, this would be easier:

sprintf(buf, "%.*s", MAX_LEN, val);
紫轩蝶泪 2024-07-14 14:15:32

虽然之前的一些答案“有效”,但我个人建议仅使用简单的字符串 API,而不是 libc

有许多可移植的 API,其中一些还进行了优化,以便轻松包含在您的项目中......还有一些像 ustr 的空间开销很小,并且支持堆栈变量。

While some of the previous answers "work", personally I'd recommend just using a simple string API instead of the dreck that comes in libc.

There are a number of portable APIs, some of which are also optimized for ease of inclusion in your project ... and some like ustr have a tiny space overhead and support for stack variables.

我不在是我 2024-07-14 14:15:32

在我的示例中,生成的格式为 %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;
}

输出

输出

In my example, the format to generate is %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

Output

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文