Làm thế nào để nối một chuỗi std :: và int?


655

Tôi nghĩ rằng điều này sẽ thực sự đơn giản nhưng nó có một số khó khăn. Nếu tôi có

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

Làm cách nào để kết hợp chúng để có được một chuỗi "John21"?


Herb Sutter có một bài viết hay về chủ đề này: "The String Formatters of Manor Farm" . Ông đã bao gồm Boost::lexical_cast, std::stringstream, std::strstream(mà bị phản đối), và sprintfvs snprintf.
Fred Larson

Hãy để tôi thêm vào điều này: Tôi đã thử 'str = "hi"; str + = 5; cout << str; ' và thấy không có tác dụng. Hóa ra toán tử gọi này + = (char) và thêm một ký tự không in được.
daveagp

Câu trả lời:


1125

Theo thứ tự bảng chữ cái:

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. là an toàn, nhưng chậm; yêu cầu Boost (chỉ tiêu đề); hầu hết / tất cả các nền tảng
  2. là an toàn, yêu cầu C ++ 11 ( to_opes () đã được bao gồm trong #include <string>)
  3. là an toàn, và nhanh chóng; yêu cầu FastFormat , phải được biên dịch; hầu hết / tất cả các nền tảng
  4. ( ditto )
  5. là an toàn, và nhanh chóng; yêu cầu thư viện {fmt} , có thể được biên dịch hoặc sử dụng trong chế độ chỉ tiêu đề; hầu hết / tất cả các nền tảng
  6. an toàn, chậm và dài dòng; yêu cầu #include <sstream>(từ tiêu chuẩn C ++)
  7. là dễ vỡ (bạn phải cung cấp một bộ đệm đủ lớn), nhanh và dài dòng; itoa () là tiện ích mở rộng không chuẩn và không được bảo đảm khả dụng cho tất cả các nền tảng
  8. là dễ vỡ (bạn phải cung cấp một bộ đệm đủ lớn), nhanh và dài dòng; không yêu cầu gì (là tiêu chuẩn C ++); tất cả các nền tảng
  9. là dễ vỡ (bạn phải cung cấp một bộ đệm đủ lớn), có thể là chuyển đổi nhanh nhất có thể , dài dòng; yêu cầu STLSoft (chỉ tiêu đề); hầu hết / tất cả các nền tảng
  10. safe-ish (bạn không sử dụng nhiều hơn một cuộc gọi int_to_opes () trong một câu lệnh), nhanh chóng; yêu cầu STLSoft (chỉ tiêu đề); Chỉ dành cho Windows
  11. là an toàn, nhưng chậm; yêu cầu Poco C ++ ; hầu hết / tất cả các nền tảng

13
Ngoài một liên kết bạn đã gfiven, bạn dựa trên những nhận xét về hiệu suất của bạn là gì?
JamieH

2
Đó gần như toàn bộ danh tiếng của bạn từ một câu trả lời duy nhất !! Bạn may mắn đậu;) Tôi nghĩ 8 là tiêu chuẩn C (tất nhiên cũng là C ++), nhưng có lẽ là giá trị khác biệt.
noelicus

2. chậm khi std :: to_opes (age) tạo ra một chuỗi tạm thời được gắn vào kết quả.
Igor Bukanov

Nếu bạn đang dùng Arduino, bạn cũng có thể sử dụng String(number).
Machado

266

Trong C ++ 11, bạn có thể sử dụng std::to_string, ví dụ:

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

Tôi thích cái này, đơn giản. Cảm ơn.
Truthadjustr

85

Nếu bạn có Boost, bạn có thể chuyển đổi số nguyên thành chuỗi bằng cách sử dụng boost::lexical_cast<std::string>(age).

Một cách khác là sử dụng chuỗi dòng:

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

Cách tiếp cận thứ ba sẽ là sử dụng sprintfhoặc snprintftừ thư viện C.

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

Áp phích khác đề nghị sử dụng itoa. Đây KHÔNG phải là một chức năng tiêu chuẩn, vì vậy mã của bạn sẽ không thể di động nếu bạn sử dụng nó. Có những trình biên dịch không hỗ trợ nó.


Lưu ý rằng snprintf không được đảm bảo để chấm dứt chuỗi. Đây là một cách để đảm bảo nó hoạt động: <pre> char buffer [128]; bộ đệm [sizeof (bộ đệm) -1] = '\ 0'; snprintf (bộ đệm, sizeof (bộ đệm) -1, "% s% d", name.c_str (), tuổi); std :: cout << đệm << std :: endl; </ pre>
Mr Fooz

Xu hướng của tôi sẽ là không bao giờ sử dụng sprintf, vì điều này có thể dẫn đến tràn bộ đệm. Ví dụ trên là một ví dụ điển hình trong đó sử dụng sprintf sẽ không an toàn nếu tên quá dài.
terson

lưu ý rằng snprintf là c ++ không chuẩn (như itoa mà bạn đề cập). nó được lấy từ c99
Johannes Schaub - litb

@terson: Tôi chỉ thấy không có sự xuất hiện của sprintfcâu trả lời snprintf.
David foerster

80
#include <iostream>
#include <sstream>

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

2
điều này thật tuyệt vời, tập tin tiêu đề BYT là
sux

52
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
string itos(int i) // convert int to string
{
    stringstream s;
    s << i;
    return s.str();
}

Bị đánh cắp một cách đáng xấu hổ từ http://www.research.att.com/~bs/bs_faq2.html .


nhưng s là một biến stack, bộ nhớ của ssẽ được miễn phí sau khi gọi itos. sNên phân bổ từ đống, và freesau khi sử dụng, phải không?
kgbook

1
trả về theo giá trị là ok mặc dù đối tượng chuỗi đã vượt quá phạm vi, stackoverflow.com/a/3977119/5393174
kgbook


23

Nếu bạn có C ++ 11, bạn có thể sử dụng std::to_string .

Thí dụ:

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

name += std::to_string(age);

std::cout << name;

Đầu ra:

John21

2
Nó sẽ có name += std::to_string(static_cast<long long>(age));trong VC ++ 2010 như bạn có thể thấy ở đây
neonmate

@neonmate Làm thế nào về name += std::to_string(age + 0LL);thay thế?
chux - Phục hồi Monica

18

Dường như với tôi rằng câu trả lời đơn giản nhất là sử dụng sprintfhàm:

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

1
snprintf có thể khó khăn (chủ yếu vì nó có khả năng không bao gồm ký tự null trong một số tình huống nhất định), nhưng tôi thích điều đó để tránh bộ đệm sprintf vượt qua các vấn đề tiềm ẩn.
terson

3
sprintf (char *, const char *, ...) sẽ thất bại trên một số phiên bản trình biên dịch khi bạn chuyển một chuỗi std :: sang% s. Tuy nhiên, không phải tất cả (đó là hành vi không xác định) và nó có thể phụ thuộc vào độ dài chuỗi (SSO). Vui lòng sử dụng .c_str ()
MSalters

cộng với sprintf có thể bị tràn bộ đệm để có thể tiêm mã
Jean-François Fabre

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

Sau đó, việc sử dụng của bạn sẽ trông giống như thế này

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

Googled [và đã thử nghiệm: p]


10

Vấn đề này có thể được thực hiện theo nhiều cách. Tôi sẽ chỉ cho nó theo hai cách:

  1. Chuyển đổi số thành chuỗi bằng cách sử dụng to_string(i).

  2. Sử dụng các chuỗi chuỗi.

    Mã số:

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

Cái nào nhanh hơn?
GyuHyeon Choi

7

Nếu bạn muốn sử dụng +để ghép bất cứ thứ gì có toán tử đầu ra, bạn có thể cung cấp phiên bản mẫu của operator+:

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

Sau đó, bạn có thể viết các kết nối của bạn một cách đơn giản:

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

Đầu ra:

the answer is 42

Đây không phải là cách hiệu quả nhất, nhưng bạn không cần cách hiệu quả nhất trừ khi bạn thực hiện nhiều thao tác nối trong vòng lặp.


Nếu tôi cố gắng thêm vào số nguyên hoặc số nguyên và gấp đôi, hàm này có được gọi không? Tôi tự hỏi liệu giải pháp này sẽ ghi đè lên các bổ sung thông thường ...
Hilder Vitor Lima Pereira

Toán tử trả về a std::string, do đó sẽ không phải là ứng cử viên trong các biểu thức trong đó một chuỗi không thể chuyển đổi thành loại cần thiết. Ví dụ, điều này operator+là không đủ điều kiện để được sử dụng cho +trong int x = 5 + 7;. Tất cả mọi thứ được xem xét, tôi sẽ không định nghĩa một nhà điều hành như thế này mà không có lý do rất thuyết phục, nhưng mục đích của tôi là đưa ra một câu trả lời khác với những người khác.
uckelman

Bạn nói đúng (tôi vừa thử nó ...). Và khi tôi cố gắng làm một cái gì đó như chuỗi s = 5 + 7 , tôi đã nhận được lỗi chuyển đổi không hợp lệ từ 'int' sang 'const char ' *
Hilder Vitor Lima Pereira

5

Nếu bạn đang sử dụng MFC, bạn có thể sử dụng CString

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

Managed C ++ cũng có một bộ định dạng chuỗi .


4

Std :: Ostringstream là một phương pháp tốt, nhưng đôi khi thủ thuật bổ sung này có thể giúp chuyển đổi định dạng thành một lớp lót:

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

Bây giờ bạn có thể định dạng các chuỗi như thế này:

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

4

Vì một câu hỏi liên quan đến Qt đã được đóng lại có lợi cho câu hỏi này, đây là cách thực hiện bằng Qt:

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

Biến chuỗi bây giờ có giá trị someIntVariable thay cho% 1 và giá trị someOtherIntVariable ở cuối.


QString ("Something") + QString :: number (someIntVariable) cũng hoạt động
gremwell

3

Có nhiều tùy chọn có thể sử dụng để nối số nguyên (hoặc đối tượng số khác) với chuỗi. Đó là 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);
}

và Karma từ Boost.Sprite (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.Sprite Karma tuyên bố là một trong những lựa chọn nhanh nhất để chuyển đổi số nguyên sang chuỗi .



3

Bạn có thể nối int thành chuỗi bằng cách sử dụng thủ thuật đơn giản dưới đây, nhưng lưu ý rằng điều này chỉ hoạt động khi số nguyên có một chữ số. Nếu không, thêm chữ số nguyên bằng chữ số vào chuỗi đó.

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

Output:  John5

2

Dưới đây là cách triển khai cách nối int vào chuỗi bằng cách sử dụng các khía cạnh phân tích cú pháp và định dạng từ thư viện 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
}

2
  • std :: xương
#include <sstream>

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

Cái nào nhanh nhất?
GyuHyeon Choi

2

Có một hàm tôi đã viết, lấy số int làm tham số và chuyển đổi nó thành một chuỗi bằng chữ. Hàm này phụ thuộc vào một hàm khác có thể chuyển đổi một chữ số thành tương đương char của nó:

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

Với thư viện {fmt} :

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

Một tập hợp con của thư viện được đề xuất để chuẩn hóa là Định dạng văn bản P0645 và, nếu được chấp nhận, phần trên sẽ trở thành:

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

Tuyên bố miễn trừ trách nhiệm : Tôi là tác giả của thư viện {fmt}.


0

Như một lớp lót: name += std::to_string(age);


3
Đó là mã giống như trong câu trả lời 0x499602D2.
BDL
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.