【问题标题】:How can I use variable width specifiers defined by a macro in sscanf()如何使用由 sscanf() 中的宏定义的可变宽度说明符
【发布时间】:2020-03-07 03:40:30
【问题描述】:

我正在尝试根据 #define 指定 sscanf() 调用中变量的宽度,该 #define 根据另一个 #define 计算其值。

当 TEST 定义只是一个数字时它可以工作,但是当它变成一个计算时,代码会失败。让 TEST 调用另一个包含计算的函数也不起作用。

我正在使用的代码:

#include <stdio.h>

#define A       3
#define TEST    FUN()
#define FUN()   (A + 2)
#define STR(X)  _STR(X)
#define _STR(x) #x

int main()
{
    char input[] = "Test123";
    char output[10];

    sscanf(input, "%" STR(TEST) "s\n", output);

    printf("%s\n", output);

    return 0;
}

我在这里错过了什么?

【问题讨论】:

  • 预处理器不做任何算术运算,它基本上是一个简单的搜索和替换。
  • 我认为 inputoutput 在代码中被交换了。目标字符串,在scanf中,是第一个参数。
  • 1) 它是在编译阶段还是在运行时归档? 2) 你得到什么输出?
  • 您可以将 variable 视为通过命令行参数或作为函数的变量参数传入的东西。但是宏是经过预处理的,在运行时不会发生变化。
  • 一切都在编译时就知道了

标签: c c-preprocessor preprocessor


【解决方案1】:

您无法实现问题中发生的算术运算。因此,在编译时,它被评估为字符串形式的(3 + 2)

我的两分钱让人想起the post

#define STRING_LENGTH 20
#define STR(x) _STR(x)
#define _STR(x) #x

{
  ...    
  fscanf(input, "%" STR(STRING_LENGTH) "s", output);
  ...
}

需要两个宏,因为如果您尝试直接使用 _STR 之类的东西,您只会得到字符串 "STRING_LENGTH" 而不是它的值。

更多click herean example

【讨论】:

  • 谢谢。我想要实现的目标有什么好的选择吗?
【解决方案2】:

只需在执行期间构建scanf 格式字符串。例如:

const int width_modifier = FUN();
char fmt[100] = {0};
snprintf(fmt, sizeof(fmt), "%%%ds\n", width_modifier);
sscanf(input, fmt, output);

我在这里错过了什么?

预处理器进行文本替换,它不计算东西。所以"%" STR(TEST) "s\n"展开成一个包含"%" "3 + 2" "s\n"的字符串,拼接后就是"%3 + 2s",这是一个无效的scanf格式字符串。

您也可以使用其他程序来准备源文件进行编译。一种流行的用途是在编译之前对文件进行预处理并且能够计算算术的预处理器。一个流行的选择是m4

m4_define(`A', 3)
m4_define(`FUN', `eval(A + 2)')

#include <stdio.h>
#define STR(X)  #X
int main() {
    printf("%s", STR(FUN()));
}

使用m4 预处理并编译将输出5

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-04
    • 2020-02-05
    • 1970-01-01
    • 1970-01-01
    • 2018-11-24
    • 2020-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多