How I can do something like this in C++:
void my_print(format_string) {
vector<string> dat开发者_Python百科a;
//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}");
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
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.
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;
}
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;
}
I think you're looking to do the following:
- Convert your
std::vector<std::string>
into ava_list
ofchar*
s - Pass that
va_list
, along with the user-supplied format string tovprintf
.
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.)
Now suports only %...f format. You can you can expand the possibilities by changing regex expression
https://regex101.com/r/dBaolO/1
template<typename ... Args>
static std::string string_format(const std::string& format, Args ... args)
{
int size_s = std::snprintf(nullptr, 0, format.c_str(), args ...) + 1; // Extra space for '\0'
if (size_s <= 0) { throw std::runtime_error("Error during formatting."); }
auto size = static_cast<size_t>(size_s);
auto buf = std::make_unique<char[]>(size);
std::snprintf(buf.get(), size, format.c_str(), args ...);
return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
}
static std::string string_format(const std::string& format, std::vector<float> args)
{
std::string formatted(format);
std::string pattern = R"(\%(?:\d+\.\d+)?[f|F])";
std::regex rx(pattern);
int args_index = 0;
int mismatch_offset = 0;
for (std::sregex_iterator i = std::sregex_iterator(format.begin(), format.end(), rx); i != std::sregex_iterator(); ++i, ++args_index) {
std::smatch match = *i;
auto string_value = string_format(match.str(), args.at(args_index));
formatted.replace(match.position() + mismatch_offset, match.length(), string_value);
mismatch_offset += string_value.length() - match.length();
}
return formatted;
}
Call the ones you want
printf("%1$s - %2$s - %3$s", date[0].c_str(), data[1].c_str(), data[2].c_str());
精彩评论