🔒 Locked
How to write a printf-like function.
Advertisement
Original Post
Quote:I or someone else could certainly post the code for this, but if you're programming in C++ you might consider using streams or boost::format instead.
Original post by kwaung
Hi,
I want to write a printf-like function to use as debug-message printing function on my render engine. Anyone can tell me how to write a message printing function that know how to deal with a notation like %d , %f, etc.
I have never used this function but I seem to recall the function vsprintf for a purpose such as this. Look it up for how to use it or maybe someone here knows how to use it.
:)
:)
This example is for educational purposes only. I'd personally consider using another alternative, such as Boost (what jyk mentioned), a printf variation (what Nypyren and Adam Hamilton mentioned), or a premade solution such as Fluid Studio's Logger Class, but if you wish to do it yourself using va_list (what Mike2343 mentioned), then here's an example I made that you should be able to learn from:
Good luck!
// What we need#include <cstdarg>#include <iostream>#include <sstream>#include <string>// Cleaner codeusing std::string;using std::stringstream;using std::cout;string MyPrintf( const char* str, ... ){ // Store the length of the passed in string int str_size = strlen(str); // We do not want to process an empty string if(str_size == 0) return ""; // This is the delimeter that is used to specify the format flags // you can use what you want. static char delim = '%'; // Stores final output, use a stringstream for // easy output of all basic data types stringstream output; // A place to store the list of arguments va_list arguments; // Initializing arguments to store all values after the initial string va_start(arguments, str); for(int x = 0; x < str_size; x++) { // We know that delim is used to denote a start of a format, but if you // wanted to use your own character, you'd add it here. if(str[x] == delim) { // If there is a next character, and it is not a delim, ("delimdelim" means add a single delim) // If you use your own character, replave the % with it! if(x + 1 < str_size && str[x + 1] != delim) { // If we get in a string if(str[x + 1] == 's') { // We have a c-string, so get it and save it char* temp = va_arg(arguments, char*); output << temp; // We know what comes after the delim, so do not process it x++; } // If we get in an integer else if(str[x + 1] == 'i') { // We have an integer, so get it and save it int temp = va_arg(arguments, int); output << temp; // We know what comes after the delim, so do not process it x++; } // ... Continue on for what else you need } else if(x + 1 < str_size) { // Save the delim that "delimdelim" was used for output << delim; // We know what comes after the delim, so do not process it x++; } } else { // Save the character to the output string output << str[x]; } } // Cleans up the list va_end(arguments); // Return the actual string return output.str();}int main(int argc, char* argv[]){ // Create the string string temp = MyPrintf("Hello %s must be at least %i years old", "world", 100); // Just show what it is cout << temp << "\n"; // Standard return return 0;}Good luck!
Use streams, but if you insist,
This will work like printf without having to rewrite formatting code. You should probably also use <cstdio> and <cstdarg> and the std:: thing although if you are using ellipses, this is the least of your worries. You need to take care of buffer overflow as well although this is not easy with the above simple method.
#include <stdio.h>#include <stdarg.h>const int max=1024;void debug(const char *s,...){ va_list va; va_start(va,s); char buffer[max]; sprintf(max,"error: "); vsprintf(max,s,va); sprintf(max,"\n"); va_end(va); do_whatever_with(buffer);}This will work like printf without having to rewrite formatting code. You should probably also use <cstdio> and <cstdarg> and the std:: thing although if you are using ellipses, this is the least of your worries. You need to take care of buffer overflow as well although this is not easy with the above simple method.
If you're using C++ then follow the advice of jyk, Drew_Benton, Herb Sutter and Andrei Alexandrescu (no, the last two of those didn't post in this thread [lol]):
Σnigma
Quote:
C++ Coding Standards by Herb Sutter and Andrei Alexandrescu
98. Don't use varargs (ellipsis).
Quote:
C++ Coding Standards by Herb Sutter and Andrei Alexandrescu
99. Don't use invalid objects. Don't use unsafe functions.
<snip />
Don't use the unsafe C legacy: strcpy, strncpy, sprintf, or any other functions that do write to range-unchecked buffers, and/or do not check and correctly handle out-of-bounds errors.
<snip />
Σnigma
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement