Конкатенация строк в C ++ - PullRequest
       15

Конкатенация строк в C ++

1 голос
/ 22 января 2010

Я довольно неопытный программист на C ++, поэтому этот вопрос, вероятно, довольно простой Я пытаюсь получить имя файла для моей связки:

string MonteCarloBasketDistribution::fileName(char c)
{
    char result[100];
    sprintf(result, "%c_%s(%s, %s).csv", copula.toString().c_str(), left.toString().c_str(), right.toString().c_str());
    return string(result);
}

который используется в:

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

Однако созданные файлы имеют мусорные имена, состоящие в основном из странных символов. Есть идеи, что я делаю не так и как это исправить?

Ответы [ 7 ]

14 голосов
/ 22 января 2010

sprintf имеет 4 заполнителя, а вы задаете только 3 параметра.

Я бы предложил:

string MonteCarloBasketDistribution::fileName(char c) {
   std::ostringstream result;
   result << c <<"_"<<copula<<'('<<left<<", "<<right<<").csv";
   return result.str();
}

Ваш sprintf небезопасен для переполнения буфера, используйте скорее C99 snprintf или std::stringstream

13 голосов
/ 22 января 2010

Поскольку все вещи, которые вы связываете, основаны на символах, использование sprintf для этого довольно глупо.

Что должен делать программист на C ++, есть нечто большее:

std::string result = copula.toString() + "(" + left.toString() + "," 
                   + right.toString() + ")";
5 голосов
/ 22 января 2010

У вас есть четыре спецификатора в строке формата, но вы предоставляете только три дополнительных аргумента.

4 голосов
/ 22 января 2010

Поскольку вы, кажется, работаете с std :: string, вам вообще не нужно использовать sprintf. std :: string имеет простые в использовании перегруженные операторы, поэтому вы можете объединить строки, используя + =. Я думаю, что + тоже работает, так что просто "добавьте" std :: strings вместе.

3 голосов
/ 22 января 2010

Boost имеет библиотеку форматирования , которая безопаснее, чем printf и друзья.

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

или, альтернативно:

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

В последнем примере Boost знает, что% 1% является символом и что% 2% через% 4% являются строками, "просматривая" типы аргументов, передаваемых через оператор%.

3 голосов
/ 22 января 2010

Единственное, что выглядит совершенно неработающим, это то, что вы передаёте только 3 параметра данных в свой sprintf, но он ожидает 4 (% c,% s,% s,% s)

2 голосов
/ 22 января 2010

Предполагая, что toString() возвращает std::string,

Это:

sprintf (результат, "% c_% s (% s,% s) .csv", copula.toString (). c_str (), left.toString (). c_str (), . Right.toString () c_str ());

... должно быть:

sprintf (результат, "% s _% s (% s,% s) .csv", copula.toString (). c_str (), left.toString (). c_str (), . Right.toString () c_str ());

...