Search code examples
cmacrosscanfc89

How do I use a #defined constant as the max field width in fscanf?


All of this is in C89, not C99.

I have a constant.

#define MAX_NAME_LEN 256

I want to use it as the max field width in fscanf, sort of like this.

fscanf(input, "%256s", name);

But I want to use the MAX_NAME_LEN instead of the literal 256 for sake of good style. I have tried all of

fscanf(input, "%MAX_NAME_LENs", name);

char* max_name_len_str = malloc(16 * sizeof *max_name_len_str);
sprintf(max_name_len_str, "%d", MAX_NAME_LEN);
fscanf(input, "%" max_name_len_str "s", name);
free(max_name_len_str);

//works with printf, but has different meaning in scanf
fscanf(input, "%*s", MAX_NAME_LEN, name);

fscanf(input, "%%ds", MAX_NAME_LEN, name);

without success.

char* nameFormat = malloc(16 * sizeof *nameFormat); //I assume I don't ever want more than 10^13 characters in a name
sprintf(nameFormat, "%s%ds", "%", MAX_NAME_LEN);
fscanf(input, nameFormat, name);
free(nameFormat);

does work, but is ungainly as all get out. Is there a more elegant solution?


Solution

  • 1st simplification.

    // Unlikely need to malloc short array
    char nameFormat[16]; // I assume I don't ever want more than 10^13 characters  
    sprintf(nameFormat, "%%%ds", MAX_NAME_LEN);  // %% prints a %
    fscanf(input, nameFormat, name);
    

    2nd offering or better, use stringify @DevilaN.
    Note that the size of the buffer needs to be at least 1 more than the "%s" width.

    #define MAX_NAME_LEN 256
    #define MAX_NAME_LEN_STR "256"
    
    char name[MAX_NAME_LEN + 1];
    fscanf(input, "%" MAX_NAME_LEN_STR "s", name);
    

    3rd, use fgets() (my preference), Of course this reads a line and not a sequence of non-white-space characters. This often does meet that higher level goal though.

    #define MAX_NAME_LEN 256
    char name[MAX_NAME_LEN + 2];
    fgets(name, sizeof name, input);