Câu hỏi Cách dễ nhất để chuyển đổi int thành chuỗi trong C ++


Cách dễ nhất để chuyển đổi từ int tương đương string trong C ++. Tôi biết hai phương pháp. Có cách nào dễ hơn không?

(1)

int a = 10;
char *intStr = itoa(a);
string str = string(intStr);

(2)

int a = 10;
stringstream ss;
ss << a;
string str = ss.str();

1212
2018-04-08 04:19


gốc


Tôi nghĩ rằng cả hai phương pháp bạn đưa ra là giải pháp tốt. nó phụ thuộc vào bối cảnh mà bạn cần làm. Nếu bạn đã làm việc với các luồng, ví dụ như đọc hoặc viết một tệp, thì phương pháp thứ hai của bạn là tốt nhất. Nếu bạn cần truyền một int như một chuỗi cho một đối số hàm, thì itoa có thể là một cách dễ dàng. Nhưng hầu hết thời gian, int để chuyển đổi chuỗi xảy ra khi giao dịch với các tập tin, do đó, suối là thích hợp. - Charles Brunet
Làm thế nào tùy chọn 1 thậm chí làm việc cho bạn ở tất cả? Đó là sự hiểu biết của tôi rằng itoa() có ba tham số. - b1nary.atr0phy
itoa sẽ nhanh hơn luồng tương đương. Ngoài ra còn có cách tái sử dụng bộ đệm chuỗi với phương pháp itoa (tránh phân bổ heap nếu bạn thường xuyên tạo chuỗi. Ví dụ: để cập nhật nhanh chóng số lượng đầu ra số). Ngoài ra, bạn có thể tạo ra một streambuf tùy chỉnh để giảm bớt một số chi phí phân bổ vv Xây dựng các dòng suối ở nơi đầu tiên cũng không phải là một chi phí thấp liên doanh. - Pete
@Pete: Một khi bạn bắt đầu lo lắng về điều đó nhanh hơn, bạn sẽ muốn xem xét stackoverflow.com/questions/4351371/… - Ben Voigt
Lưu ý rằng itoa () không phải là một phần của tiêu chuẩn và do đó sử dụng nó làm cho mã của bạn không di động vì không phải tất cả các trình biên dịch đều hỗ trợ nó. Đối với Linux, bạn chắc chắn nhất là trừ khi bạn đang sử dụng một cái gì đó khác hơn là GCC, mà không hỗ trợ chức năng này. Nếu bạn có C ++ 0x, hãy làm theo những gì @Matthieu đã gợi ý trong câu trả lời của mình. Nếu đó không phải là trường hợp, đi với stringstream vì nó là một tính năng được hỗ trợ tốt và mã của bạn nên tương thích với mọi trình biên dịch C ++ trên mạng. Thay vào đó, bạn luôn có thể sử dụng sprintf (). - rbaleksandar


Các câu trả lời:


Giới thiệu C ++ 11 std::stoi (và các biến thể cho từng loại số) và std::to_string, các đối tác của C atoi và itoa nhưng được thể hiện dưới dạng std::string.

#include <string> 

std::string s = std::to_string(42);

do đó, cách ngắn nhất tôi có thể nghĩ đến. Bạn thậm chí có thể bỏ qua việc đặt tên loại, bằng cách sử dụng auto từ khóa:

auto s = std::to_string(42);

Lưu ý: xem [string.conversions] (21,5 trong n3242)


1597
2018-04-08 06:13



to_string không phải là thành viên của std sửa chữa: stackoverflow.com/questions/12975341/… - Ben
Hoặc tùy thuộc vào trình biên dịch của bạn, chỉ cần đặt tiêu chuẩn ngôn ngữ phù hợp: g++ -std=c++11 someFile.cc - Thomas M. DuBuisson
@Steve: nó được cho là vậy. Đó là thành viên của std trong mọi trình biên dịch tôi biết ngoại trừ một trình biên dịch. - Mooing Duck
@ Matthiew M. Tôi đang sử dụng cùng một mà bạn đề nghị nhưng tôi nhận được lỗi này: Error : No instance of overloaded function "std::to_string" matches the argument list  tôi đang sử dụng VS2010 c ++
@Flying: dưới VS2010 bạn phải rõ ràng truyền số nguyên chuyển đổi sang một trong các loại sau đây [_Longlong, _ULonglong, long double]; I E: string s = to_string((_ULonglong)i); - Zac


Chọn một cuộc thảo luận với @ v.oddou một vài năm sau đó, C ++ 17 cuối cùng đã phân phối một cách để thực hiện giải pháp dựa trên vĩ mô ban đầu dựa trên vĩ mô (được bảo tồn bên dưới) không có trải qua tình trạng xấu xí của macro.

template < typename... Args >
std::string sstr( Args &&... args )
{
    std::ostringstream sstr;
    ( sstr << std::dec << ... << args );
    return sstr.str();
}

Sử dụng:

int i = 42;
std::string s = sstr( "i is: ", i );
puts( sstr( i ).c_str() );

Foo x( 42 );
throw std::runtime_error( sstr( "Foo is '", x, "', i is ", i ) );

Câu trả lời gốc:

Vì "chuyển đổi ... thành chuỗi" là một vấn đề định kỳ, tôi luôn xác định SSTR () macro trong tiêu đề trung tâm của nguồn C ++ của tôi:

#include <sstream>

#define SSTR( x ) static_cast< std::ostringstream & >( \
        ( std::ostringstream() << std::dec << x ) ).str()

Cách sử dụng dễ dàng như có thể là:

int i = 42;
std::string s = SSTR( "i is: " << i );
puts( SSTR( i ).c_str() );

Foo x( 42 );
throw std::runtime_error( SSTR( "Foo is '" << x << "', i is " << i ) );

Ở trên là C ++ 98 tương thích (nếu bạn không thể sử dụng C ++ 11 std::to_string) và không cần bất kỳ bên thứ ba nào bao gồm (nếu bạn không thể sử dụng Boost) lexical_cast<>); cả hai giải pháp khác này đều có hiệu suất tốt hơn.


165
2018-04-08 04:23



Tôi không quen lắm dynamic_cast nhưng tôi đang sử dụng tiếng kêu để biên dịch nên nó phàn nàn về nó. Nếu tôi chỉ bỏ qua dynamic_castsau đó nó biên dịch tốt; mục đích gì dynamic_cast phục vụ trong trường hợp này? Chúng tôi đã tạo một ostringstream, vậy tại sao lại chọn nó? - Mathew
@Mathew: Liên kết trong câu trả lời của tôi dẫn đến mô tả chi tiết về từng phần của cấu trúc. Trong khi chúng tôi tạo một ostringstream, chúng tôi đã gọi operator<<() trên đó, trả về ostream & -- mà .str() không được xác định. Tôi thực sự tự hỏi làm thế nào kêu vang sẽ làm cho công việc này mà không có diễn viên (hoặc tại sao nó tạo ra một lỗi với nó). Cấu trúc này được xuất bản ở nhiều nơi, và tôi đã sử dụng nó trong hơn một thập kỷ trên nhiều trình biên dịch khác nhau, bao gồm MSVC, GCC, và XLC, vì vậy tôi khá ngạc nhiên với những tiếng lẩm bẩm ở đó. - DevSolar
Chỉ cần đến bên cho sự tò mò, và downvoted. Lý do: quá nhiều phiếu bầu cho giải pháp không thanh lịch và có thể chậm. 1. sử dụng macro. Tôi không có hệ thống cau mày trên bất kỳ macro nào, nhưng cái này quá ngắn và khách hàng cuối luôn luôn sợ sự lặp lại của đối số, trên đầu trang của sự sợ hãi đối với các macro nhiều dòng không được bảo vệ. (không được bảo vệ bởi do {} trong khi (0)) 2. dynamic_cast. có vẻ như bạn chỉ cần một static_cast ở đây, trừ khi bạn muốn khẳng định rằng thư viện thực sự được thực hiện như bạn hy vọng. trong trường hợp này bạn nên sử dụng boost :: polymorphic_downcast thay thế. - v.oddou
@ v.oddou: Tất nhiên là bạn hoàn toàn miễn phí. Nhưng 1. không hợp lệ - macro là một câu lệnh duy nhất, do { } while( 0 ) sẽ không thêm bất cứ điều gì. Với 2. và 3. bạn có thể có một điểm - điều này có thể được thực hiện với một diễn viên tĩnh, và có lẽ một trong các bạn thuật sĩ mẫu ra có thể đưa ra một giao diện "đẹp hơn". Nhưng như tôi đã nói, đây không phải là một phát minh của bản thân tôi. Nhìn xung quanh, macro này (macro!) Khá phổ biến. Đó là trường hợp của POLA. Tôi có thể đồ chơi với điều này một chút để làm cho nó "hợp lý hơn". - DevSolar
@ v.oddou: Hãy nhìn vào những gì tôi tìm thấy trong số những điều C ++ 17 mang đến cho chúng tôi. :-) Tôi hy vọng bạn thích câu trả lời cập nhật. - DevSolar


Tôi thường sử dụng phương pháp sau:

#include <sstream>

template <typename T>
  std::string NumberToString ( T Number )
  {
     std::ostringstream ss;
     ss << Number;
     return ss.str();
  }

được mô tả chi tiết đây.


96
2017-11-29 22:46



Trước khi sử dụng ss, bạn cần phải ss.clear() nó. Tôi đã nhìn thấy kết quả không mong muốn mà không cần khởi tạo này. - lifebalance
@ lifebalance: Tôi chưa bao giờ thấy hành vi như vậy. - Rasoul
@ lifebalance: Bạn không cần phải clear() mới được tạo ostringstream vật. clear() đặt lại cờ lỗi / eof và chưa có bất kỳ lỗi / điều kiện eof nào được tạo ra. - Remy Lebeau
Bạn đã bao giờ thử với char? - Wolf
@Rasoul NumberToString(23213.123) sản xuất 23213.1 trong khi std::to_string(23213.123) sản xuất 23213.123000 Điều gì xảy ra ở đó? - Killzone Kid


Có lẽ cách dễ nhất phổ biến nhất kết thúc tốt đẹp về cơ bản lựa chọn thứ hai của bạn vào một mẫu có tên lexical_cast, chẳng hạn như một trong Tăng cường, vì vậy mã của bạn trông như thế này:

int a = 10;
string s = lexical_cast<string>(a);

Một trong số đó là nó cũng hỗ trợ các phôi khác (ví dụ, theo hướng ngược lại cũng hoạt động tốt).

Cũng lưu ý rằng mặc dù Boost lexical_cast bắt đầu như chỉ viết vào một chuỗi, sau đó trích xuất trở lại ra khỏi dòng, nó bây giờ có một vài bổ sung. Trước hết, các chuyên môn cho một vài loại đã được thêm vào, vì vậy đối với nhiều loại phổ biến, nó nhanh hơn đáng kể so với việc sử dụng một chuỗi. Thứ hai, nó bây giờ kiểm tra kết quả, vì vậy (ví dụ) nếu bạn chuyển đổi từ một chuỗi thành một int, nó có thể ném một ngoại lệ nếu chuỗi chứa một thứ không thể chuyển đổi thành int (ví dụ., 1234 sẽ thành công, nhưng 123abc sẽ ném).

Kể từ C ++ 11, có một std::to_string chức năng quá tải cho các loại số nguyên, vì vậy bạn có thể sử dụng mã như:

int a = 20;
std::string s = to_string(a);

Tiêu chuẩn xác định các tiêu chí này tương đương với việc thực hiện chuyển đổi với sprintf (sử dụng trình chỉ định chuyển đổi phù hợp với loại đối tượng được cung cấp, chẳng hạn như %d cho int), vào bộ đệm đủ kích thước, sau đó tạo std::string nội dung của bộ đệm đó.


84
2018-04-08 04:23



Nice, tôi thích câu trả lời của Kevin, mặc dù anh ta cho thấy bao gồm và không gian tên. Chỉ là một cái kẹp nhỏ. :) Tốt lắm! - Jason R. Mick
Tôi muốn nói đây là cách để đi nếu bạn không có hỗ trợ C ++ 11. - Alex
Liên kết Boost bị hỏng. - Kris Hollenbeck


Nếu bạn đã cài đặt Boost (bạn nên sử dụng):

#include <boost/lexical_cast.hpp>

int num = 4;
std::string str = boost::lexical_cast<std::string>(num);

40
2018-04-08 04:26



Đồng ý về cài đặt tăng cường. Tôi nghĩ rằng thường xuyên hơn một người sẽ định dạng chuỗi. Với mục đích này, tôi thích tăng :: định dạng e.g định dạng ("% 02d", số) .str () - Werner Erasmus


Nó sẽ không được dễ dàng hơn bằng cách sử dụng stringstreams?

#include <sstream>

int x=42;            //The integer
string str;          //The string
ostringstream temp;  //temp as in temporary
temp<<x;
str=temp.str();      //str is temp as string

Hoặc thực hiện một chức năng:

#include <sstream>

string IntToString (int a)
{
    ostringstream temp;
    temp<<a;
    return temp.str();
}

27
2018-04-16 19:37





Không phải là tôi biết, trong C ++ thuần túy. Nhưng một chút sửa đổi về những gì bạn đã đề cập

string s = string(itoa(a));

nên làm việc, và nó khá ngắn.


19
2018-04-08 04:22



itoa() không phải là một chức năng tiêu chuẩn! - cartoonist
@cartoonist: Vậy thì nó là gì? - Mehrdad
Hàm này không được định nghĩa trong ANSI-C và C ++. Vì vậy, nó không được hỗ trợ bởi một số trình biên dịch như g ++. - cartoonist


sprintf() khá tốt cho việc chuyển đổi định dạng. Sau đó bạn có thể gán chuỗi C kết quả cho chuỗi C ++ như bạn đã làm trong 1.


16
2018-04-08 04:23



và hy vọng bộ đệm bạn sử dụng đủ lớn ... - Matthieu M.
Heh, vâng. Tuy nhiên, tôi thường dựa vào snprintf () và bạn bè cho bất cứ điều gì do hậu quả khi xử lý các chuỗi C. - Throwback1986
@MatthieuM. Nhận xét của bạn chứng tỏ thêm, rằng bạn không. Nếu đầu ra bị cắt ngắn do giới hạn này thì giá trị trả về là số ký tự (không bao gồm byte null kết thúc) mà sẽ được ghi vào chuỗi cuối cùng nếu đủ dung lượng trống. Do đó, giá trị trả về của kích thước hoặc nhiều hơn có nghĩa là đầu ra đã bị cắt bớt. Vì vậy, bạn gọi nó với một NULL và kích thước bằng không để có được kích thước bộ đệm cần thiết. - user1095108
@ user1095108: Tôi nghĩ bạn đang nhầm lẫn snprintf (lưu ý SNP tiền tố) và sprintf (lưu ý SP tiếp đầu ngữ). Bạn vượt qua kích thước để trước đây, và nó sẽ chăm sóc không tràn, tuy nhiên sau này không biết kích thước của bộ đệm và do đó có thể tràn. - Matthieu M.
Ý tưởng là gọi một snprintf biến thể đầu tiên và sprintf biến thể sau đó. Khi kích thước bộ đệm được biết đến lúc đó, gọi sprintf trở nên hoàn toàn an toàn. - user1095108


Đầu tiên bao gồm:

#include <string>
#include <sstream>

Thứ hai thêm phương thức:

template <typename T>
string NumberToString(T pNumber)
{
 ostringstream oOStrStream;
 oOStrStream << pNumber;
 return oOStrStream.str();
}

Sử dụng phương pháp như sau:

NumberToString(69);

hoặc là

int x = 69;
string vStr = NumberToString(x) + " Hello word!."

12
2018-05-31 21:32





Bạn có thể dùng std::to_string có sẵn trong C ++ 11 như đề xuất bởi Matthieu M.:

std::to_string(42);

Hoặc, nếu hiệu suất là rất quan trọng (ví dụ: nếu bạn thực hiện nhiều chuyển đổi), bạn có thể sử dụng fmt::FormatInt từ Định dạng C ++ thư viện để chuyển đổi một số nguyên thành std::string:

fmt::FormatInt(42).str();

Hoặc một chuỗi C:

fmt::FormatInt f(42);
f.c_str();

Sau này không thực hiện bất kỳ phân bổ bộ nhớ động nào và nhanh hơn 10 lần so với std::to_string trên các tiêu chuẩn Boost Karma. Xem Chuyển đổi chuỗi số nguyên nhanh thành C ++ để biết thêm chi tiết.

không giống std::to_string, fmt::FormatInt không yêu cầu C ++ 11 và làm việc với bất kỳ trình biên dịch C ++ nào.

Disclaimer: Tôi là tác giả của thư viện định dạng C ++.


9
2018-05-25 13:42



Nó có an toàn không? - Soren
@ Soren: Vâng, đó là chủ đề an toàn. - vitaut
Tôi đã tò mò về yêu cầu bồi thường không có bất kỳ phân bổ bộ nhớ động nào trong khi vẫn duy trì luồng (tái nhập cảnh), vì vậy tôi đọc mã của bạn - c_str() trả về một con trỏ tới một bộ đệm được khai báo bên trong fmt::FormatInt lớp - vì vậy con trỏ trả về sẽ không hợp lệ tại dấu chấm phẩy - xem thêm stackoverflow.com/questions/4214153/lifetime-of-temporaries - Soren
Có, hành vi tương tự như với std::string::c_str() (do đó đặt tên). Nếu bạn muốn sử dụng nó bên ngoài biểu thức đầy đủ, hãy xây dựng một đối tượng FormatInt f(42); Sau đó, bạn có thể sử dụng f.c_str() không có nguy cơ bị phá hủy. - vitaut
Tôi nhận được một cái gì đó kỳ lạ khi tôi cố gắng để chuyển đổi từ int để chuỗi bằng cách sử dụng std :: to_string (num). Nếu tôi lưu trữ kết quả trong một biến và cố gắng truy cập vào nó như stringNum [1] hoặc stringNum [n] khi n tăng lên, tôi nhận được rác. - user8951490