Return const char * from printf user function

I wrote a special print function. My problem is that I need to return const char*as it needs to be used in another function . I just don't know how to do this ...

anotherFunction (const char* text /*Here*/, unsigned __int32 value, unsigned __int64 bigVal);

I know that the following example / s do / es does not work as it should. This is what I have tried so far.

const char* CatchMessage (const char *message, ...)
{
    va_list  args;
    va_start (args, message);
    /*?*/
    va_end   (args);
    return message;
}

I still managed to get the correct output in cmd, but actually I need this as a return value.

void CatchMessage (const char *message, ...)
{
    va_list  args;
    va_start (args, message);
    vfprintf (stdout, message, args);
    va_end   (args);
}

Call:

CatchMessage ("Some Input %s and %d equals to %d", randString, randNumber, secRandNumber);

Must return:

"Some Input stuff and 12 equals to 6"

I could not find a solution. Any help would be appreciated.

Q: How to get this function CatchMessageto return correctly formatted const char*?

+4
6

(const) char * , -.

:

  • malloc() it
  • static, - ..

1:

void CatchMessage(char * result, size_t maxlen, const char *message, ...)
{
    va_list ap;
    va_start(ap, message);
    vsnprintf(result, maxlen, message, ap);
    va_end(ap);
}

char buffer[500];
CatchMessage(buffer, sizeof buffer, "Some Input %s and %d equals to %d", randString, randNumber, secRandNumber);
anotherfunction(buffer, ...)

ad 2:

char * CatchMessage(const char *message, ...)
{
    size_t size = 500;
    char * result = malloc(size);
    if (!result) return NULL; // error handling!
    while (1) {
        va_list ap;
        va_start(ap, message);
        size_t used = vsnprintf(result, size, message, ap);
        va_end(ap);
        char * newptr = realloc(result, size);
        if (!newptr) { // error
            free(result);
            return NULL;
        }
        result = newptr;
        if (used <= size) break;
        size = used;
    }
    return result;
}

char * buffer = CatchMessage(buffer, sizeof buffer, "Some Input %s and %d equals to %d", randString, randNumber, secRandNumber);
if (!buffer) { /* error handling: no memory! */ }
anotherfunction(buffer, ...)
free(buffer); // important for avoiding memory leaks

ad 3:

char * CatchMessage(const char *message, ...)
{

    static char result[500]; // static is important here! Otherwise the memory will be freed immediately after returning.
    va_list ap;
    va_start(ap, message);
    vsnprintf(result, sizeof result, message, ap);
    va_end(ap);
    return result;
}

char * buffer = CatchMessage(buffer, sizeof buffer, "Some Input %s and %d equals to %d", randString, randNumber, secRandNumber);
anotherfunction(buffer, ...)

,

char result[500];

, : . ; undefined.

+2

, CatchMessage char ( ) vsnprintf() .

+6

++ ( , ), std::string?

+3

, , :

#define MESSAGE_MAX 1024

const char *
CatchMessage (const char *message, ...)
{
    static buffer[MESSAGE_MAX];
    va_list  args;
    va_start (args, message);
    vsnprintf (buffer, MESSAGE_MAX, message, args);
    va_end   (args);
    return buffer;
}

:

  • . , .

  • . C99, vsprintf NULL , , .

+1

++ , ( ). , , ( , ), :

template <typename H, typename... Args>
void format(std::ostream& out,
            char const* format,
            size_t len,
            H const& head,
            Args const&... args);

// Variations with 'char const (&)[N]' and 'std::string' formats
// as well as variations returning directly a 'std::string'.

format ; . :

inline void format_string(std::ostream& out, char const* const* c) { out << *c; }
inline void format_string(std::ostream& out, std::string const* s) { out << *s; }
inline void format_string(std::ostream& out, void const*); // will throw

template <typename Integral, typename = enable_integral<Integral>::type>
inline void format_integral(std::ostream& out, Integral const* i) { out << *i; }
inline void format_integral(std::ostream& out, void const*); // will throw

inline size_t format_consume(std::ostream& out,
                             char const* const format,
                             size_t const length)
{
    char const* end = format + length;
    char const* current = format;

    do {
        // 1. Find first "format identifier", output stuff in-between
        char const* perc = std::find(current, end, '%');

        if (perc != current) { out.write(current, perc - current); }

        current = perc;

        // 2. %% is % escaped by %, so output it directly
        while (*current == '%' and *(current + 1) == '%') {
            out.put('%');
            current += 2;
        }
    } while (current != end and *current != '%');

    // 3. Return number of characters of format parameter consumed
    return current - format;
} // format_consume

inline void format(std::ostream& out, char const* format, size_t len) {
     size_t const consumed = format_consume(out, format, len);

     if (consumed != len) { throw std::runtime_exception("Missing arguments"); }
} // format

template <typename H, typename typename... Args>
void format(std::ostream& out,
            char const* format,
            size_t len,
            H const& head,
            Args const&... args)
{
     size_t const consumed = format_consume(out, format, len);

     if (consumed == len) { throw std::runtime_exception("Extraneous arguments"); }

     format += consumed;
     len -= consumed;

     assert(*format == '%');

     switch(*(format+1)) {
     case 's': format_string(out, &head); break;
     case 'd': format_integral(out, &head); break;
     default: throw std::runtime_exception("Invalid specifier");
     }

     format(out, format+2, len-2, args...);
} // format

, .., , , Boost.Format.

0
char* CatchMessage (size_t size, const char *message, ...)
{
    char result[size];
    va_list  args;
    va_start (args, message);
    vsprintf (result, message, args);
    va_end   (args);
    return result;
}

. this .

glglgl: , vsnprintf(result, size, message, args)

-3

All Articles