开发者

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());

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜