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

587

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

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

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

  • 0
    Позвольте мне добавить к этому: я попробовал 'str = "hi"; ул + = 5; cout << str; ' и не видел эффекта. Оказывается, это вызывает оператор + = (char) и добавляет непечатный символ.
Теги:
concatenation
int
stdstring

30 ответов

1047

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

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 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 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++; большинство/все платформы
  • 13
    Помимо той ссылки, которую вы получили, на чем основаны ваши комментарии по эффективности?
  • 1
    См. Tinyurl.com/234rq9u для сравнения некоторых решений
Показать ещё 1 комментарий
249

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

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

Если у вас есть 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. Это НЕ стандартная функция, поэтому ваш код не будет переносимым, если вы его используете. Есть компиляторы, которые его не поддерживают.

  • 0
    Обратите внимание, что snprintf не гарантирует нулевое завершение строки. Вот один из способов убедиться, что он работает: <pre> char buffer [128]; buffer [sizeof (buffer) -1] = '\ 0'; snprintf (буфер, sizeof (буфер) -1, "% s% d", name.c_str (), age); std :: cout << buffer << std :: endl; </ PRE>
  • 0
    Моя тенденция заключается в том, чтобы никогда не использовать sprintf, так как это может привести к переполнению буфера. Приведенный выше пример является хорошим примером, когда использование sprintf было бы небезопасно, если имя было очень длинным.
Показать ещё 3 комментария
73
std::ostringstream o;
o << name << age;
std::cout << o.str();
  • 2
    это здорово, заголовочный файл BYT sstream
47
#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.

  • 0
    спасибо за код, ссылка сейчас битая: D
  • 0
    но s это переменная стека, память s будет свободна после вызова itos . s должен выделяться из кучи и быть free после использования, верно?
Показать ещё 1 комментарий
27

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

string s = name + std::to_string(age);
  • 7
    Это решение после C ++ 11!
19

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

sprintf(outString,"%s%d",name,age);
  • 1
    snprintf может быть сложным (в основном потому, что в некоторых ситуациях он может не включать нулевой символ), но я предпочитаю избегать переполнения буфера sprintf потенциальными проблемами.
  • 2
    sprintf (char *, const char *, ...) не будет работать в некоторых версиях компиляторов, когда вы передаете std :: string в% s. Не все, хотя (это неопределенное поведение), и это может зависеть от длины строки (SSO). Пожалуйста, используйте .c_str ()
18

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

Пример:

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

name += std::to_string(age);

std::cout << name;

Выход:

John21
  • 2
    Это будет name += std::to_string(static_cast<long long>(age)); в VC ++ 2010, как вы можете увидеть здесь
  • 0
    @neonmate Как насчет name += std::to_string(age + 0LL); вместо?
15

У меня нет достаточной кармы, чтобы прокомментировать (не говоря уже о редактировании), но Jay post (в настоящее время верхний проголосовавший в 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;

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

15
#include <string>
#include <sstream>
using namespace std;
string concatenate(std::string const& name, int i)
{
    stringstream s;
    s << name << i;
    return s.str();
}
12

У Herb Sutter есть хорошая статья на эту тему: String Formatters of Manor Farm. Он охватывает Boost::lexical_cast, std::stringstream, std::strstream (который устарел) и sprintf vs. snprintf.

11
#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;

Googled [и проверено: p]

7

Если вы хотите использовать + для конкатенации всего, что имеет оператор вывода, вы можете предоставить версию шаблона 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

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

  • 0
    Если я попытаюсь добавить к целым числам или целому числу и двойному, будет ли вызываться эта функция? Мне интересно, если это решение переопределит обычные дополнения ...
  • 0
    Оператор возвращает std::string , поэтому не будет кандидатом в выражения, где строка не может быть преобразована в нужный тип. Например, этот operator+ не может использоваться для + в int x = 5 + 7; , Учитывая все обстоятельства, я бы не определить оператора , как это не очень убедительных причин, но моя цель состояла в том, чтобы предложить ответ , отличный от других.
Показать ещё 1 комментарий
5

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

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

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

4

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

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

Output:  John5
4

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

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

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

  • 0
    QString ("Something") + QString :: number (someIntVariable) также работает
4

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"
}
4

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

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

3

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

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

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

3

Я написал функцию, которая принимает число 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 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;
}
3

Если вы хотите получить char * out и использовали stringstream в соответствии с тем, что было указано выше, выполните следующие действия:

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

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

3

Можно использовать больше опций для объединения целого числа (или другого числового объекта) со строкой. Это 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 утверждает, что является одним из самым быстрым вариантом для преобразования целых чисел.

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

std::ostringstream s;
s << "John " << age;
std::string query(s.str());
  • std :: to_string (С++ 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));
2

Вот реализация того, как добавить 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
}
1

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

#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
}
1

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

name.append(age+"");
cout << name;
  • 3
    На самом деле, он компилируется, но вызывает неопределенное поведение
  • 2
    Вы распадаете строковый литерал "" на char* и увеличиваете этот указатель по age . Другими словами, неопределенное поведение.
0

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

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

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

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

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

0

Предложите альтернативное решение для таких людей, как я, у которых может не быть доступа к С++ 11 и дополнительных библиотек/заголовков, таких как boost. Простое преобразование работает следующим образом:

Пример числа 4, чтобы преобразовать 3 в ascii, мы можем просто использовать код:
char a = '0' + 4

Это немедленно сохранит 4 как символ в a.

Отсюда мы можем просто конкатенировать a с остальной частью строки.

0

Без С++ 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"

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

-5

Я начинающий пользователь С++ и нашел это самым простым способом:

cout << name << age; 

Это будет успешно связывать имя и возраст, выход будет "John21."

Однако должна быть причина, по которой никто не сказал этого; Я думаю, что в этом может быть недостаток, хотя до сих пор я этого не испытывал.

EDIT: Я понял, что это не обязательно правильный ответ, однако я сохраню его здесь, если бы новички С++ хотели бы знать, как выводить конкатенированные строки.

  • 5
    Это просто вывод двух строк вместе, а не создание новой строки. Так, например, вы не можете передать результат другим функциям. Это не ответ.
  • 1
    Ах, я не правильно истолковал вопрос ОП, в таком случае. Но IOStream будет работать, правильно?
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню