Я думал, что это будет очень просто, но это вызывает некоторые трудности. Если бы у меня был
std::string name = "John";
int age = 21;
Как их объединить, чтобы получить одну строку "John21"?
У Херба Саттера есть хорошая статья на эту тему: "Строковые форматтеры усадьбы". Он охватывает Boost::lexical_cast, std::stringstream, std::strstream (который устарел) и sprintf по сравнению с snprintf.





Общий ответ: итоа ()
Это плохо. itoa нестандартен, как указал здесь.
itoa нестандартный: stackoverflow.com/questions/190229/…
#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 после использования, верно?
возврат по значению в порядке, даже если строковый объект вышел за пределы области видимости, stackoverflow.com/a/3977119/5393174
#include <iostream>
#include <sstream>
std::ostringstream o;
o << name << age;
std::cout << o.str();
это здорово, НО заголовочный файл - это поток
Если у вас есть 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>
Я бы никогда не использовал sprintf, поскольку это может привести к переполнению буфера. Приведенный выше пример является хорошим примером, когда использование sprintf было бы небезопасным, если бы имя было очень длинным.
обратите внимание, что snprintf также нестандартный C++ (например, itoa, о котором вы упомянули). это взято из c99
@terson: Я не вижу в ответе sprintf, только snprintf.
#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.
sprintf (char *, const char *, ...) завершится ошибкой в некоторых версиях компиляторов, когда вы передадите std :: string в% s. Однако не все (это неопределенное поведение), и это может зависеть от длины строки (SSO). Пожалуйста, используйте .c_str ()
плюс sprintf подвержен переполнению буфера, поэтому возможна инъекция кода
Если вы используете 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 на выходе операнда << немного небезопасно. По соглашению все средства вывода возвращают ссылку на исходный объект потока, но в стандарте это нигде не гарантируется.
Вы комментируете ответ 12-летней давности. Теперь у нас есть вариативные шаблоны. Я бы сейчас, наверное, выбрал github.com/fmtlib/fmt.
В алфавитном порядке:
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);
#include <string>)#include <sstream> (из стандартного C++)Помимо одной ссылки, которую вы дали, на чем вы основываете свои комментарии о производительности?
Это почти вся ваша репутация с одного ответа !! Тебе повезло;) Я думаю, что 8 - это стандартный C (конечно, также C++), но, вероятно, стоит выделить его.
2. работает медленно, поскольку std :: to_string (age) создает временную строку, которая добавляется к результату.
Если вы используете Arduino, вы также можете использовать String(number).
Есть больше вариантов, которые можно использовать для объединения целого числа (или другого числового объекта) со строкой. Это 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) также работает
Если вы хотите использовать + для конкатенации всего, что имеет оператор вывода, вы можете предоставить версию шаблона 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
Это не самый эффективный способ, но вам не нужен самый эффективный способ, если вы не выполняете много конкатенации внутри цикла.
Если я попытаюсь добавить к целым числам или к целому и двойному, будет ли вызываться эта функция? Мне интересно, переопределит ли это решение обычные дополнения ...
Оператор возвращает std::string, поэтому не будет кандидатом в выражения, в которых строка не может быть преобразована в нужный тип. Например, этот operator+ не подходит для использования с + в int x = 5 + 7;. Учитывая все обстоятельства, я бы не стал определять такой оператор без веской причины очень, но моей целью было предложить ответ, отличный от других.
Вы правы (я только что проверил ...). И когда я пытался сделать что-то вроде строка s = 5 + 7, у меня возникала ошибка недопустимое преобразование из int в const char ’*
В большинстве случаев использования шаблонов, которые связывают левый или правый операнд со строкой (включая std::string, std::string_view и const char *), должно быть достаточно.
В 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 Как насчет name += std::to_string(age + 0LL);?
Я написал функцию, которая принимает число 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!
Вы можете объединить 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.
Эту проблему можно решить разными способами. Я покажу это двумя способами:
Преобразуйте число в строку с помощью to_string(i).
Использование строковых потоков.
Код:
#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;
}
Какой из них быстрее?
#include <sstream> std::ostringstream s; s << "John " << age; std::string query(s.str());
std::string query("John " + std::to_string(age));
#include <boost/lexical_cast.hpp> std::string query("John " + boost::lexical_cast<std::string>(age));
Какой самый быстрый?
В качестве одного лайнера: name += std::to_string(age);
Позвольте мне добавить к этому: я пробовал 'str = "hi"; стр + = 5; cout << str; ' и не увидел никакого эффекта. Оказывается, это вызывает оператор + = (char) и добавляет непечатаемый символ.