tags:

views:

549

answers:

6

How I can do something like this in C++:

void my_print(format_string) {
   vector<string> data;
   //Fills vector
   printf(format_string, data);
}

my_print("%1$s - %2$s - %3$s");
my_print("%3$s - %2$s);

I have not explained well before. The format string is entered by the application user.

In C# this works:

void my_print(format_string) {
 List<string> data = new List<string>();
 //Fills list
 Console.WriteLine(format_string, data.ToArray);
}

my_print("{0} - {1} - {2}");
my_print("{2} - {1}");
A: 

Call the ones you want

printf("%1$s - %2$s - %3$s", date[0].c_str(), data[1].c_str(), data[2].c_str());
wheaties
Still have to call `c_str()`
John Dibling
+9  A: 
printf("%s - %s - %s", data[0].c_str(), data[1].c_str(), data[2].c_str() );

Note that you must convert to C-style strings - printf cannot do this for you.

Edit: In response to your revised question, I think you will have to parse the format string yourself, as you will have to validate it. printf() won't do the job.

anon
+5  A: 

If you're going to use streams, you can also use ostream_iterator in conjunction with a looping construct like copy:

vector<string> data;
data.assign(10, "hello");

copy( &data[0], &data[3], ostream_iterator<string>(cout, " "));

Note that the second parameter to copy points to one past the end. Output:

hello hello hello

John Dibling
But the output the OP wanted was "hello - hello - hello"
anon
`ostream_iterator` doesn't do the job here. It appends the delimiter to every write, whereas the questioner wants a separator (i.e. not appended after the last write).
Steve Jessop
John Dibling
Though it's not included in the standard, an ostream_iterator-like class that only inserts separators is entirely possible. see: http://groups.google.com/group/comp.lang.c++/msg/a746a588cedfa44b
Jerry Coffin
Ken Bloom
@Ken: Taking the address is fine. Dereferencing that address is not. This has been discussed many times on SO.
John Dibling
@Ken are you referring to taking the address of one-past-the end? Or to using pointers with copy()?
John Dibling
@John you're right. It is safe http://www.parashift.com/c++-faq-lite/containers.html#faq-34.3
Ken Bloom
@Ken: Ah, yes, I see what you're referring to now. Note that this is not true for other containers, as I'm sure you know already.
John Dibling
+3  A: 

The Boost Format Library might be helpful.

#include <boost/format.hpp>
#include <vector>
#include <string>
#include <iostream>
int main(int arc, char** argv){
   std::vector<std::string> array;
   array.push_back("Hello");
   array.push_back("word");
   array.push_back("Hello");
   array.push_back("again");
   boost::format f("%s, %s! %s %s! \n");
   f.exceptions( f.exceptions() &
     ~ ( boost::io::too_many_args_bit | boost::io::too_few_args_bit )  );

   for (std::vector<std::string>::iterator i=array.begin();i!=array.end();++i){
      f = f % (*i);
   }
   std::cout << f;
   return 0;
}
Ken Bloom
A: 

I think you're looking to do the following:

  1. Convert your std::vector<std::string> into a va_list of char*s
  2. Pass that va_list, along with the user-supplied format string to vprintf.

I still don't know how to do step 1. (What I do know is that most higher-level languages, such as Java, Scala, and Ruby have a simple, safe, direct conversion for that. C++ doesn't.)

Ken Bloom
+1  A: 

I have temporarly solved with this function:

string format_vector(string format, vector<string> &items)
{   
   int counter = 1;

   replace_string(format,"\\n","\n");
   replace_string(format,"\\t","\t");

   for(vector<string>::iterator it = items.begin(); it != items.end(); ++it) {
        ostringstream stm; stm << counter;
        replace_string(format, "%" + stm.str(), *it);
        counter++;
   }
    return format;
}
Sebtm
I think that's a pretty reasonable solution.
Ken Bloom