0

Is there a function like printf that can return a string instead of printing it? I have a function that prints a string in a certain color, but it has to be a string literal instead of accepting variables like printf.

// Function declaration (Assums YELLOW and NORMAL are the unix constants for terminal colors
void pYellow(char *str) {
    printf("%s%s%s", YELLOW, str, NORMAL);
}

//Function call 
void pYellow("This is a string");

If I wanted to print in color with a variable, it wont work. Like pYellow("Num: %d", 42); will give an error, because its got too many parameters. And doing pYellow(printf("String")); won't work either.

TL:DR I want to know if there's a printf method that returns a string instead of printing it.

cclloyd
  • 8,171
  • 16
  • 57
  • 104
  • 1
    You can use snprintf as suggested by `dom0`, or you can use a function which dynamically allocates memory and returns a pointer. There is a non-standard one called `asprintf`, however you can implement that in Standard C in a few lines by delegating to `vsnprintf`. – M.M Oct 10 '14 at 02:07
  • http://en.cppreference.com/w/cpp/io/c/fprintf – phuclv Oct 10 '14 at 02:09
  • See also [Substitute or workaround for `asprintf()` on AIX](http://stackoverflow.com/questions/4899221/substitute-or-workaround-for-asprintf-on-aix). – Jonathan Leffler Oct 10 '14 at 18:29

1 Answers1

2

Use snprintf:

int snprintf(char *str, size_t size, const char *format, ...);
  • str is a buffer you allocated (e.g. malloc())
  • size is the size of that buffer
  • After the call the formatted string is stored in str.
  • There's also sprintf, never use it

Also you can create you own printf-like functions using the v*printf family of functions. Simplest example for this:

#include <stdarg.h>
// required for va_list, va_start, va_end

void customPrintf(const char* format, /* additional arguments go here */ ...)
{
    va_list args;
    va_start(args, format);
    // set color here (for example)
    vprintf(format, args);
    // reset color
    va_end(args);
}
dom0
  • 7,356
  • 3
  • 28
  • 50
  • Disagree with "`sprintf`, never use it". `snprintf()` has its own set of problems too. Use the right tool for the job and use it correctly. There is nothing unsafe about `char[sizeof(int)*CHAR_BIT/3 + 3]; sprintf(buf, "%d", some_int);` If a coder cannot use `sprintf()` correctly, the chances of using `snprintf()` correctly are not much higher and provides a false sense of security. Much like recommending `strncpy()` over `strcpy()` - trading one set of issues for another. – chux - Reinstate Monica Oct 10 '14 at 02:03
  • @chux I'd still prefer the snprintf version for `%d`, you *know* it will not buffer overflow, whereas with the other one you have to engage your brain to check it (and even then you might not be 100% sure). – M.M Oct 10 '14 at 02:08
  • @Matt McNabb Agree `snprintf()` does prevents buffer overflow. If the buffer is insufficient, the printed results are wrong (truncated). Code still has a problem. We have traded one type of problem for another. It is arguable which is better, but at the end, robust code needs to 1) prevent (`sprintf()` route) or 2) cope with truncation (`snprintf()` route). IAC - my point is that it is not which is always _better_, but that declaring "`sprintf`, never use it" is not good advice due to "never". – chux - Reinstate Monica Oct 10 '14 at 02:58
  • I don't see the problem here. Either you know the buffer size, then there is really no issue at all using snprintf. Or you don't know it, then it is completely unsafe two write even a single byte into the buffer. As he seems to be a novice programmer I'd rather give the *never*-kind of advice. *Do it if you exactly know what you're doing*-advice is not for novices. By the way, did you know that printf output sometimes depends on locale? Truncation check = check return value, is not UB. Invalid memory access *is* UB. – dom0 Oct 10 '14 at 09:15