0

I'm currently creating a program that takes a CSV file, parses it, then prints out the various items on the page. Eventually, you'd have various columns of data. In order to have the columns looking nicely, you'd have to add padding to the fprintf() statement (at least I can't think of another way of doing it). The below is a snippet from my code:

    for (int pos = 0; pos < size; pos++) {
        fprintf(stdout, "%30s - %20d, %20d, %20s, %20d, %20d\n", 
                (char *)(item+pos)->itemval, (item+pos)->column, 
                (item+pos)->row, (char *)(item+pos)->columntitle, 
                (item+pos)->adjustedpos, (item+pos)->adjustedcolumn,
                (item+pos)->adjustedrow);
    }

Is it possible to use a macro constant as the padding? For example, in the printf() statement, can I have something like fprintf(..., "%'COLUMNMACROCONSTANT's", ...), which is defined in a macro? I apologize if this question has been asked before, but I don't know how to describe that part of the fprintf() function. I tried to just put it in, but it won't let me, which makes sense (how does the compiler know to separate the macro from the string). I'm wondering if there's some kind of separator like "\" for macros contained in this area of the print function.

6
  • 4
    You can use * such as in say printf("%*d", width, value); Commented Jan 5 at 17:07
  • 2
    ...which also works with left-alignment printf("%-*s", width, text); Commented Jan 5 at 17:20
  • 1
    ... or you can specify a negative field width in printf("%*d", width, value); to enable left justification (the - flag) together with a (positive) field width. Commented Jan 5 at 17:48
  • 1
    Are you looking for ways to implement predetermined column widths, or is your intent to adapt the column widths to fit the data? Because macros are not suitable for the latter, and although you can use them for the former, they don't do that much for you there. Commented Jan 5 at 17:56
  • 4
    Style comment: instead of (item+pos)->column, it is more idiomatic to write item[pos].column. (Functionally they are completely equivalent, of course.) Commented Jan 5 at 20:35

2 Answers 2

2

If the macro is a simple decimal numeral, just digits, you can insert it into a string literal by using a macro to convert it to a string. Due to the order in which parts of macro replacement operate, you need two macros to do this. In the first, the macro parameter is replaced with the argument and a second macro is invoked:

#define Stringize(x)        StringizeHelper(x)

In the second, the argument is converted to a string literal:

#define StringizeHelper(x)  #x

So this program will print y in a field of 10 spaces, with an x before the field and a z after the field to mark the ends:

#define Width   10

#define StringizeHelper(x)  #x
#define Stringize(x)        StringizeHelper(x)

#include <stdio.h>

int main(void)
{
    printf("x%" Stringize(Width) "sz\n", "y");
}

Output:

x         yz

You can also specify the field width by putting * in the conversion specification, as in %*s, and passing the width as an argument to printf. This program produces the same output:

#define Width   10

#include <stdio.h>

int main(void)
{
    printf("x%*sz\n", Width, "y");
}

That methods works as long as Width is any int expression; it does not have to be a constant.

2

You can use string literal concatenation in C (refer to this answer for more details).

In C, you can concatenate string literals by simply placing them next to each other, like this:

char* hello_world = "Hello, " "World!";

This is equivalent to:

char* hello_world = "Hello, World!";

The compiler automatically combines the adjacent string literals into one.

You can leverage this property to achieve the desired functionality. For example:

#define COLUMNMACROCONSTANT "20" // Define it as a string literal
// ... other code

fprintf(..., "%" COLUMNMACROCONSTANT "s", ...);
  • The compiler replaces COLUMNMACROCONSTANT with "20".
  • The string "%" COLUMNMACROCONSTANT "s" becomes "%" "20" "s", which the compiler combines into "%20s".
0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.