3

I am trying to specify the width of variables in a sscanf() call based on a #define that calculates its values based on another #define.

It works when the TEST define is just a single number, but when it becomes a calculation, the code fails. Have TEST call another function that contains the calculation does not work either.

The code I am working with:

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

What am I missing here?

Kodiak
  • 77
  • 1
  • 7

3 Answers3

3

You cannot realize an arithmetic operation as happened in your question. So, it is evaluated as (3 + 2) in string form while compiling.

My two cents reminiscent of the post,

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

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

Two macros are required because if you tried to use something like _STR directly you would just get the string "STRING_LENGTH" instead of its value.

For more click here and an example.

2

Just build the scanf format string during execution. For example:

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

What am I missing here?

Preprocessor does text replacement, it doesn't calculate things. So "%" STR(TEST) "s\n" expands to a string containing "%" "3 + 2" "s\n", which after concatenation is "%3 + 2s", which is an invalid scanf format string.

Alternatively you can use other program to prepare the source file for compilation. A popular use is a preprocessor that preprocesses the file before compilation and that is able to calculate arithmetic. A popular choice is m4:

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

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

preprocessed with m4 and compiled would output 5.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
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

Gowtam
  • 495
  • 2
  • 8
  • 20