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

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

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

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

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

daveagp 26.10.2014 00:00

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

Fred Larson 10.10.2008 20:54
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
695
2
679 337
23

Ответы 23

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

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

itoa нестандартный: stackoverflow.com/questions/190229/…

David Dibben 10.10.2008 19:11

#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.

но s - это переменные стека, память s будет освобождена после вызова itos. s должен выделяться из кучи, а free после использования, верно?

kgbook 10.09.2018 10:29

возврат по значению в порядке, даже если строковый объект вышел за пределы области видимости, stackoverflow.com/a/3977119/5393174

kgbook 10.09.2018 11:18

#include <iostream>
#include <sstream>

std::ostringstream o;
o << name << age;
std::cout << o.str();

это здорово, НО заголовочный файл - это поток

landerlyoung 13.01.2017 10:48

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

Обратите внимание, что snprintf не гарантирует завершение строки нулем. Вот один из способов убедиться, что это работает: <pre> char buffer [128]; буфер [размер (буфер) -1] = '\ 0'; snprintf (буфер, sizeof (буфер) -1, «% s% d», name.c_str (), age); std :: cout << buffer << std :: endl; </pre>

Mr Fooz 10.10.2008 20:06

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

terson 11.10.2008 22:06

обратите внимание, что snprintf также нестандартный C++ (например, itoa, о котором вы упомянули). это взято из c99

Johannes Schaub - litb 09.02.2009 06:36

@terson: Я не вижу в ответе sprintf, только snprintf.

David Foerster 03.07.2013 22:07

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

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

sprintf(outString,"%s%d",name,age);

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

terson 11.10.2008 22:08

sprintf (char *, const char *, ...) завершится ошибкой в ​​некоторых версиях компиляторов, когда вы передадите std :: string в% s. Однако не все (это неопределенное поведение), и это может зависеть от длины строки (SSO). Пожалуйста, используйте .c_str ()

MSalters 13.10.2008 14:42

плюс sprintf подвержен переполнению буфера, поэтому возможна инъекция кода

Jean-François Fabre 16.05.2019 19:41

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

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

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

#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]

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

Зачем использовать препроцессор #define вместо template? С помощью вариативных шаблонов можно было бы передать даже несколько токенов. Но я не решаюсь использовать это, поскольку от static_cast к std::ostringstream на выходе операнда << немного небезопасно. По соглашению все средства вывода возвращают ссылку на исходный объект потока, но в стандарте это нигде не гарантируется.

Kai Petzke 14.09.2020 13:28

Вы комментируете ответ 12-летней давности. Теперь у нас есть вариативные шаблоны. Я бы сейчас, наверное, выбрал github.com/fmtlib/fmt.

Pyry Jahkola 15.10.2020 17:45

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

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. безопасно, но медленно; требуется Способствовать росту (только заголовок); большинство / все платформы
  2. безопасно, требует C++ 11 (нанизывать() уже включен в #include <string>)
  3. безопасно и быстро; требует FastFormat, который должен быть скомпилирован; большинство / все платформы
  4. (то же самое)
  5. безопасно и быстро; требует библиотека {fmt}, который можно скомпилировать или использовать в режиме только заголовков; большинство / все платформы
  6. безопасный, медленный и подробный; требуется #include <sstream> (из стандартного C++)
  7. является хрупким (необходимо предоставить достаточно большой буфер), быстрым и подробным; itoa () - нестандартное расширение, и его доступность для всех платформ не гарантируется.
  8. является хрупким (необходимо предоставить достаточно большой буфер), быстрым и подробным; ничего не требует (это стандартный C++); все платформы
  9. хрупкий (необходимо предоставить достаточно большой буфер), возможно самое быстрое преобразование, подробный; требуется STLSoft (только заголовок); большинство / все платформы
  10. безопасный (вы не используете более одного вызова int_to_string () в одном операторе), быстро; требуется STLSoft (только заголовок); Только для Windows
  11. безопасно, но медленно; требуется Поко C++; большинство / все платформы

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

JamieH 23.05.2009 01:45

Это почти вся ваша репутация с одного ответа !! Тебе повезло;) Я думаю, что 8 - это стандартный C (конечно, также C++), но, вероятно, стоит выделить его.

noelicus 16.08.2018 14:54

2. работает медленно, поскольку std :: to_string (age) создает временную строку, которая добавляется к результату.

Igor Bukanov 15.09.2019 12:49

Если вы используете Arduino, вы также можете использовать String(number).

Machado 19.04.2020 11:04

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

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

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

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

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

gremwell 07.08.2017 07:33

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

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

Если я попытаюсь добавить к целым числам или к целому и двойному, будет ли вызываться эта функция? Мне интересно, переопределит ли это решение обычные дополнения ...

Hilder Vitor Lima Pereira 14.01.2016 18:30

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

uckelman 15.01.2016 18:14

Вы правы (я только что проверил ...). И когда я пытался сделать что-то вроде строка s = 5 + 7, у меня возникала ошибка недопустимое преобразование из int в const char ’*

Hilder Vitor Lima Pereira 15.01.2016 20:55

В большинстве случаев использования шаблонов, которые связывают левый или правый операнд со строкой (включая std::string, std::string_view и const char *), должно быть достаточно.

Kai Petzke 14.09.2020 13:32

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

auto result = 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

Это будет name += std::to_string(static_cast<long long>(age)); в VC++ 2010, как вы можете видеть здесь

neonmate 27.05.2014 19:40

@neonmate Как насчет name += std::to_string(age + 0LL);?

chux - Reinstate Monica 07.10.2016 22:22

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

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

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

Это решение после C++ 11!

YamHon.CHAN 18.05.2015 06:30

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

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

Output:  John5

В C++ 20 вы сможете:

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

А пока вы можете использовать библиотека {fmt}, std::format основан на:

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

Отказ от ответственности: Я автор библиотеки {fmt} и C++ 20 std::format.

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

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

Какой из них быстрее?

ghchoi 18.02.2020 13:57
  • std :: 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));
  • boost :: lexical_cast
#include <boost/lexical_cast.hpp>

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

Какой самый быстрый?

ghchoi 18.02.2020 13:58

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

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