Подтвердить что ты не робот

Альтернатива 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. Любые предложения, как я могу сгенерировать эти форматированные строки, чтобы перейти к системе в моей программе?

4b9b3361

Ответ 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());

Для этого вам не нужны дополнительные библиотеки.