如何在sscanf()中使用由宏定义的变宽格式说明符

3

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

当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;
}

我在这里缺少什么?

5
预处理器不进行任何算术运算,它基本上只是一个简单的搜索和替换过程。 - Some programmer dude
我认为代码中inputoutput被交换了。在scanf中,目标字符串是第一个参数。 - Roberto Caboni
  1. 它是在编译阶段还是运行时进行文件处理?
  2. 你得到了什么输出?
- Roberto Caboni
你可能会认为_variable_是通过命令行参数或作为函数的变量参数传递的内容。但是宏是预处理的,在运行时不是变量。 - ryyker
所有东西都在编译时期间已知。 - Kodiak
3个回答

3

你无法像你提问中发生的那样实现算术运算。因此,在编译时以字符串形式评估为(3 + 2)

我觉得类似于这篇文章

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

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

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

欲了解更多,请点击此处并查看示例


谢谢。我尝试实现的目标有没有好的替代方案? - Kodiak

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


0
#include <stdio.h>
#include <string.h>


#define MAX_LENGTH 5


int main()
{
    // specify format 

    char formatStr[20] = {0};
    snprintf(formatStr, 20-1, "%s%d%s", "%", MAX_LENGTH-1, "s%u");
    printf("%s\n", formatStr);
    
    // example to use that format 

    char *input = "programming 123";
    
    char dataStr[MAX_LENGTH] = {0};
    int  dataVal;
    sscanf(input, formatStr, dataStr, &dataVal);
    printf("%s-%d\n", dataStr, dataVal);
    
    return 0;
}

output:

%4s%u
prog-21942


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接