Question

I am not sure exactly how to pass different string types to functions in C.

I have a function that receives a formatted string

void Logger::info(const char *logstring, ...) 
{

    // So I basically can write a preliminary message "DATA:" to a buffer
    // and then use vsnprintf() to write the const char *logstring to the buffer as well.

    int offset = 0;
    va_list argp;
    char buf[STRSIZE + 1];

    va_start(argp, logstring);
    offset = sprintf(buf, "DATA: ");
    vsnprintf(&buf[offset], STRSIZE - offset, logstring, argp);
    va_end(argp);

    // Then I write the buffer to stderr

    fprintf(stderr, "%s\n", buf);
}

What I would like to do is move all of that deeper into the function. But I cannot make it work because I have no idea how to successfully pass the formatted string "logstring" to the function and have it come out the other side.

So I want to do it like this...

info(const char *logstring, ...)
{
    writeToFile("Data:",logstring);
}

Then I can have the log file writing done more centrally.

Was it helpful?

Solution

Ok, its higly likely I didn't get exaclty where you're looking for here, but willing to take a shot and burn an answer. The following is about as basic a logger as you can get, but demonstrates how to centralize the message-build. Included at the bottom are some test conditions, and I purposely undersized the initial buffer size to allow you walk through in a debugger and see the resizes interactively. You will no-doubt want to size that up.

Anyway, if I happened to get luck and understand the question correctly, I hope if it doesn't directly address your issue, you at least get some ideas. Thanks.

EDIT: OP requested to squelch using std::string and buffer resizing to allow conformance with the limited compilation capabilities of his embedded system environment. Fixed length buffers are used, therefore, and output from vsnprintf() is only trusted if content actually fit.

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

class Logger
{
    static const size_t STRSIZE = 256;

public:
    void error(const char* fmt, ...)
    {
        va_list argptr;
        va_start(argptr,fmt);
        log("ERROR", fmt, argptr);
    };

    // two different logging interfaces.
    void info(const char* fmt, ...)
    {
        va_list argptr;
        va_start(argptr,fmt);
        log("INFO", fmt, argptr);
    };

    void debug(const char* fmt, ...)
    {
        va_list argptr;
        va_start(argptr,fmt);
        log("DEBUG", fmt, argptr);
    };

private:
    void log(const char *msg, const char* fmt, va_list& vl)
    {
        // uses a fixed size message buffer
        char str[STRSIZE+1] = {0};
        strncpy(str, msg, sizeof(str)-1);
        strncat(str, ": ", (sizeof(str)-1) - strlen(str));

        // needed for sizing limits of variadic printf, then send
        //  output as a single line message to stderr.
        size_t mlen = strlen(str);
        if (vsnprintf(str + mlen, sizeof(str)-mlen-1, fmt, vl) >= 0)
            fprintf(stderr, "%s\n", str);
        else
            fprintf(stderr, "%s: (max log message length exceeded)\n", msg);
    };
};

int main(int argc, char *argv[])
{
    Logger logger;

    logger.debug("Numbers %d %d %d", 1,2,3);
    logger.error("Strings %s %s %s", "1", "2", "3");
    logger.info("Mixed %s %d %p", "1", 2, "3");
    logger.info("No additional parameters required for this message.");

    // demonstrate automatic cutoff.
    char sbig[] = "0123456789012345678901234567890123456789"
                  "0123456789012345678901234567890123456789";

    logger.debug("Oversized params: %d-%s %d-%s %d-%s %d-%s", 
                 1, sbig, 2, sbig, 3, sbig, 4, sbig);
    return 0;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top