如何串联一个std :: string和一个int?


655

我以为这真的很简单,但是却带来了一些困难。如果我有

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

如何将它们组合成一个字符串"John21"


赫伯·萨特(Herb Sutter)在这个主题上有一篇很好的文章:“庄园农场的弦乐格式化者”。他介绍Boost::lexical_caststd::stringstreamstd::strstream(这是不建议使用),以及sprintfsnprintf
弗雷德·拉森

让我补充一下:我尝试过'str =“ hi”; str + = 5; cout << str;' 并没有看到效果。原来这会调用operator + =(char)并添加一个不可打印的字符。
daveagp 2014年

Answers:


1125

按字母顺序:

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. 同上
  5. 安全,快速;需要{fmt}库,该可以编译或在仅标头模式下使用;大多数/所有平台
  6. 安全,缓慢且冗长;需要#include <sstream>(来自标准C ++)
  7. 脆弱(必须提供足够大的缓冲区),快速且冗长;itoa()是非标准扩展,并不保证可用于所有平台
  8. 脆弱(必须提供足够大的缓冲区),快速且冗长;不需要任何东西(是标准的C ++);所有平台
  9. 非常脆弱(您必须提供足够大的缓冲区),可能是最快可能的转换,冗长;需要STLSoft(仅标头);大多数/所有平台
  10. 安全可靠(在单个语句中不要使用多个int_to_string()调用),快速;需要STLSoft(仅标头);仅Windows
  11. 安全,但速度慢;需要Poco C ++ ; 大多数/所有平台

13
除了您所提供的一个链接之外,您还基于什么表现评论?
JamieH

2
一个答案几乎就是您的全部声誉!!幸运豆;)我认为8是标准C(当然也是C ++),但可能值得区分。
noelicus

2.速度很慢,因为std :: to_string(age)创建一个临时字符串,该字符串将附加到结果中。
伊戈尔·布卡诺夫

如果您使用Arduino,也可以使用String(number)
马查多

267

在C ++ 11中,您可以使用std::to_string,例如:

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

我喜欢这个,简单。谢谢。
Trudadjustr

85

如果您有Boost,可以使用以下命令将整数转换为字符串 boost::lexical_cast<std::string>(age)

另一种方法是使用字符串流:

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

第三种方法是使用C库sprintf或使用snprintfC库。

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

其他海报建议使用itoa。这不是标准功能,因此如果使用它,代码将无法移植。有些编译器不支持它。


请注意,snprintf不能保证以空值终止该字符串。这是确保其工作的一种方法:<pre> char buffer [128]; buffer [sizeof(buffer)-1] ='\ 0'; snprintf(buffer,sizeof(buffer)-1,“%s%d”,name.c_str(),age); std :: cout <<缓冲区<< std :: endl; </ pre>
Fooz先生08年

我的趋势是永远不要使用sprintf,因为这会导致缓冲区溢出。上面的示例是一个很好的示例,如果名称很长,则使用sprintf将是不安全的。
terson

请注意,snprintf同样是非标准的c ++(例如您提到的itoa)。它取自c99
Johannes Schaub-litb

@terson:我认为sprintf答案中没有snprintf
David Foerster




23

如果您拥有C ++ 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,你可以看到在这里
neonmate

@neonmate name += std::to_string(age + 0LL);呢?
chux-恢复莫妮卡

18

在我看来,最简单的答案是使用该sprintf函数:

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

1
snprintf可能很棘手(主要是因为在某些情况下它可能不包含空字符),但是我更希望避免sprintf缓冲区溢出潜在的问题。
terson

3
当您将std :: string传递给%s时,sprintf(char *,const char *,...)在某些版本的编译器上将失败。并非全部(这是未定义的行为),并且可能取决于字符串长度(SSO)。请使用.c_str()
MSalters

加的sprintf是受到缓冲区溢出,从而可能的代码注入
让弗朗索瓦法布尔

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

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]


10

这个问题可以用很多方法来解决。我将以两种方式展示它:

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

哪一个更快?
GyuHyeon Choi

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

这不是最有效的方法,但是除非您在循环内进行大量串联操作,否则您不需要最有效的方法。


如果我尝试将整数相加,或者将整数与双精度数相加,会将此函数称为吗?我想知道这种解决方案是否会取代通常的添加方法……
Hilder Vitor Lima Pereira

该运算符返回一个std::string,因此不会成为无法将字符串转换为所需类型的表达式的候选对象。例如,这operator+不适合+在中使用 int x = 5 + 7;。考虑到所有因素,我不会在没有非常令人信服的理由的情况下定义这样的运算符,但我的目标是提供与其他答案不同的答案。
uckelman '16

您是对的(我刚刚测试过...)。当我尝试执行类似字符串s = 5 + 7的操作时,我得到了从'int'到'const char '* 的错误无效转换
Hilder Vitor Lima Pereira


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

由于与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

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)的Karma

#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声称是整数到字符串转换的最快选择之一



3

您可以使用下面给出的简单技巧将int连接到字符串,但是请注意,这仅在integer为一位数字时才有效。否则,将整数逐个数字地添加到该字符串。

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

Output:  John5

2

这是一个如何使用IOStreams库中的解析和格式化方面将int附加到字符串的实现。

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

2
  • 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));

哪一个最快?
GyuHyeon Choi

2

我写了一个函数,该函数将int数字作为参数,并将其转换为字符串文字。此函数依赖于另一个将一位数字转换为其等效char的函数:

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

1

使用{fmt}库

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

建议将该库的子集标准化为P0645文本格式,如果被接受,则以上内容将变为:

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

免责声明:我是{fmt}库的作者。


0

作为一个班轮: name += std::to_string(age);


3
这与0x499602D2答案中的代码相同。
BDL
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.