процесс сборки — C # String.Format с параметрами стандартного эквивалента в C ++?

У меня много кода на C #, который я должен написать на C ++. У меня нет большого опыта в C ++.

я использую Visual Studio 2012 строить. Проект является Статическая библиотека в C ++ (не в C ++ / CLI).

Во многих местах они использовали String.Format, как это:

C #

String.Format("Some Text {0}, some other Text {1}", parameter0, parameter1);

Теперь я знаю, что подобные вещи уже задавались ранее, но мне не ясно, какой самый стандартный / безопасный способ сделать это.

Было бы безопасно использовать что-то вроде Sprintf или же Printf? Я читал, что некоторые люди упоминают, что они не стандартные. Что-то вроде этого? (Будет ли это C ++ или C?)

C ++ (или это C?)

char buffer [50];
int n, a=5, b=3;
n=sprintf (buffer, "Some Text %d, some other Text %d", a, b);

Другие люди предложили сделать свой собственный класс, и я видел много разных реализаций.

В настоящее время у меня есть класс, который использует станд :: to_string, ostringstream, станд :: string.replace а также станд :: string.find, с Шаблоны. Мой класс довольно ограничен, но для случаев, которые я имею в коде C #, это работает. Теперь я не знаю, что это самый эффективный способ (или даже правильный):

C ++

template <typename T>
static std::string ToString(T Number)
{
std::ostringstream stringStream;
stringStream << Number;
std::string string = stringStream.str();
return string;
};

template <typename T,unsigned S>
static std::string Format(const std::string& stringValue, const T (&parameters)[S])
{
std::string stringToReturn = std::string(stringValue);

for (int i = 0; i < S; ++i)
{
std::string toReplace = "{"+ std::to_string(i) +"}";
size_t f = stringToReturn.find(toReplace);
if(std::string::npos != f)
stringToReturn.replace(f, toReplace.length(), ToString(parameters[i]));
}

return stringToReturn;
};

//I have some other overloads that call the Format function that receives an array.
template <typename T>
static std::string Format(const std::string& stringValue, const T parameter, const T parameter2)
{
T parameters[] = {parameter, parameter2};
return Format(stringValue, parameters);
};

И мне нужен мой код, чтобы работать как в Linux а также Windows, поэтому мне нужны разные компиляторы, чтобы его можно было собрать, поэтому я должен быть уверен, что использую стандартный способ. И моя среда не может быть обновлена ​​так легко, поэтому я не могу использовать C ++ 11. Я не могу использовать Увеличение либо потому, что я не уверен, что смогу добавить библиотеки в разных средах, которые мне нужны для работы.

Какой наилучший подход я могу использовать в этом случае?

2

Решение

sprintf работает, если все, что у вас есть, не является объектным типом (или вы вручную конвертируете их в C-строки, или конвертируете их в строки, а затем вызываете функция-член c_str ()). Вы можете захотеть дополнительную защиту от переполнения буфера, snprintf обеспечивает.

Если вы хотите узнать больше, чтобы делать то, что вам нужно, вы можете использовать Библиотека Boost Format. Я уверен, что вы можете написать скрипт для преобразования вызовов String.format в синтаксис Boost.

Если вы не можете использовать Boost, и вы не можете использовать C ++ 11, вы должны использовать sprintf и быть осторожным с переполнением буфера (возможно, snprintf, если вы можете положиться на свой компилятор). Возможно, вы захотите написать скрипт для переноса всех параметров, чтобы они все преобразовывались в строки:

String.Format("Some Text {0}, some other Text {1}", to_printf(p0), to_printf(p1));

Также обратите внимание, что формат C не использует фигурные скобки. Так что это большая проблема. Возможно, вам придется реализовать свой собственный переменная функция.


Если все просто, как {0}Вы, вероятно, можете написать скрипт для замены большинства экземпляров String.Format (и ни одного из более сложных) чем-то вроде

`mystring = "Some Text "+tostring(p0)+", some other Text "+tostring(p1);`

Это не самый эффективный способ, но, скорее всего, он не будет иметь значения, если вы не используете тысячи форматов в секунду. Или, возможно, немного более эффективно (без промежуточных строк):

`"mystring = static_cast<std::ostringstream&>(std::ostringstream().flush()<<Some Text "<<p0<<", some other Text "<<p1).str();`,

который создает временный. Флеш-вид заставляет компилятор думать, что это не временно, и это решает конкретная проблема о невозможности использовать не-член operator<<.

1

Другие решения

Вот библиотека с 1 заголовком, которую я писал только для этой цели: fakeformat

Тестовое задание:

REQUIRE(ff::format("{2}ff{1}").with('a').also_with(7).now()=="7ffa");

Библиотека настраивается, так что вы можете начать индексирование параметров с 0. Вы также можете написать оболочку, чтобы она выглядела в точности как String.Format,

Это строит на Linux и не нуждается в C ++ 11.

Там нет стандартного способа еще …

Или вы можете использовать Boost.Locale форматирование

Вот оно, с индексами, начинающимися с 0:

#include ...

struct dotnet_config {
static const char scope_begin='{';
static const char scope_end='}';
static const char separator=',';
static const char equals='=';
static const size_t index_begin=0;
static bool string_to_key(std::string const& to_parse,int& res) {
std::istringstream ss(to_parse);
ss.imbue(std::locale::classic());
ss >> res;
if (!ss.fail() && ss.eof())
return true;
return false;
}
};

template <typename T1>
std::string Format (std::string const& format_string,T1 p1) {
return ff::formatter<dotnet_config>(format_string).with(p1).now();
}

template <typename T1,typename T2>
std::string Format (std::string const& format_string,T1 p1,T2 p2) {
return ff::formatter<dotnet_config>(format_string).with(p1).with(p2).now();
}

int main() {
std::cout<<Format("test={0}",42)<<std::endl;
std::cout<<Format("{0}!={1}",33,42)<<std::endl;
return 0;
}

Выход:

test=42
33!=42
2

Почему бы вам не использовать << оператор для форматирования вашей строки?

string strOutput;
stringstream strn;
int i = 10;
float f = 20.0f;
strn << "Sally scored "<<i<< " out of "<<f << ". She failed the test!";
strn >> strOutput;
cout << strOutput;
0