Concatenating strings in C++
I am rather inexperienced C++ programmer, so this question is probably rather basic. I am trying to get the file name for my copula:
string MonteCarloBasketDistribution::fileName(char c)
{
char result[100];
sprintf(result, "%c_%s(%s, %s).csv", copula.toString().c_str(), left.toString().c_s开发者_如何学运维tr(), right.toString().c_str());
return string(result);
}
which is used in:
MonteCarloBasketDistribution::MonteCarloBasketDistribution(Copula &c, Distribution &l, Distribution &r): copula(c), left(l), right(r)
{
//.....
ofstream funit;
funit.open (fileName('u').c_str());
ofstream freal;
freal.open (fileName('r').c_str());
}
However, the files created have rubbish names, consisting mainly from weird characters. Any idea what I am doing wrong and how to fix it?
sprintf has 4 place holders while you give only 3 parameters.
I would suggest:
string MonteCarloBasketDistribution::fileName(char c) {
std::ostringstream result;
result << c <<"_"<<copula<<'('<<left<<", "<<right<<").csv";
return result.str();
}
Your sprintf
is not safe for buffer overflow, use rather C99 snprintf
or std::stringstream
Since all the things you are tacking together are character-based, using sprintf for it is kinda silly.
What a C++ programmer should be doing there is something more along the lines of:
std::string result = copula.toString() + "(" + left.toString() + ","
+ right.toString() + ")";
You have four specifiers in your format string, yet are only supplying three additional arguments.
Since you seem to work on std::string, you needn't use sprintf at all. std::string has simple to use overloaded operators, so you can concantenate strings using +=. I think + works too, so just "add" std::strings together.
The only thing that looks totally broken is that you're only passing 3 data parameters to your sprintf, but it's expecting 4 (%c, %s, %s, %s)
Boost has a formatting library that is safer than printf and friends.
#include <boost/format.hpp>
string MonteCarloBasketDistribution::fileName(char c)
{
return boost::str( boost::format("%c_%s(%s, %s).csv")
% c % copula.toString() % left.toString() % right.toString() );
}
or, alternatively:
#include <boost/format.hpp>
string MonteCarloBasketDistribution::fileName(char c)
{
return boost::str( boost::format("%1%_%2%(%3%, %4%).csv")
% c % copula.toString() % left.toString() % right.toString() );
}
With the latter example, Boost knows that %1% is a character and that %2% thru %4% are strings by "looking" at the types of the arguments passed in via the % operator.
Assuming that toString()
returns a std::string
,
This:
sprintf(result, "%c_%s(%s, %s).csv", copula.toString().c_str(), left.toString().c_str(), right.toString().c_str());
...should be:
sprintf(result, "%s_%s(%s, %s).csv", copula.toString().c_str(), left.toString().c_str(), right.toString().c_str());
精彩评论