Альтернатива String.Format в С++
У меня нет большого опыта работы с С++. Скорее я больше работал на С#, и поэтому я хотел задать свой вопрос, связавшись с тем, что я бы сделал там. Мне нужно создать конкретный формат строки, которую я должен передать другой функции. В С# я бы легко сгенерировал строку через следующий простой код.
string a = "test";
string b = "text.txt";
string c = "text1.txt";
String.Format("{0} {1} > {2}", a, b, c);
Создав такую вышеприведенную строку, я должен передать это в system()
. Однако system
принимает только char*
Я нахожусь на Win32 C++
(не С++/CLI) и не могу использовать boost
, поскольку он будет включать слишком много включения всех файлов для проекта, который сам по себе очень мал. Мне кажется что-то вроде sprintf()
, но sprintf
не принимает string
как параметры a
, b
и c
. Любые предложения, как я могу сгенерировать эти форматированные строки, чтобы перейти к системе в моей программе?
Ответы
Ответ 1
Вы можете использовать sprintf
в комбинации с std::string.c_str()
.
c_str()
возвращает a const char*
и работает с sprintf
:
string a = "test";
string b = "text.txt";
string c = "text1.txt";
char* x = new char[a.length() + b.length() + c.length() + 32];
sprintf(x, "%s %s > %s", a.c_str(), b.c_str(), c.c_str() );
string str = x;
delete[] x;
или вы можете использовать предварительно выделенный массив char
, если знаете размер:
string a = "test";
string b = "text.txt";
string c = "text1.txt";
char x[256];
sprintf(x, "%s %s > %s", a.c_str(), b.c_str(), c.c_str() );
Ответ 2
Путь С++ должен состоять в том, чтобы использовать объект std::stringstream
как:
std::stringstream fmt;
fmt << a << " " << b << " > " << c;
Путь C должен состоять в использовании sprintf
.
Путь C трудно получить, поскольку:
- Это тип небезопасный
- Требуется управление буфером.
Конечно, вы можете захотеть вернуться на C-путь, если производительность является проблемой (представьте, что вы создаете миллион маленьких объектов stringstream
с фиксированным размером и затем отбрасываете их).
Ответ 3
Для полноты вы можете использовать std::stringstream
:
#include <iostream>
#include <sstream>
#include <string>
int main() {
std::string a = "a", b = "b", c = "c";
// apply formatting
std::stringstream s;
s << a << " " << b << " > " << c;
// assign to std::string
std::string str = s.str();
std::cout << str << "\n";
}
Или (в данном случае) std::string
очень собственные возможности конкатенации строк:
#include <iostream>
#include <string>
int main() {
std::string a = "a", b = "b", c = "c";
std::string str = a + " " + b + " > " + c;
std::cout << str << "\n";
}
Для справки:
Если вы действительно хотите пойти на C. Вот вы:
#include <iostream>
#include <string>
#include <vector>
#include <cstdio>
int main() {
std::string a = "a", b = "b", c = "c";
const char fmt[] = "%s %s > %s";
// use std::vector for memory management (to avoid memory leaks)
std::vector<char>::size_type size = 256;
std::vector<char> buf;
do {
// use snprintf instead of sprintf (to avoid buffer overflows)
// snprintf returns the required size (without terminating null)
// if buffer is too small initially: loop should run at most twice
buf.resize(size+1);
size = std::snprintf(
&buf[0], buf.size(),
fmt, a.c_str(), b.c_str(), c.c_str());
} while (size+1 > buf.size());
// assign to std::string
std::string str = &buf[0];
std::cout << str << "\n";
}
Для справки:
Затем появилась Библиотека формата ускорения. Ради вашего примера:
#include <iostream>
#include <string>
#include <boost/format.hpp>
int main() {
std::string a = "a", b = "b", c = "c";
// apply format
boost::format fmt = boost::format("%s %s > %s") % a % b % c;
// assign to std::string
std::string str = fmt.str();
std::cout << str << "\n";
}
Ответ 4
В дополнение к вариантам, предложенным другими, я могу порекомендовать fmt library, которая реализует форматирование строк, аналогичное str.format
в Python и String.Format
в С#. Вот пример:
std::string a = "test";
std::string b = "text.txt";
std::string c = "text1.txt";
std::string result = fmt::format("{0} {1} > {2}", a, b, c);
Отказ от ответственности: я являюсь автором этой библиотеки.
Ответ 5
Для полноты, ускорение будет заключаться в использовании boost::format
cout << boost::format("%s %s > %s") % a % b % c;
Возьмите свой выбор. Преимущество надстройки имеет преимущество безопасности типов с форматом sprintf
(для тех, кто считает синтаксис <<
немного неуклюжим).
Ответ 6
Как уже упоминалось, путь С++ использует строковые потоки.
#include <sstream>
string a = "test";
string b = "text.txt";
string c = "text1.txt";
std::stringstream ostr;
ostr << a << " " << b << " > " << c;
Обратите внимание, что вы можете получить строку C из объекта потока строк таким образом.
std::string formatted_string = ostr.str();
const char* c_str = formatted_string.c_str();
Ответ 7
Вы можете просто конкатенировать строки и создать командную строку.
std::string command = a + ' ' + b + " > " + c;
system(command.c_str());
Для этого вам не нужны дополнительные библиотеки.