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


1574

Cách dễ nhất để chuyển đổi từ inttương đương stringtrong C ++ là gì. Tôi nhận thức được hai phương pháp. Có cách nào dễ dàng 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();

4
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 điều đó. 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 dưới dạng 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, chuyển đổi int thành chuỗi xảy ra khi xử lý các tệp, vì vậy các luồng là phù hợp.
Charles Brunet

41
Làm thế nào để tùy chọn 1 thậm chí làm việc cho bạn cả? Đó là sự hiểu biết của tôi itoa()có ba tham số.
b1nary.atr0phy

1
itoa sẽ nhanh hơn luồng tương đương. Ngoài ra còn có cách sử dụng lại bộ đệm chuỗi bằng phương thức itoa (tránh phân bổ heap nếu bạn thường xuyên tạo chuỗi. Ví dụ: đối với một số đầu ra số cập nhật nhanh). Ngoài ra, bạn có thể tạo một streambuf tùy chỉnh để giảm một số chi phí phân bổ, v.v. Xây dựng luồng ở vị trí đầu tiên cũng không phải là một liên doanh chi phí thấp.
Pete

6
@Pete: Một khi bạn bắt đầu lo lắng về cái nào nhanh hơn, bạn sẽ muốn xem stackoverflow.com/questions/4351371/ Kẻ
Ben Voigt

20
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 khả chuyển 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 sẽ ra ngoài trừ khi bạn đang sử dụng một thứ khác ngoài GCC, không hỗ trợ chức năng này. Nếu bạn có C ++ 0x, hãy đi với những gì @Matthieu đã gợi ý trong câu trả lời của anh ấy. Nếu không phải như vậy, hãy sử dụng chuỗi dòng vì đây là một tính năng được hỗ trợ tốt và mã của bạn phải tương thích với mọi trình biên dịch C ++ ngoài kia. Thay thế, bạn luôn có thể đi với sprintf ().
rbaleksandar

Câu trả lời:


2102

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

#include <string> 

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

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

auto s = std::to_string(42);

Lưu ý: xem [string.conversions] ( 21.5 trong n3242 )


199
to_stringkhông phải là thành viên của stdbản sửa lỗi: stackoverflow.com/questions/12975341/ Khăn
Ben

36
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

12
@Steve: đáng ra phải thế. Nó là thành viên của stdmọi trình biên dịch mà tôi biết ngoại trừ một trình biên dịch.
Vịt mướp

5
@Matthiew M. Tôi đang sử dụng chính cái mà bạn đề xuất nhưng tôi gặp 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 ++

19
@ Tìm kiếm: theo VS2010, bạn phải truyền rõ ràng số nguyên chuyển đổi thành một trong các loại sau [_Longlong, _ULonglong, long double]; tức là:string s = to_string((_ULonglong)i);
Zac

184

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 đã đưa ra một cách để thực hiện giải pháp loại bất khả tri dựa trên vĩ mô ban đầu (được bảo tồn bên dưới) mà không phải trải qua sự xấu xí vĩ mô.

// variadic template
template < typename... Args >
std::string sstr( Args &&... args )
{
    std::ostringstream sstr;
    // fold expression
    ( 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 đề lặp đi lặp lại, tôi luôn xác định macro SSTR () trong tiêu đề trung tâm của các nguồn C ++ của mình:

#include <sstream>

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

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

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à tương thích C ++ 98 (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 có hiệu suất tốt hơn mặc dù.


2
Tôi không quen thuộc lắm dynamic_castnhư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 bỏ qua dynamic_castthì nó sẽ biên dịch tốt; mục đích nào dynamic_castphục vụ trong trường hợp này? Chúng tôi đã tạo ra một ostringstream, vậy tại sao đúc nó?
Mathew

2
@Mathew: Liên kết trong câu trả lời của tôi dẫn đến một 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<<()nó, trả về ostream &- .str()không được xác định. Tôi thực sự tự hỏi làm thế nào clang 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 khi nói về nó.
DevSolar

5
Chỉ cần đến bữa tiệc vì tò mò, và bị hạ bệ. Lý do: quá nhiều phiếu cho một giải pháp không thanh lịch và có thể chậm. 1. sử dụng vĩ mô. Tôi không cau mày một cách có hệ thống 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 sợ sự lặp lại của cuộc tranh luận, trên hết là nỗi sợ hãi đối với các macro đa tuyến không được bảo vệ. (không được bảo vệ bởi do {} while (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 triển khai như bạn hy vọng. trong trường hợp đó bạn nên sử dụng boost :: polymorphic_downcast thay thế.
v.oddou

2
@ v.oddou: Tất nhiên, bạn được tự do phê bình. Nhưng 1. không hợp lệ - macro là một câu lệnh đơn, 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 dàn diễn viên tĩnh, và có lẽ một trong số các pháp sư mẫu của bạn có thể có 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. Nhìn xung quanh, macro này (macro!) Khá phổ biến. Bản thân đó là một 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ó "sắp xếp hợp lý" hơn.
DevSolar

1
@ v.oddou: Hãy nhìn vào những gì tôi tìm thấy trong số những thứ C ++ 17 mang lại cho chúng tôi. :-) Tôi hy vọng bạn thích câu trả lời cập nhật.
DevSolar

109

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

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


2
Trước khi sử dụng ss, bạn cần ss.clear()nó. Tôi đã thấy kết quả bất ngờ mà không cần khởi tạo này.
cuộc sống

14
@lifebalance: Tôi chưa bao giờ thấy hành vi như vậy.
Rasoul

18
@lifebalance: Bạn không cần đến clear()một ostringstreamđối tượng mới được tạo . clear()Đặt lại các cờ lỗi / eof và chưa có bất kỳ điều kiện lỗi / eof nào được tạo.
Remy Lebeau

2
@Rasoul NumberToString(23213.123)sản xuất 23213.1trong khi std::to_string(23213.123)sản xuất 23213.123000Điều gì xảy ra ở đó?
Killzone Kid

1
@KillzoneKid Điều này là do std 'Ostream là trạng thái (điều này có nghĩa là mọi thay đổi trạng thái trước đó được giữ, như số chữ số thập phân) trong khi phương thức này bắt đầu với trạng thái mặc định.
xryl669

85

Có lẽ cách dễ dàng phổ biến nhất bao bọc về cơ bản sự 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ẫu trong Boost , 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 điều thú vị của điều này là nó cũng hỗ trợ các diễn viên 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ỉ ghi vào một chuỗi, sau đó trích xuất ra khỏi luồng, nhưng bây giờ nó có một vài bổ sung. Trước hết, các chuyên ngành cho khá nhiều 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 sử dụng chuỗi. Thứ hai, bây giờ nó sẽ 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 chuỗi int, nó có thể ném ngoại lệ nếu chuỗi chứa thứ gì đó không thể chuyển đổi thành int(ví dụ: 1234sẽ thành công, nhưng 123abcsẽ ném) .

Kể từ C ++ 11, có một std::to_stringhàm bị quá tải cho các kiểu số nguyên, vì vậy bạn có thể sử dụng mã như:

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

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


2
Thật tuyệt, tôi thích câu trả lời của Kevin, mặc dù anh ấy cho thấy không gian bao gồm và không gian tên. Chỉ là một nắm nhỏ. :) Mặc dù vậy, công việc tốt!
Jason R. Mick

4
Tôi muốn nói rằng đây là con đường để đi nếu bạn không có hỗ trợ C ++ 11.
Alex

40

Nếu bạn đã cài đặt Boost (mà bạn nên):

#include <boost/lexical_cast.hpp>

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

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

28

Nó sẽ dễ dàng hơn bằng cách sử dụng chuỗi dòng:

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

18

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

string s = string(itoa(a));

nên hoạt động, và nó khá ngắn.


55
itoa()không phải là một chức năng tiêu chuẩn!
vẽ tranh biếm họa

4
@cartoonist: Thế thì sao?
dùng541686

20
Hàm này không được xác định 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 ++.
vẽ tranh biếm họa

17

Bạn có thể sử dụng std::to_stringcó sẵn trong C ++ 11 theo đề xuất của Matthieu M . :

std::to_string(42);

Hoặc, nếu hiệu suất là 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::format_inttừ thư viện {fmt} để chuyển đổi một số nguyên sang std::string:

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

Hoặc một chuỗi C:

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

Loại thứ hai 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điểm chuẩn Boost Karma. Xem Chuyển đổi số nguyên nhanh sang chuỗi trong C ++ để biết thêm chi tiết.

Lưu ý rằng cả hai đều an toàn chủ đề.

Không giống như std::to_string, fmt::format_intkhông yêu cầu C ++ 11 và hoạt động với bất kỳ trình biên dịch C ++ nào.

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


2
Tôi tò mò về tuyên bố không có phân bổ bộ nhớ động trong khi vẫn giữ nguyên luồng an toàn (được cấp lại), vì vậy tôi đã đọc mã của bạn - c_str()trả về một con trỏ tới bộ đệm được khai báo bên trong fmt::FormatIntlớp - vì vậy con trỏ được 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

1
Có, hành vi tương tự như với std::string::c_str()(do đó, việc đặ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()mà không có nguy cơ bị phá hủy.
vitaut

1
Tôi nhận được một cái gì đó kỳ lạ khi tôi cố gắng chuyển đổi từ int sang chuỗi bằng std :: to_opes (num). Nếu tôi lưu trữ kết quả trong một biến và cố gắng Truy cập nó như stringNum [1] hoặc stringNum [n] khi n tăng, tôi sẽ nhận được rác.
dùng8951490

1
Đó chắc chắn là câu trả lời đúng cho câu hỏi này: mã hiệu quả và tiêu chuẩn không mang tính trạng thái.
xryl669

16

sprintf()là khá tốt để 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.


1
Heh, vâng. Tuy nhiên, tôi thường dựa vào snprintf () và bạn bè cho bất kỳ hậu quả nào khi xử lý chuỗi C.
throwback1986

1
@MatthieuM. Nhận xét của bạn chứng minh thêm, rằng bạn không. Nếu đầu ra bị cắt bớt 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) sẽ được ghi vào chuỗi cuối cùng nếu có đủ không gian. 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 ngắn. Vì vậy, bạn gọi nó với NULLkích thước a và 0 để có được kích thước bộ đệm cần thiết.
user1095108

2
@ user1095108: Tôi nghĩ bạn đang nhầm lẫn snprintf(lưu ý tiền tố SNP ) và sprintf(lưu ý tiền tố SP ). Bạn chuyển kích thước cho cái trước và cần chú ý không tràn, tuy nhiên cái sau không biết kích thước của bộ đệm và do đó có thể tràn.
Matthieu M.

1
Ý tưởng là gọi một snprintfbiến thể trước và một sprintfbiến thể sau đó. Khi kích thước bộ đệm được biết đến sau đó, việc gọi sprintftrở nên hoàn toàn an toàn.
user1095108

1
@ user1095108 À, vâng. Nếu bộ đệm đầu tiên cho snprintf không đủ, giá trị trả về sẽ cho bạn biết cái gì sẽ đủ. Tôi vẫn sẽ sử dụng snprintf cho cuộc gọi thứ hai, bởi vì dựa vào việc triển khai sprintf và snprintf để khớp là nguy hiểm không cần thiết.
mabraham

11

Đầ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ư thế này:

NumberToString(69);

hoặc là

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

10

Sử dụng chuỗi để chuyển đổi số là nguy hiểm!

Xem http://www.cplusplus.com/reference/ostream/ostream/operator%3C%3C/ nơi thông báo rằng operator<<chèn đầu ra được định dạng.

Tùy thuộc vào ngôn ngữ hiện tại của bạn một số nguyên lớn hơn 3 chữ số, có thể chuyển đổi thành một chuỗi gồm 4 chữ số, thêm một dấu phân cách hàng nghìn.

Ví dụ, int = 1000có thể được chuyển đổi thành một chuỗi 1.001. Điều này có thể làm cho các hoạt động so sánh không hoạt động.

Vì vậy, tôi rất muốn giới thiệu cách sử dụng std::to_string. Nó dễ dàng hơn và làm những gì bạn mong đợi.

Cập nhật (xem bình luận bên dưới) :

C ++ 17 cung cấp std::to_charsnhư là một thay thế độc lập địa phương hiệu suất cao hơn


2
Tôi đồng ý rằng đây là một vấn đề nghiêm trọng nếu bạn cần trao đổi dữ liệu. Thật không may, cũng std::to_stringsử dụng ngôn ngữ hiện tại (xem en.cppreference.com/w/cpp/opes/basic_opes/to_opes , phần 'Ghi chú'). Hầu như tất cả các công cụ tiêu chuẩn (từ chuỗi dòng đến sprintf, nhưng cũng sscanfv.v.) đang sử dụng ngôn ngữ hiện tại. Tôi đã không nhận ra điều này cho đến gần đây khi nó đánh tôi mạnh mẽ. Hiện đang sử dụng những thứ trồng tại nhà, không khó để làm.
Bert Bril

Trong liên kết ở trên, C ++ 17 cung cấp std :: to_chars như là một thay thế độc lập với hiệu suất cao hơn.
CóThatIsMyName

Thật không may, tôi bị mắc kẹt với C ++ 11 cho (các) năm tới (khá là đã được cải thiện, may mắn thay).
Bert Bril

1
from_chars và to_chars sẽ hoàn hảo nhưng thật không may, họ đã không cung cấp một biến thể wchar_t.
gast128

8

Đối với C ++ 98 , có một vài lựa chọn:

boost/lexical_cast

Boost không phải là một phần của thư viện C ++, nhưng chứa nhiều phần mở rộng thư viện hữu ích.

Mẫu lexical_casthàm cung cấp một hình thức thuận tiện và nhất quán để hỗ trợ các chuyển đổi phổ biến đến và từ các loại tùy ý khi chúng được thể hiện dưới dạng văn bản.
- Tài liệu của Boost

#include "boost/lexical_cast.hpp"
#include <string>

int main() {
    int x = 5;
    std::string x_str = boost::lexical_cast<std::string>(x);
    return 0;
}

Đối với thời gian chạy, lexical_casthoạt động mất khoảng 80 micro giây (trên máy của tôi) trong lần chuyển đổi đầu tiên, và sau đó tăng tốc đáng kể sau đó nếu được thực hiện dự phòng.


itoa

Hàm này không được định nghĩa trong ANSI-C và không phải là một phần của C ++, nhưng được một số trình biên dịch hỗ trợ.
- cplusplus.com

Điều này có nghĩa là gcc/ g++không thể biên dịch mã bằng cách sử dụng itoa.

#include <stdlib.h>

int main() {
    int x = 5;
    char * x_str = new char[2];
    x_str = itoa(x, x_str, 10); // base 10
    return 0;
}

Không có thời gian chạy để báo cáo. Tôi không có Visual Studio cài đặt, đó là báo cáo có thể biên dịch itoa.


sprintf

sprintf là một hàm thư viện chuẩn C hoạt động trên các chuỗi C và là một thay thế hoàn toàn hợp lệ.

Soạn một chuỗi có cùng văn bản sẽ được in nếu định dạng được sử dụng trên printf, nhưng thay vì được in, nội dung được lưu dưới dạng chuỗi C trong bộ đệm được chỉ bởi str.
- cplusplus.com

#include <stdio.h>

int main() {
    int x = 5;
    char * x_str = new char[2];
    int chars_written = sprintf(x_str, "%d", x);
    return 0;
}

Các stdio.htiêu đề có thể không cần thiết. Đối với thời gian chạy, sprintfhoạt động mất khoảng 40 micro giây (trên máy của tôi) trong lần chuyển đổi đầu tiên, và sau đó tăng tốc đáng kể sau đó nếu được thực hiện dự phòng.


stringstream

Đây là cách chính của thư viện C ++ để chuyển đổi số nguyên thành chuỗi và ngược lại. Có các chức năng tương tự để stringstreamhạn chế hơn nữa mục đích sử dụng của luồng, chẳng hạn như ostringstream. Việc sử dụng ostringstreamcụ thể cho người đọc mã của bạn rằng bạn chỉ có ý định sử dụng <<toán tử. Hàm này là tất cả những gì đặc biệt cần thiết để chuyển đổi một số nguyên thành một chuỗi. Xem câu hỏi này để thảo luận chi tiết hơn.

#include <sstream>
#include <string>

int main() {
    int x = 5;
    std::ostringstream stream;
    stream << x;
    std::string x_str = stream.str();
    return 0;
}

Đối với thời gian chạy, ostringstreamhoạt động mất khoảng 71 micro giây (trên máy của tôi), và sau đó tăng tốc đáng kể sau đó nếu được thực hiện dự phòng, nhưng không nhiều như các chức năng trước đó .


Tất nhiên có những lựa chọn khác, và bạn thậm chí có thể bọc một trong số chúng vào chức năng của riêng bạn, nhưng điều này mang lại cái nhìn phân tích về một số trong những cái phổ biến.


Cảm ơn bạn đã chăm sóc chúng tôi (người dùng C ++ 98)
A. B

@AB Tôi không thể tin rằng vẫn còn bất kỳ người dùng C ++ 98 nào.
Kotauskas

@VladislavToncharov Khi công việc của bạn chỉ là để hỗ trợ thiết bị và mã kế thừa, bạn đã làm hỏng những thứ cũ bằng cách sử dụng các tiêu chuẩn công nghiệp tươi hơn. Một mùa hè trước, tôi đã viết mã bằng Python 2.3.
Joshua Detwiler

@JoshuaDetwiler ơi, quên mất điều đó, xin lỗi.
Kotauskas

4

C ++ 17 cung cấp std :: to_chars như một sự thay thế độc lập với miền địa phương hiệu suất cao hơn.


3

Thật dễ dàng để thêm một số đường cú pháp cho phép người ta soạn các chuỗi một cách nhanh chóng theo cách giống như luồng

#include <string>
#include <sstream>

struct strmake {
    std::stringstream s;
    template <typename T> strmake& operator << (const T& x) {
        s << x; return *this;
    }   
    operator std::string() {return s.str();}
};

Bây giờ bạn có thể nối bất cứ thứ gì bạn muốn (với điều kiện là một toán tử << (std::ostream& ..)được xác định cho nó) strmake()và sử dụng nó thay cho một std::string.

Thí dụ:

#include <iostream>

int main() {
    std::string x =
      strmake() << "Current time is " << 5+5 << ":" << 5*5 << " GST";
    std::cout << x << std::endl;
}

2

EDITED. Nếu bạn cần chuyển đổi nhanh một số nguyên có số chữ số cố định thành char * được đệm trái với '0' , đây là ví dụ cho các kiến ​​trúc cuối nhỏ (tất cả x86, x86_64 và các số khác):

Nếu bạn đang chuyển đổi một số có hai chữ số:

int32_t s = 0x3030 | (n/10) | (n%10) << 8;

Nếu bạn đang chuyển đổi một số có ba chữ số:

int32_t s = 0x303030 | (n/100) | (n/10%10) << 8 | (n%10) << 16;

Nếu bạn đang chuyển đổi một số có bốn chữ số:

int64_t s = 0x30303030 | (n/1000) | (n/100%10)<<8 | (n/10%10)<<16 | (n%10)<<24;

Và cứ như vậy lên đến bảy chữ số. Trong ví dụ nnày là một số nguyên cho trước. Sau khi chuyển đổi, biểu diễn chuỗi có thể được truy cập dưới dạng (char*)&s:

std::cout << (char*)&s << std::endl;

LƯU Ý: Nếu bạn cần nó theo thứ tự byte cuối lớn, mặc dù tôi đã không kiểm tra nó, nhưng đây là một ví dụ: đối với số có ba chữ số, nó int32_t s = 0x00303030 | (n/100)<< 24 | (n/10%10)<<16 | (n%10)<<8;dành cho số có bốn chữ số (vòm 64 bit): int64_t s = 0x0000000030303030 | (n/1000)<<56 | (n/100%10)<<48 | (n/10%10)<<40 | (n%10)<<32;Tôi nghĩ rằng nó nên hoạt động.


2
Thứ tự byte thì sao?
shjeff

Đây không phải là hành vi không xác định do bí danh con trỏ?
thức

1
@shjeff cảm ơn vì nhận xét, tôi đã thêm một lưu ý về endianness cho câu trả lời.
Alek

@dgnuff cảm ơn bạn đã chỉ ra điều này, mặc dù tôi không gặp vấn đề gì với điều này, bạn đã đúng. Tôi hơi sửa đổi câu trả lời để nó tuân thủ Quy tắc bí danh nghiêm ngặt, cảm ơn.
Alek

1

Sử dụng:

#define convertToString(x) #x

int main()
{
    convertToString(42); // Returns const char* equivalent of 42
}

3
Chỉ hoạt động với số bằng chữ, không đánh giá nội dung biến, mặc dù đôi khi hữu ích.
Sói

Đúng. Nhưng chắc chắn có ích vào thời gian
maverick9888

1
Chỉ hoạt động vào thời gian biên dịch với các số hằng, tôi nghĩ OP yêu cầu chuyển đổi động, sử dụng các số nguyên biến
Ing. Gerardo Sánchez

0

Tôi sử dụng:

int myint = 0;
long double myLD = 0.0;

string myint_str = static_cast<ostringstream*>(&(ostringstream() << myint))->str();
string myLD_str = static_cast<ostringstream*>(&(ostringstream() << myLD))->str();

Nó hoạt động trên trình biên dịch Windows và Linux g ++ của tôi.


0

Đây là một cách dễ dàng để làm

char str[100];
sprintf(str, "%d", 101);
string s = str;

sprintf là một công cụ nổi tiếng để chèn bất kỳ dữ liệu nào vào một chuỗi có định dạng bắt buộc.

Bạn có thể chuyển đổi một char *mảng thành một chuỗi như trong dòng thứ ba.


0

Điều này làm việc cho tôi -

Mã của tôi:

#include <iostream>
using namespace std;

int main()
{
    int n = 32;
    string s = to_string(n);
    cout << "string: " + s  << endl;
    return 0;
}

Chủ yếu dùng cái gì? stringstream?
Peter Mortensen

@PeterMortensen Hãy nhìn kỹ, nóstd::to_string()
Kotauskas

tôi có using namespace std;:)
Gonçalo Garrido

0

C ++ 11 được giới thiệu std::to_string()cho các loại số:

int n = 123; // Input, signed/unsigned short/int/long/long long/float/double
std::string str = std::to_string(n); // Output, std::string

4
Chào! Bạn có thể thêm một lời giải thích về lý do tại sao và làm thế nào điều này cung cấp một câu trả lời cho câu hỏi?
Anothernode

0

Sử dụng:

#include<iostream>
#include<string>

std::string intToString(int num);

int main()
{
    int integer = 4782151;

    std::string integerAsStr = intToString(integer);

    std::cout << "integer = " << integer << std::endl;
    std::cout << "integerAsStr = " << integerAsStr << std::endl;

    return 0;
}

std::string intToString(int num)
{
    std::string numAsStr;

    while (num)
    {
        char toInsert = (num % 10) + 48;
        numAsStr.insert(0, 1, toInsert);

        num /= 10;
    }
    return numAsStr;
}

1
Hoàn toàn thất bại trong n0
Toby Speight

-1
string number_to_string(int x) {

    if (!x)
        return "0";

    string s, s2;
    while(x) {
        s.push_back(x%10 + '0');
        x /= 10;
    }
    reverse(s.begin(), s.end());
    return s;
}

1
Cảm ơn bạn vì đoạn mã này, có thể cung cấp một số trợ giúp ngắn hạn có giới hạn. Một lời giải thích phù hợp sẽ cải thiện đáng kể giá trị lâu dài của nó bằng cách chỉ ra lý do tại sao đây là một giải pháp tốt cho vấn đề và sẽ giúp nó hữu ích hơn cho những người đọc tương lai với những câu hỏi tương tự khác. Vui lòng chỉnh sửa câu trả lời của bạn để thêm một số giải thích, bao gồm các giả định bạn đã thực hiện.
Toby Speight

Hoàn toàn thất bại trong n0
Toby Speight

Thêm ý kiến, giải thích câu trả lời của bạn, đọc cách trả lời .
Aksen P

-1

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

int a = 10;
CString strA;
strA.Format("%d", a);

8
Bạn nên lưu ý rằng đây là tiện ích mở rộng chỉ dành cho Microsoft: msdn.microsoft.com/en-us/l
Library / ms174288.aspx

1
Tôi thích ý tưởng về CString :: Format (). Thật không may nó chỉ MS không di động.
Nick

1
Tôi đã cập nhật câu trả lời của mình để bao gồm thông tin từ nhận xét của bạn @JonnyJD, vì tôi tiếp tục bị hạ thấp trong 5 năm sau đó ..
Tur1ng

-2
char * bufSecs = new char[32];
char * bufMs = new char[32];
sprintf(bufSecs, "%d", timeStart.elapsed()/1000);
sprintf(bufMs, "%d", timeStart.elapsed()%1000);

12
rò rỉ bộ nhớ, -1 từ tôi
paulm

Điều này có mùi như tràn bộ đệm.
Kotauskas

-2
namespace std
{
    inline string to_string(int _Val)
    {   // Convert long long to string
        char _Buf[2 * _MAX_INT_DIG];
        snprintf(_Buf, "%d", _Val);
        return (string(_Buf));
    }
}

Bây giờ bạn có thể sử dụng to_string(5).


10
Trong khi giải pháp này hoạt động, nó rất nản lòng! Tên bắt đầu bằng dấu gạch dưới và chữ in hoa được dành riêng cho trình biên dịch, bạn không nên sử dụng chúng. Việc tiêm các hàm vào stdkhông gian tên cũng không phải là điều bạn nên làm. Ngoài ra, nó dường như không phải _MAX_INT_DIGlà một macro tiêu chuẩn, vì vậy nếu nó được định nghĩa sai, mã này có tiềm năng lớn gây ra hành vi không xác định. -1
iFreilicht

6
_Max_INT_DIG là gì và tại sao nó được nhân đôi?
paulm

-2

Tôi nghĩ rằng việc sử dụng stringstreamlà khá dễ dàng:

 string toString(int n)
 {
     stringstream ss(n);
     ss << n;
     return ss.str();
 }

 int main()
 {
    int n;
    cin >> n;
    cout << toString(n) << endl;
    return 0;
 }

Điều này đã được đề cập trong câu hỏi, và không may là khá chậm.
Kotauskas

-3

Bạn sử dụng một loại thuật toán truy cập để chuyển đổi thành một chuỗi. Tôi đã có được kỹ thuật này từ lập trình máy tính Commodore 64 . Nó cũng tốt cho lập trình trò chơi.

  • Bạn lấy số nguyên và lấy mỗi chữ số có trọng số bằng 10. Vì vậy, giả sử số nguyên là 950.

    • Nếu số nguyên bằng hoặc lớn hơn 100.000 thì trừ 100.000 và tăng bộ đếm trong chuỗi tại ["000000"];
      tiếp tục làm cho đến khi không còn số ở vị trí 100.000. Thả một sức mạnh khác của mười.

    • Nếu số nguyên bằng hoặc lớn hơn 10.000 thì trừ 10.000 và tăng bộ đếm trong chuỗi tại ["000000"] + 1 vị trí;
      tiếp tục làm cho đến khi không còn số ở vị trí 10.000.

  • Giảm sức mạnh khác của mười

  • Lặp lại mô hình

Tôi biết 950 quá nhỏ để sử dụng làm ví dụ, nhưng tôi hy vọng bạn có ý tưởng.


Nó không hữu ích lắm để mô tả một thuật toán, thay vì hiển thị một ví dụ trong mã.
cdeerinck
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.