Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

C ansi format macro global char[] overwrite

I have an coding assignment that must be done in C. I got sidetracked and decided to try to make a format macro i can use for styling text with ansi codes. My code is as follows:
<format.h>

#include <stdarg.h>
#include <string.h>

/**
 * global buffer to store format arguments for prints
 */
char format_buffer[128];

/**
 * Count the number of char* in variadic arguments, auxiliary for FMT macro
 */
#define FARGS(...)  (sizeof((char*[]){__VA_ARGS__})/sizeof(char*))

/**
 * Automatically fills in parameters buffer and argc for the format function. Buffer is a global variable, therefore it is never out of scope.
 */
#define FMT(...) format(format_buffer, FARGS(__VA_ARGS__), __VA_ARGS__)

#define A_START "\x1B["
#define A_END "m"

/**
 * creates a format string based on input parameters.
 * @param argc the number of ansi flags to use
 * @param buffer the buffer to write the format string into. A size of 64 should be enough for most reasonable uses
 * @param ... the ansi flags to use. Examples include RED, BLUE, DASH, etc
 * @return the same pointer buffer, for ease of use in printf functions
 */
char* format(char* buffer, int argc, ...);

// ansi macros for formatting, all of the style ";NN"

<format.c>

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel


#include "format.h"

char format_buffer[128] = {};

char* format(char* buffer, int argc, ...){
    buffer[0] = '\0';

    va_list argv;
    int i;

    // initialize argv to get data from the variable arguments
    va_start(argv, argc);

    strcat(buffer, A_START);
    /* access all the arguments assigned to valist */
    for (i = 0; i < argc; i++) {
        strcat(buffer, va_arg(argv, char*));
    }
    strcat(buffer, A_END);

    /* clean memory reserved for valist */
    va_end(argv);

    return buffer;

}

Using that, I can call the macro as follows, which is what I want:
printf("%sHello!\n", FMT(RED, BOLD)) //prints <Hello!\n> in red and bold

The problem

The problem I have is when I try to use multiple calls in the same print statement:
printf("%sHello, %sWorld!\n", FMT(RED, BOLD), FMT(YELLOW)) //prints <Hello, World!\n> in yellow
I’m positive it’s not working as expected because FMT(...) always returns the same global char*, but I don’t know how could i change it so that:

  • I can call the format macro as shown above: printf("%sHello!\n", FMT(RED, BOLD)).
  • I can use multiple FMT calls in the same print statement, as in printf("%sHello, %sWorld!\n", FMT(RED, BOLD), FMT(YELLOW)) should print <Hello, > in red and bold and <World!\n> in yellow.

As a final note, I’d rather code the solution instead of using a library or header that already has an implementation of this.

I first tried creating a new char[] inside the format function, but it would be stored in the stack so I assume that’s a much worse outcome.

>Solution :

Simply change the macro to:

#define FMT(...) format((char[128]){}, FARGS(__VA_ARGS__), __VA_ARGS__)

https://godbolt.org/z/KvWWcYfPb

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading