Как объединить std::string и int?

Я думал, что это будет действительно просто, но это представляет некоторые трудности. Если у меня есть

std::string name = "John";
int age = 21;

Как мне объединить их, чтобы получить одну строку "John21"?

33 ответа

В алфавитном порядке:

std::string name = "John";
int age = 21;
std::string result;

// 1. with Boost
result = name + boost::lexical_cast<std::string>(age);

// 2. with C++11
result = name + std::to_string(age);

// 3. with FastFormat.Format
fastformat::fmt(result, "{0}{1}", name, age);

// 4. with FastFormat.Write
fastformat::write(result, name, age);

// 5. with the {fmt} library
result = fmt::format("{}{}", name, age);

// 6. with IOStreams
std::stringstream sstm;
sstm << name << age;
result = sstm.str();

// 7. with itoa
char numstr[21]; // enough to hold all numbers up to 64-bits
result = name + itoa(age, numstr, 10);

// 8. with sprintf
char numstr[21]; // enough to hold all numbers up to 64-bits
sprintf(numstr, "%d", age);
result = name + numstr;

// 9. with STLSoft's integer_to_string
char numstr[21]; // enough to hold all numbers up to 64-bits
result = name + stlsoft::integer_to_string(numstr, 21, age);

// 10. with STLSoft's winstl::int_to_string()
result = name + winstl::int_to_string(age);

// 11. With Poco NumberFormatter
result = name + Poco::NumberFormatter().format(age);
  1. безопасно, но медленно; требует Boost (только заголовок); большинство / все платформы
  2. является безопасным, требует C++ 11 ( to_string () уже включен в #include <string>)
  3. безопасно и быстро; требует FastFormat, который должен быть скомпилирован; большинство / все платформы
  4. безопасно и быстро; требует FastFormat, который должен быть скомпилирован; большинство / все платформы
  5. безопасно и быстро; требуется библиотека {fmt}, которую можно скомпилировать или использовать в режиме только заголовка; большинство / все платформы
  6. безопасный, медленный и многословный; требует #include <sstream> (из стандарта C++)
  7. является хрупким (вы должны предоставить достаточно большой буфер), быстрым и многословным; itoa () является нестандартным расширением и не гарантируется быть доступным для всех платформ
  8. является хрупким (вы должны предоставить достаточно большой буфер), быстрым и многословным; ничего не требует (стандарт C++); все платформы
  9. является хрупким (вы должны предоставить достаточно большой буфер), вероятно, самое быстрое преобразование, многословное; требует STLSoft (только заголовок); большинство / все платформы
  10. safe-ish (вы не используете более одного вызова int_to_string() в одном выражении), быстро; требует STLSoft (только заголовок); Windows, только
  11. безопасно, но медленно; требует Poco C++; большинство / все платформы

В C++11 вы можете использовать std::to_stringНапример:

auto result = name + std::to_string( age );

Если у вас есть Boost, вы можете преобразовать целое число в строку, используя boost::lexical_cast<std::string>(age),

Другой способ заключается в использовании строковых потоков:

std::stringstream ss;
ss << age;
std::cout << name << ss.str() << std::endl;

Третий подход заключается в использовании sprintf или же snprintf из библиотеки C.

char buffer[128];
snprintf(buffer, sizeof(buffer), "%s%d", name.c_str(), age);
std::cout << buffer << std::endl;

Другие постеры предложили использовать itoa, Это НЕ стандартная функция, поэтому ваш код не будет переносимым, если вы его используете. Есть компиляторы, которые не поддерживают это.

std::ostringstream o;
o << name << age;
std::cout << o.str();
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
string itos(int i) // convert int to string
{
    stringstream s;
    s << i;
    return s.str();
}

Бесстыдно похищен с http://www.research.att.com/~bs/bs_faq2.html.

Это самый простой способ:

string s = name + std::to_string(age);

Если у вас есть C++11, вы можете использовать std::to_string,

Пример:

std::string name = "John";
int age = 21;

name += std::to_string(age);

std::cout << name;

Выход:

John21

Мне кажется, что самый простой ответ заключается в использовании sprintf функция:

sprintf(outString,"%s%d",name,age);
#include <string>
#include <sstream>
using namespace std;
string concatenate(std::string const& name, int i)
{
    stringstream s;
    s << name << i;
    return s.str();
}

У меня недостаточно кармы, чтобы комментировать (не говоря уже о редактировании), но пост Джея (в настоящее время пользующийся наибольшим количеством голосов в 27) содержит ошибку. Этот код:

std::stringstream ss;
ss << age;
std::cout << name << ss.str() << std::endl;

Не решает заявленную проблему создания строки, состоящей из объединенной строки и целого числа. Я думаю, что Джей имел в виду что-то вроде этого:

std::stringstream ss;
ss << name;
ss << age;
std::cout << "built string: " << ss.str() << std::endl;

Последняя строка просто печатает результат и показывает, как получить доступ к последней объединенной строке.

#include <sstream>

template <class T>
inline std::string to_string (const T& t)
{
   std::stringstream ss;
   ss << t;
   return ss.str();
}

Тогда ваше использование будет выглядеть примерно так

   std::string szName = "John";
   int numAge = 23;
   szName += to_string<int>(numAge);
   cout << szName << endl;

Погуглил [и проверил:p ]

У Херба Саттера есть хорошая статья на эту тему: "Строковые форматеры усадебной фермы". Он покрывает Boost::lexical_cast, std::stringstream, std::strstream (что устарело), ​​и sprintf против snprintf,

С библиотекой {fmt}:

auto result = fmt::format("{}{}", name, age);

Подмножество библиотеки предлагается для стандартизации как форматирование текста P0645, и, если оно будет принято, приведенное выше станет:

auto result = std::format("{}{}", name, age);

Отказ от ответственности: я являюсь автором библиотеки {fmt}.

Эта проблема может быть решена разными способами. Я покажу это двумя способами:

  1. Преобразуйте число в строку, используя to_string(i).

  2. Использование строковых потоков.

    Код:

    #include <string>
    #include <sstream>
    #include <bits/stdc++.h>
    #include <iostream>
    using namespace std;
    
    int main() {
        string name = "John";
        int age = 21;
    
        string answer1 = "";
        // Method 1). string s1 = to_string(age).
    
        string s1=to_string(age); // Know the integer get converted into string
        // where as we know that concatenation can easily be done using '+' in C++
    
        answer1 = name + s1;
    
        cout << answer1 << endl;
    
        // Method 2). Using string streams
    
        ostringstream s2;
    
        s2 << age;
    
        string s3 = s2.str(); // The str() function will convert a number into a string
    
        string answer2 = "";  // For concatenation of strings.
    
        answer2 = name + s3;
    
        cout << answer2 << endl;
    
        return 0;
    }
    

// Надеюсь, поможет

В качестве одного лайнера: name += std::to_string(age);

Если вы хотите использовать + для объединения всего, что имеет оператор вывода, вы можете предоставить шаблонную версию operator+:

template <typename L, typename R> std::string operator+(L left, R right) {
  std::ostringstream os;
  os << left << right;
  return os.str();
}

Тогда вы можете написать свои сочинения простым способом:

std::string foo("the answer is ");
int i = 42;
std::string bar(foo + i);    
std::cout << bar << std::endl;

Выход:

the answer is 42

Это не самый эффективный способ, но вам не нужен самый эффективный способ, если вы не делаете много конкатенации внутри цикла.

Если вы используете MFC, вы можете использовать CString

CString nameAge = "";
nameAge.Format("%s%d", "John", 21);

Управляемый C++ также имеет форматировщик строки.

Общий ответ: itoa ()

Это плохо. itoa является нестандартным, как указано здесь.

Поскольку вопрос, связанный с Qt, был закрыт в пользу этого, вот как это сделать, используя Qt:

QString string = QString("Some string %1 with an int somewhere").arg(someIntVariable);
string.append(someOtherIntVariable);

Строковая переменная теперь имеет значение someIntVariable вместо%1 и значение someOtherIntVariable в конце.

Std::ostringstream - хороший метод, но иногда этот дополнительный трюк может оказаться полезным для преобразования форматирования в однострочный:

#include <sstream>
#define MAKE_STRING(tokens) /****************/ \
    static_cast<std::ostringstream&>(          \
        std::ostringstream().flush() << tokens \
    ).str()                                    \
    /**/

Теперь вы можете отформатировать строки следующим образом:

int main() {
    int i = 123;
    std::string message = MAKE_STRING("i = " << i);
    std::cout << message << std::endl; // prints: "i = 123"
}

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

string name = "John";
int age = 5;
char temp = 5 + '0';
name = name + temp;
cout << name << endl;

Output:  John5
  • станд:: ostringstream
#include <sstream>

std::ostringstream s;
s << "John " << age;
std::string query(s.str());
  • std:: to_string (C++ 11)
std::string query("John " + std::to_string(age));
  • повышение::lexical_cast
#include <boost/lexical_cast.hpp>

std::string query("John " + boost::lexical_cast<std::string>(age));

Если вы хотите получить символ * и использовать stringstream в соответствии с тем, что наметили вышеупомянутые респонденты, то сделайте, например:

myFuncWhichTakesPtrToChar(ss.str().c_str());

Поскольку то, что stringstream возвращает через str(), является стандартной строкой, вы можете затем вызвать c_str() для получения желаемого типа вывода.

Есть больше опций, которые можно использовать для объединения целого числа (или другого числового объекта) со строкой. Это Boost.Format

#include <boost/format.hpp>
#include <string>
int main()
{
    using boost::format;

    int age = 22;
    std::string str_age = str(format("age is %1%") % age);
}

и карма от Boost.Spirit (v2)

#include <boost/spirit/include/karma.hpp>
#include <iterator>
#include <string>
int main()
{
    using namespace boost::spirit;

    int age = 22;
    std::string str_age("age is ");
    std::back_insert_iterator<std::string> sink(str_age);
    karma::generate(sink, int_, age);

    return 0;
}

Boost.Spirit Karma претендует на звание одного из самых быстрых вариантов преобразования целых чисел в строки.

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

char intToChar(int num)
{
    if (num < 10 && num >= 0)
    {
        return num + 48;
        //48 is the number that we add to an integer number to have its character equivalent (see the unsigned ASCII table)
    }
    else
    {
        return '*';
    }
}

string intToString(int num)
{
    int digits = 0, process, single;
    string numString;
    process = num;

    // The following process the number of digits in num
    while (process != 0)
    {
        single  = process % 10; // 'single' now holds the rightmost portion of the int
        process = (process - single)/10;
        // Take out the rightmost number of the int (it's a zero in this portion of the int), then divide it by 10
        // The above combination eliminates the rightmost portion of the int
        digits ++;
    }

    process = num;

    // Fill the numString with '*' times digits
    for (int i = 0; i < digits; i++)
    {
        numString += '*';
    }


    for (int i = digits-1; i >= 0; i--)
    {
        single = process % 10;
        numString[i] = intToChar ( single);
        process = (process - single) / 10;
    }

    return numString;
}

Вот реализация того, как добавить int к строке, используя аспекты синтаксического анализа и форматирования из библиотеки IOStreams.

#include <iostream>
#include <locale>
#include <string>

template <class Facet>
struct erasable_facet : Facet
{
    erasable_facet() : Facet(1) { }
    ~erasable_facet() { }
};

void append_int(std::string& s, int n)
{
    erasable_facet<std::num_put<char,
                                std::back_insert_iterator<std::string>>> facet;
    std::ios str(nullptr);

    facet.put(std::back_inserter(s), str,
                                     str.fill(), static_cast<unsigned long>(n));
}

int main()
{
    std::string str = "ID: ";
    int id = 123;

    append_int(str, id);

    std::cout << str; // ID: 123
}

В C ++ 20 у вас может быть переменная лямбда, которая объединяет произвольные потоковые типы в строку в несколько строк:

      auto make_string=[os=std::ostringstream{}](auto&& ...p) mutable 
{ 
  (os << ... << std::forward<decltype(p)>(p) ); 
  return std::move(os).str();
};

int main() {
std::cout << make_string("Hello world: ",4,2, " is ", 42.0);
}

см. https://godbolt.org/z/dEe9h75eb

использование move (os) .str () гарантирует, что строковый буфер объекта ostringstream будет пустым при следующем вызове лямбды.

Еще один простой способ сделать это:

name.append(age+"");
cout << name;

Подробный ответ похоронен ниже в других ответах, обновляя часть этого:

#include <iostream> // cout
#include <string> // string, to_string(some_number_here)

using namespace std;

int main() {
    // using constants
    cout << "John" + std::to_string(21) << endl;
    // output is:
    //    John21

    // using variables
    string name = "John";
    int age = 21;
    cout << name + to_string(age) << endl;
    // output is:
    //    John21
}

Без C++11 для небольшого целого диапазона я обнаружил, что это все, что мне нужно:

Объявите / включите где-нибудь вариант следующего:

const string intToString[10] = {"0","1","2","3","4","5","6","7","8","9"};

Затем:

string str = intToString[3] + " + " + intToString[4] + " = " + intToString[7]; //str equals "3 + 4 = 7"

Это работает с перечислениями тоже.

Другие вопросы по тегам