วิธีที่ง่ายที่สุดในการแปลง int เป็น string ใน C ++


1574

วิธีที่ง่ายที่สุดในการแปลงจากintเป็นเทียบเท่าstringใน C ++ คืออะไร ฉันรู้วิธีการสองวิธี มีวิธีง่ายกว่านี้ไหม?

(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
ฉันคิดว่าทั้งสองวิธีที่คุณให้นั้นเป็นคำตอบที่ดี มันขึ้นอยู่กับบริบทที่คุณต้องทำ หากคุณทำงานกับสตรีมอยู่แล้วเช่นการอ่านหรือเขียนไฟล์วิธีที่สองของคุณดีที่สุด หากคุณต้องการส่งค่า int เป็นสตริงไปยังอาร์กิวเมนต์ของฟังก์ชันฟังก์ชัน itoa อาจเป็นวิธีที่ง่าย แต่ส่วนใหญ่แล้วการแปลง int เป็นสตริงเกิดขึ้นเมื่อจัดการกับไฟล์ดังนั้นสตรีมจึงเหมาะสม
Charles Brunet

41
ตัวเลือกที่ 1 ทำงานอย่างไรให้คุณได้ทั้งหมด เป็นความเข้าใจของฉันที่itoa()ใช้พารามิเตอร์สามตัว
b1nary.atr0phy

1
itoa จะเร็วกว่าสตรีมที่เทียบเท่า นอกจากนี้ยังมีวิธีการใช้บัฟเฟอร์สตริงอีกครั้งด้วยวิธี itoa (หลีกเลี่ยงการจัดสรรฮีปหากคุณสร้างสตริงบ่อยครั้งเช่นเพื่อปรับปรุงเอาต์พุตตัวเลขอย่างรวดเร็ว) หรือคุณสามารถสร้างสตรีมแบบกำหนดเองเพื่อลดค่าใช้จ่ายในการจัดสรรบางส่วนเป็นต้นการสร้างสตรีมในตอนแรกนั้นไม่ได้เป็นการลงทุนที่มีต้นทุนต่ำ
Pete

6
@Pete: เมื่อคุณเริ่มกังวลเกี่ยวกับสิ่งที่เร็วกว่าคุณจะต้องการดูstackoverflow.com/questions/4351371/…
Ben Voigt

20
โปรดทราบว่า itoa () ไม่ได้เป็นส่วนหนึ่งของมาตรฐานดังนั้นการใช้มันทำให้โค้ดของคุณไม่สามารถพกพาได้เนื่องจากคอมไพเลอร์บางตัวไม่รองรับ สำหรับลีนุกซ์คุณจะออกไปข้างนอกอย่างแน่นอนเว้นแต่ว่าคุณกำลังใช้อย่างอื่นที่ไม่ใช่ GCC ซึ่งไม่รองรับฟังก์ชั่นนี้ หากคุณมี C ++ 0x ไปกับสิ่งที่ @Matthieu แนะนำในคำตอบของเขา หากไม่ใช่กรณีนี้ให้ไปกับ stringstream เนื่องจากเป็นคุณสมบัติที่ได้รับการสนับสนุนเป็นอย่างดีและรหัสของคุณควรเข้ากันได้กับคอมไพเลอร์ C ++ ทุกตัว คุณสามารถใช้ sprintf () แทนก็ได้
rbaleksandar

คำตอบ:


2099

C ++ 11 แนะนำstd::stoi(และสายพันธุ์แต่ละชนิดตัวเลข) และstd::to_stringคู่ของซีatoiและแต่แสดงในรูปของitoastd::string

#include <string> 

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

เป็นวิธีที่สั้นที่สุดที่ฉันสามารถนึกได้ คุณสามารถละเว้นการตั้งชื่อประเภทโดยใช้autoคำหลัก:

auto s = std::to_string(42);

หมายเหตุ: ดู[string.conversions] ( 21.5ในn3242 )


199
to_stringไม่ใช่สมาชิกของการstdแก้ไข: stackoverflow.com/questions/12975341/…
Ben

36
หรือขึ้นอยู่กับคอมไพเลอร์ของคุณเพียงแค่ตั้งมาตรฐานภาษาที่ถูกต้อง:g++ -std=c++11 someFile.cc
Thomas M. DuBuisson

12
@ Steve: มันควรจะเป็น มันเป็นสมาชิกของstdคอมไพเลอร์ทุกตัวที่ฉันรู้จักยกเว้นหนึ่งตัว
Mooing Duck

5
@ Matthew M. ฉันใช้ชื่อเดียวกันกับที่คุณแนะนำ แต่ฉันได้รับข้อผิดพลาดนี้: Error : No instance of overloaded function "std::to_string" matches the argument list ฉันใช้ VS2010 c ++

19
@Flying: ภายใต้ VS2010 คุณต้องแปลงจำนวนเต็มแปลงให้เป็นหนึ่งในประเภทต่อไปนี้ [_Longlong, _ULonglong, long double]; เช่น:string s = to_string((_ULonglong)i);
Zac

184

หยิบขึ้นมาพูดคุยกับ @ v.oddou สองสามปีต่อมา, C ++ 17 ได้ส่งมอบในที่สุดวิธีการทำวิธีการแก้ปัญหาชนิดไม่เชื่อเรื่องพระเจ้าเดิมมหภาค based (เก็บรักษาไว้ด้านล่าง) โดยไม่ต้องไปผ่าน uglyness แมโคร

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

การใช้งาน:

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

คำตอบเดิม:

เนื่องจาก "การแปลง ... เป็นสตริง" เป็นปัญหาที่เกิดซ้ำฉันจึงกำหนดมาโครSSTR ()ในส่วนหัวส่วนกลางของแหล่ง C ++ ของฉัน:

#include <sstream>

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

การใช้งานนั้นง่ายพอ ๆ กับ:

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 ++ 98 ที่ใช้งานร่วมกันได้ (หากคุณไม่สามารถใช้ C ++ 11 std::to_string) และไม่จำเป็นต้องมีบุคคลที่สาม (ถ้าคุณไม่สามารถใช้ Boost lexical_cast<>) ทั้งโซลูชันอื่น ๆ เหล่านี้มีประสิทธิภาพที่ดีกว่า


2
ฉันไม่ค่อยคุ้นเคยdynamic_castแต่ฉันใช้เสียงดังเพื่อรวบรวมดังนั้นมันจึงบ่นเกี่ยวกับมัน หากฉันไม่ได้ใส่dynamic_castมัน การdynamic_castให้บริการในกรณีนี้มีวัตถุประสงค์อะไร? เรากำลังสร้างสิ่งอยู่แล้วostringstreamเหตุใดจึงต้องเลือกใช้งาน
แม็ตธิว

2
@Mathew: ลิงก์ในคำตอบของฉันนำไปสู่คำอธิบายโดยละเอียดของแต่ละส่วนของโครงสร้าง ในขณะที่เราสร้าง a ostringstreamเราเรียกoperator<<()มันว่ามันจะส่งกลับostream &ซึ่ง.str()ไม่ได้กำหนดไว้ ฉันสงสัยจริงๆว่าเสียงดังกราวจะทำงานนี้ได้อย่างไรโดยไม่มีนักแสดง (หรือสาเหตุที่ทำให้เกิดข้อผิดพลาด) งานสร้างนี้เผยแพร่ในหลาย ๆ ที่และฉันใช้มันมานานกว่าทศวรรษในคอมไพเลอร์ต่าง ๆ มากมายรวมถึง MSVC, GCC และ XLC ดังนั้นฉันจึงรู้สึกประหลาดใจกับเสียงดังกราว
DevSolar

5
เพิ่งมางานปาร์ตี้เพื่ออยากรู้อยากเห็นและลดลง เหตุผล: โหวตมากเกินไปสำหรับโซลูชันที่ไม่สง่างามและมีแนวโน้มช้า 1. การใช้งานมาโคร ฉันไม่ขมวดคิ้วอย่างเป็นระบบในแมโครใด ๆ แต่อันนี้สั้นเกินไปและลูกค้าปลายทางมักจะกลัวการโต้แย้งซ้ำ ๆ บนความกลัวสำหรับมาโครที่ไม่มีการป้องกัน (ไม่ได้รับการป้องกันโดยทำ {} ขณะที่ (0)) 2. dynamic_cast ดูเหมือนว่าคุณต้องการ static_cast ที่นี่เท่านั้นเว้นแต่คุณต้องการยืนยันว่ามีการใช้งานไลบรารีอย่างที่คุณต้องการ ในกรณีนี้คุณควรใช้ boost :: polymorphic_downcast แทน
v.oddou

2
@ v.oddou: คุณมีอิสระที่จะวิจารณ์ได้แน่นอน แต่ 1. ไม่ถูกต้อง - แมโครเป็นคำสั่งเดียวdo { } while( 0 )จะไม่เพิ่มอะไรเลย ด้วย 2 และ 3 คุณอาจมีจุด - สิ่งนี้สามารถทำได้ด้วยการโยนแบบคงที่และบางทีหนึ่งในแม่แบบของคุณพ่อมดที่นั่นอาจเกิดขึ้นกับอินเทอร์เฟซ "ดีกว่า" แต่อย่างที่ฉันบอกไปนี่เป็นสิ่งประดิษฐ์ของตัวฉันเอง ดูรอบ ๆ แมโครนี้ (มาโคร!) ค่อนข้างแพร่หลาย นั่นเป็นกรณีของ POLA ในตัวของมันเอง ฉันอาจเล่นด้วยสิ่งนี้เล็กน้อยเพื่อให้ "เพรียว" ยิ่งขึ้น
DevSolar

1
@ v.oddou: ดูสิ่งที่ฉันพบในสิ่งที่ C ++ 17 นำมาให้เรา :-) ฉันหวังว่าคุณจะชอบคำตอบที่อัปเดต
DevSolar

109

ฉันมักจะใช้วิธีการดังต่อไปนี้:

#include <sstream>

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

มันเป็นเรื่องที่อธิบายไว้ในรายละเอียดที่นี่


2
ก่อนที่จะใช้ssคุณจำเป็นต้องมีss.clear()มัน ฉันเห็นผลลัพธ์ที่ไม่คาดคิดหากไม่มีการเริ่มต้นนี้
อายุการใช้งาน

14
@ Lifebalance: ฉันไม่เคยเห็นพฤติกรรมแบบนี้มาก่อน
Rasoul

18
@ Lifebalance: คุณไม่จำเป็นต้องclear()มีostringstreamวัตถุที่สร้างขึ้นใหม่ clear()รีเซ็ตแฟล็กข้อผิดพลาด / eof และยังไม่มีเงื่อนไขข้อผิดพลาด / eof ใด ๆ ที่สร้างขึ้น
Remy Lebeau

2
@Rasoul NumberToString(23213.123)ผลิต23213.1ในขณะที่std::to_string(23213.123)ผลิตเกิด23213.123000อะไรขึ้นที่นั่น?
Killzone Kid

1
@KillzoneKid นี่เป็นเพราะ std 'ostream เป็น stateful (ซึ่งหมายความว่าการเปลี่ยนแปลงสถานะก่อนหน้านี้จะถูกเก็บไว้เช่นจำนวนหลักทศนิยม) ในขณะที่วิธีนี้เริ่มต้นด้วยสถานะเริ่มต้น
xryl669

85

อาจเป็นวิธีที่ง่ายที่สุดที่ใช้กันทั่วไปโดยการรวมตัวเลือกที่สองของคุณลงในเทมเพลตที่มีชื่อlexical_castเช่นหนึ่งในBoostดังนั้นรหัสของคุณจะเป็นดังนี้:

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

ข้อดีอย่างหนึ่งของมันก็คือมันรองรับการปลดเปลื้องอื่น ๆ เช่นกัน (เช่นในทิศทางตรงกันข้ามทำงานได้ดีเช่นกัน)

โปรดทราบว่าแม้ว่า Boost lexical_cast จะเริ่มต้นเพียงแค่เขียนไปยังสตริงสตรีมแล้วแยกกลับออกจากสตรีม แต่ตอนนี้มีการเพิ่มสองสามอย่าง ก่อนอื่นมีการเพิ่มความเชี่ยวชาญเฉพาะประเภทค่อนข้างน้อยดังนั้นสำหรับประเภททั่วไปจำนวนมากจึงเร็วกว่าการใช้สตริงสตรีมอย่างมาก ข้อที่สองตอนนี้ตรวจสอบผลลัพธ์ดังนั้น (ตัวอย่าง) หากคุณแปลงจากสตริงเป็นสตริงintสามารถโยนข้อยกเว้นหากสตริงมีบางสิ่งที่ไม่สามารถแปลงเป็นint(เช่น1234จะสำเร็จ แต่123abcจะส่ง) .

ตั้งแต่ C ++ 11 มีstd::to_stringฟังก์ชั่นโอเวอร์โหลดสำหรับประเภทจำนวนเต็มดังนั้นคุณสามารถใช้รหัสเช่น:

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

มาตรฐานกำหนดสิ่งเหล่านี้ว่าเทียบเท่ากับการทำการแปลงด้วยsprintf(โดยใช้ตัวระบุการแปลงที่ตรงกับประเภทของวัตถุที่ให้มาเช่น%dfor int) ลงในบัฟเฟอร์ที่มีขนาดเพียงพอแล้วสร้างstd::stringเนื้อหาของบัฟเฟอร์นั้น


2
ดีฉันชอบคำตอบของเควินแม้ว่าเขาจะแสดงชื่อรวมและเนมสเปซ เพียงเล็กน้อย :) ทำได้ดี แต่!
Jason R. Mick

4
ฉันจะบอกว่านี่เป็นวิธีที่จะไปหากคุณไม่มีการสนับสนุน C ++ 11
อเล็กซ์

40

หากคุณมีการติดตั้ง Boost (ซึ่งคุณควร):

#include <boost/lexical_cast.hpp>

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

4
ตกลงในการติดตั้งบูสต์ ฉันคิดว่ามากกว่าหนึ่งจะจัดรูปแบบสตริง เพื่อจุดประสงค์นี้ฉันต้องการ boost :: format เช่น format ("% 02d", number) .str ()
Werner Erasmus

28

มันจะง่ายขึ้นโดยใช้ 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

หรือสร้างฟังก์ชั่น:

#include <sstream>

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

18

ไม่ว่าฉันรู้ในบริสุทธิ์ C ++ แต่การเปลี่ยนแปลงเล็กน้อยในสิ่งที่คุณพูดถึง

string s = string(itoa(a));

ควรทำงานได้และมันก็ค่อนข้างสั้น


55
itoa()ไม่ใช่ฟังก์ชั่นมาตรฐาน!
นักเขียนการ์ตูน

4
@ การ์ตูน: แล้วมันคืออะไร?
user541686

20
ฟังก์ชันนี้ไม่ได้กำหนดไว้ใน ANSI-C และ C ++ ดังนั้นคอมไพเลอร์บางตัวไม่รองรับเช่น g ++
นักเขียนการ์ตูน

17

คุณสามารถใช้std::to_stringงานได้ใน C ++ 11 ตามที่ Matthieu M. แนะนำ :

std::to_string(42);

หรือหากประสิทธิภาพมีความสำคัญ (ตัวอย่างเช่นหากคุณทำ Conversion มาก) คุณสามารถใช้fmt::format_intจากไลบรารี{fmt}เพื่อแปลงจำนวนเต็มเป็นstd::string:

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

หรือสตริง C:

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

หลังไม่ได้ทำการจัดสรรหน่วยความจำแบบไดนามิกและเร็วกว่าstd::to_stringมาตรฐานของ Boost Karma มากกว่า 10 เท่า ดูจำนวนเต็มเร็วถึงการแปลงสตริงใน C ++สำหรับรายละเอียดเพิ่มเติม

โปรดทราบว่าทั้งคู่ปลอดภัยสำหรับเธรด

ซึ่งแตกต่างstd::to_string, fmt::format_intไม่ต้องใช้ภาษา C ++ 11 และผลงานใด ๆ กับ C ++ คอมไพเลอร์

คำเตือน: ฉันเป็นผู้เขียนของห้องสมุด {fmt}


2
ฉันอยากรู้เกี่ยวกับการอ้างว่าไม่มีการจัดสรรหน่วยความจำแบบไดนามิกในขณะที่ยังคงเป็น threadsafe (ผู้เข้าร่วมใหม่) ดังนั้นฉันจึงอ่านรหัสของคุณ - c_str()คืนค่าตัวชี้ไปยังบัฟเฟอร์ที่ประกาศภายในfmt::FormatIntคลาส - ดังนั้นตัวชี้กลับจะไม่ถูกต้อง อัฒภาค - ดูstackoverflow.com/questions/4214153/lifetime-of-temporaries
Soren

1
ใช่พฤติกรรมเช่นเดียวกับด้วยstd::string::c_str()(เช่นการตั้งชื่อ) หากคุณต้องการใช้มันนอกการแสดงออกเต็มรูปแบบสร้างวัตถุFormatInt f(42);จากนั้นคุณสามารถใช้f.c_str()โดยไม่ต้องเสี่ยงกับการถูกทำลาย
vitaut

1
ฉันได้สิ่งแปลก ๆ เมื่อพยายามแปลงจาก int เป็น string โดยใช้ std :: to_string (num) ถ้าฉันเก็บผลลัพธ์ไว้ในตัวแปรแล้วลองเข้าถึงมันเช่น stringNum [1] หรือ stringNum [n] เมื่อ n เพิ่มขึ้นฉันจะได้รับขยะ
user8951490

1
นั่นเป็นคำตอบที่ถูกต้องสำหรับคำถามนี้: รหัสที่มีประสิทธิภาพและมาตรฐานที่ไม่ได้ระบุไว้
xryl669

16

sprintf()ค่อนข้างดีสำหรับการแปลงรูปแบบ จากนั้นคุณสามารถกำหนดสตริง C ที่เป็นผลลัพธ์ให้กับสตริง C ++ ได้เช่นเดียวกับที่คุณทำใน 1


1
เฮ้ใช่ อย่างไรก็ตามฉันมักจะพึ่งพา snprintf () และเพื่อน ๆ เพื่อผลที่ตามมาเมื่อจัดการกับสตริง C
Throwback1986

1
@MatthieuM ความคิดเห็นของคุณพิสูจน์เพิ่มเติมว่าคุณไม่ได้ หากเอาต์พุตถูกตัดให้สั้นลงเนื่องจากข้อ จำกัด นี้ค่าส่งคืนจะเป็นจำนวนของอักขระ (ไม่รวมไบต์ null ที่สิ้นสุด) ซึ่งจะถูกเขียนไปยังสตริงสุดท้ายหากมีพื้นที่ว่างเพียงพอ ดังนั้นค่าส่งคืนของขนาดหรือมากกว่าหมายความว่าเอาท์พุทถูกตัดทอน ดังนั้นคุณจึงเรียกมันว่าNULLขนาดa และ zero เพื่อรับขนาดบัฟเฟอร์ที่จำเป็น
user1095108

2
@ user1095108: ฉันคิดว่าคุณเข้าใจผิดsnprintf(หมายเหตุคำนำหน้าSNP ) และsprintf(หมายเหตุคำนำหน้าSP ) คุณส่งผ่านขนาดไปยังอดีตและระวังไม่ให้ล้น แต่อย่างหลังไม่รู้ขนาดของบัฟเฟอร์จึงอาจล้น
Matthieu M.

1
ความคิดคือการเรียกsnprintfตัวแปรก่อนและsprintfตัวแปรหลังจากนั้น เมื่อทราบขนาดบัฟเฟอร์แล้วการโทรsprintfจะปลอดภัยทั้งหมด
user1095108

1
@ user1095108 อ่าใช่ หากบัฟเฟอร์แรกไปยัง snprintfไม่เพียงพอค่าส่งคืนจะบอกคุณว่าอะไรจะเพียงพอ ฉันยังคงใช้ snprintf สำหรับการโทรครั้งที่สองเพราะการใช้งาน sprintf และ snprintf ในการจับคู่นั้นเป็นสิ่งที่อันตรายโดยไม่จำเป็น
mabraham

11

ก่อนรวมถึง:

#include <string>
#include <sstream>

ประการที่สองเพิ่มวิธีการ:

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

ใช้วิธีการเช่นนี้:

NumberToString(69);

หรือ

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

10

การใช้สตริงสตรีมสำหรับการแปลงตัวเลขเป็นสิ่งที่อันตราย!

ดูที่http://www.cplusplus.com/reference/ostream/ostream/operator%3C%3C/ซึ่งจะแจ้งให้ทราบว่าoperator<<ส่วนแทรกที่จัดรูปแบบผลลัพธ์

จำนวนเต็มมากกว่า 3 หลักขึ้นอยู่กับที่ตั้งปัจจุบันของคุณสามารถแปลงเป็นสตริง 4 หลักโดยเพิ่มตัวคั่นหลักพันพิเศษ

เช่นint = 1000อาจจะ convertet 1.001สตริง สิ่งนี้อาจทำให้การเปรียบเทียบไม่ทำงานเลย

ดังนั้นฉันขอแนะนำอย่างยิ่งให้ใช้std::to_stringวิธีนี้ มันง่ายกว่าและทำในสิ่งที่คุณคาดหวัง

อัปเดต (ดูความคิดเห็นด้านล่าง) :

C ++ 17 std::to_charsเป็นตัวเลือกที่ไม่ขึ้นกับสถานที่ที่มีประสิทธิภาพสูงกว่า


2
ฉันยอมรับว่านี่เป็นปัญหาร้ายแรงหากคุณต้องการแลกเปลี่ยนข้อมูล น่าเสียดายที่ยังstd::to_stringใช้ตำแหน่งที่ตั้งปัจจุบัน (ดูen.cppreference.com/w/cpp/string/basic_string/to_stringส่วน 'Notes') เครื่องมือมาตรฐานเกือบทั้งหมด (จาก stringstreams ไปจนถึงsprintfแต่ยังsscanfเป็นต้น) ใช้สถานที่ปัจจุบัน ฉันไม่ได้ตระหนักถึงสิ่งนี้จนกระทั่งเมื่อเร็ว ๆ นี้เมื่อมันมาถึงฉันอย่างหนัก ขณะนี้ใช้สิ่งที่ปลูกเองที่บ้านไม่ยากที่จะทำ
Bert Bril

ในลิงค์ด้านบนมันยังเป็น statet ที่ C ++ 17 มี std :: to_chars เป็นทางเลือกที่มีประสิทธิภาพสูงขึ้น
YesThatIsMyName

น่าเสียดายที่ฉันติดอยู่กับ C ++ 11 สำหรับปีที่จะมาถึง (ค่อนข้างดีขึ้นแล้วโชคดี)
Bert Bril

1
from_chars และ to_chars จะสมบูรณ์แบบ แต่น่าเสียดายที่พวกเขาไม่มีตัวแปร wchar_t
gast128

8

สำหรับ C ++ 98มีตัวเลือกให้เลือกดังนี้:

boost/lexical_cast

Boost ไม่ได้เป็นส่วนหนึ่งของไลบรารี C ++ แต่มีส่วนขยายไลบรารีที่มีประโยชน์มากมาย

lexical_castแม่แบบฟังก์ชั่นมีรูปแบบที่สะดวกและสอดคล้องกันสำหรับการสนับสนุนการแปลงที่พบบ่อยไปและกลับจากประเภทโดยพลการเมื่อพวกเขาจะแสดงเป็นข้อความ
- เอกสารประกอบของ 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;
}

สำหรับรันไทม์การlexical_castดำเนินการใช้เวลาประมาณ 80 microseconds (บนเครื่องของฉัน) ในการแปลงครั้งแรกจากนั้นเพิ่มความเร็วขึ้นอย่างมากหลังจากนั้นหากดำเนินการซ้ำซ้อน


itoa

ฟังก์ชั่นนี้ไม่ได้กำหนดไว้ใน ANSI-C และไม่ได้เป็นส่วนหนึ่งของ C ++ แต่ได้รับการสนับสนุนจากคอมไพเลอร์บางตัว
- cplusplus.com

ซึ่งหมายความว่าgcc/ รหัสไม่สามารถใช้คอมไพล์g++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;
}

ไม่มีรันไทม์ที่จะรายงาน ฉันไม่ได้มีการติดตั้ง Visual Studio ซึ่งเป็นข่าวที่itoaสามารถรวบรวม


sprintf

sprintf เป็นฟังก์ชันไลบรารีมาตรฐาน C ที่ทำงานกับสตริง C และเป็นทางเลือกที่ถูกต้องสมบูรณ์

ประกอบด้วยสตริงที่มีข้อความเดียวกับที่จะพิมพ์หากใช้รูปแบบกับ printf แต่แทนที่จะพิมพ์เนื้อหาจะถูกจัดเก็บเป็นสตริง C ในบัฟเฟอร์ที่ชี้โดย 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;
}

stdio.hส่วนหัวอาจไม่จำเป็น สำหรับรันไทม์การsprintfดำเนินการใช้เวลาประมาณ 40 microseconds (บนเครื่องของฉัน) ในการแปลงครั้งแรกจากนั้นเพิ่มความเร็วขึ้นอย่างมากหลังจากนั้นหากดำเนินการซ้ำซ้อน


stringstream

นี่เป็นวิธีหลักของไลบรารี C ++ ในการแปลงจำนวนเต็มเป็นสตริงและในทางกลับกัน มีฟังก์ชั่นที่คล้ายกับน้องสาวอยู่ที่วงเงินเพิ่มเติมวัตถุประสงค์การใช้งานของกระแสเช่นstringstream ostringstreamการใช้เป็นการostringstreamเฉพาะบอกผู้อ่านรหัสของคุณว่าคุณตั้งใจจะใช้<<โอเปอเรเตอร์เท่านั้น ฟังก์ชันนี้มีความจำเป็นอย่างยิ่งในการแปลงจำนวนเต็มเป็นสตริง ดูคำถามนี้เพื่อการอภิปรายที่ละเอียดยิ่งขึ้น

#include <sstream>
#include <string>

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

สำหรับรันไทม์การostringstreamดำเนินการใช้เวลาประมาณ 71 microseconds (บนเครื่องของฉัน) จากนั้นเพิ่มความเร็วขึ้นอย่างมากหลังจากนั้นหากทำซ้ำซ้อน แต่ไม่ได้ทำหน้าที่เท่าที่ผ่านมา


แน่นอนว่ามีตัวเลือกอื่น ๆ และคุณสามารถห่อสิ่งเหล่านี้ไว้ในฟังก์ชั่นของคุณเองได้


ขอขอบคุณที่ดูแลเรา (ผู้ใช้ C ++ 98 คน)
A. B

@AB ฉันไม่สามารถเชื่อได้ว่ามีผู้ใช้ C ++ 98 รายเหลืออยู่
Kotauskas

@VladislavToncharov เมื่องานของคุณเป็นเพียงการสนับสนุนอุปกรณ์ดั้งเดิมและรหัสคุณโคลนในสิ่งเก่าโดยใช้มาตรฐานอุตสาหกรรมที่สดใหม่ เมื่อฤดูร้อนที่ผ่านมาฉันกำลังเขียนโค้ดใน Python 2.3
Joshua Detwiler

@JoshuaDetwiler โอ้ลืมไปแล้วขอโทษ
Kotauskas

4

C ++ 17 ให้std :: to_charsเป็นทางเลือกที่เป็นอิสระต่อประสิทธิภาพการทำงานที่สูงขึ้น


3

มันค่อนข้างง่ายที่จะเพิ่มน้ำตาลประโยคที่อนุญาตให้หนึ่งเขียนสตริงได้ทันทีในลักษณะที่เหมือนสตรีม

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

ตอนนี้คุณอาจผนวกสิ่งที่คุณต้องการ (ในกรณีที่ผู้ประกอบการ<< (std::ostream& ..)มีการกำหนดให้มัน) ไปและใช้ในสถานที่ของstrmake()std::string

ตัวอย่าง:

#include <iostream>

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

2

แก้ไข หากคุณต้องการแปลงจำนวนเต็มอย่างรวดเร็วด้วยตัวเลขคงที่เพื่อแปลง * ซ้ายด้วย "0"นี่เป็นตัวอย่างสำหรับสถาปัตยกรรมแบบ end-endian (ทั้งหมด x86, x86_64 และอื่น ๆ ):

หากคุณแปลงตัวเลขสองหลัก:

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

หากคุณแปลงตัวเลขสามหลัก:

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

หากคุณแปลงตัวเลขสี่หลัก:

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

และตัวเลขมากถึงเจ็ดหลัก ในตัวอย่างnนี้เป็นจำนวนเต็มที่กำหนด หลังจากการแปลงการแสดงสตริงสามารถเข้าถึงได้เป็น(char*)&s:

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

หมายเหตุ: หากคุณต้องการตามลำดับไบต์ใหญ่แม้ว่าฉันไม่ได้ทดสอบ แต่นี่คือตัวอย่าง: สำหรับตัวเลขสามหลักมันเป็นตัวเลขint32_t s = 0x00303030 | (n/100)<< 24 | (n/10%10)<<16 | (n%10)<<8;สี่หลัก (64 บิตโค้ง): int64_t s = 0x0000000030303030 | (n/1000)<<56 | (n/100%10)<<48 | (n/10%10)<<40 | (n%10)<<32;ฉันคิดว่ามันควรจะทำงาน


2
สิ่งที่เกี่ยวกับการสั่งซื้อไบต์?
shjeff

นี่ไม่ใช่พฤติกรรมที่ไม่ได้กำหนดเนื่องจากมีนามแฝงตัวชี้หรือไม่
dgnuff

1
@shjeff ขอบคุณสำหรับความคิดเห็นฉันได้เพิ่มหมายเหตุเกี่ยวกับ endianness ให้กับคำตอบ
Alek

@duffuff ขอบคุณสำหรับการชี้ให้เห็นถึงแม้ว่าฉันจะไม่มีปัญหากับสิ่งนี้คุณพูดถูก ฉันแก้ไขคำตอบเล็กน้อยเพื่อให้เป็นไปตามกฎนามแฝงที่เข้มงวดขอบคุณ
Alek

1

ใช้:

#define convertToString(x) #x

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

3
ใช้งานได้กับตัวเลขตามตัวอักษรเท่านั้นไม่ได้ประเมินเนื้อหาที่หลากหลาย แต่บางครั้งก็มีประโยชน์
Wolf

ขวา. แต่มีประโยชน์ในเวลาแน่นอน
maverick9888

1
ใช้งานได้เฉพาะในเวลารวบรวมด้วยค่าคงที่ตัวอักษรฉันคิดว่า OP ขอการแปลงแบบไดนามิกโดยใช้ตัวแปรจำนวนเต็ม
จี Gerardo Sánchez

0

ฉันใช้:

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

มันทำงานบนคอมไพเลอร์ของ Windows และ Linux g ++ ของฉัน


0

นี่เป็นอีกวิธีที่ง่ายที่จะทำ

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

sprintf เป็นที่รู้จักกันดีในการแทรกข้อมูลลงในสตริงของรูปแบบที่ต้องการ

คุณสามารถแปลงchar *อาร์เรย์เป็นสตริงตามที่แสดงในบรรทัดที่สาม


0

สิ่งนี้ใช้ได้กับฉัน -

รหัสของฉัน:

#include <iostream>
using namespace std;

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

เป็นหลักโดยใช้อะไร stringstream?
Peter Mortensen

@PeterMortensen ดูอย่างระมัดระวังมันstd::to_string()
Kotauskas

ฉันมีusing namespace std;:)
Gonçalo Garrido

0

แนะนำ C ++ 11 std::to_string()สำหรับประเภทตัวเลข:

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

4
Hi! คุณสามารถเพิ่มคำอธิบายเกี่ยวกับสาเหตุและวิธีการนี้ให้คำตอบสำหรับคำถามได้อย่างไร
โหนด

0

ใช้:

#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
ล้มเหลวโดยสิ้นเชิงสำหรับn≤0
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
ขอบคุณสำหรับข้อมูลโค้ดนี้ซึ่งอาจให้ความช่วยเหลือระยะสั้นแบบ จำกัด คำอธิบายที่เหมาะสมจะช่วยเพิ่มมูลค่าในระยะยาวได้อย่างมากโดยการแสดงว่าเหตุใดจึงเป็นวิธีแก้ปัญหาที่ดีและจะทำให้มีประโยชน์มากขึ้นสำหรับผู้อ่านในอนาคตด้วยคำถามอื่น ๆ ที่คล้ายกัน โปรดแก้ไขคำตอบของคุณเพื่อเพิ่มคำอธิบายรวมถึงข้อสมมติฐานที่คุณทำ
Toby Speight

ล้มเหลวโดยสิ้นเชิงสำหรับn≤0
Toby Speight

เพิ่มความคิดเห็นอธิบายคำตอบของคุณอ่านวิธีการที่จะตอบ
Aksen P

-1

หากคุณใช้MFCคุณสามารถใช้CString:

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

8
คุณควรทราบว่านี่เป็นส่วนขยายของ Microsoft เท่านั้น: msdn.microsoft.com/en-us/library/ms174288.aspx
JonnyJD

1
ฉันชอบความคิดของ CString :: Format () โชคไม่ดีที่ไม่ใช่พกพา MS เท่านั้น
Nick

1
ฉันได้อัปเดตคำตอบของฉันเพื่อรวมข้อมูลจากความคิดเห็นของคุณ @JonnyJD เนื่องจากฉันยังคงได้รับการลงคะแนนสำหรับมันในอีก 5 ปีต่อมา ..
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
หน่วยความจำรั่ว -1 จากฉัน
paulm

มีกลิ่นเหมือนบัฟเฟอร์ล้น
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));
    }
}

to_string(5)ตอนนี้คุณสามารถใช้


10
ในขณะที่วิธีนี้ใช้งานได้มันก็ท้อแท้อย่างมาก! ชื่อที่เริ่มต้นด้วยเครื่องหมายขีดล่างและตัวอักษรใหญ่ถูกสงวนไว้สำหรับคอมไพเลอร์คุณไม่ควรใช้ชื่อเหล่านั้น การฉีดฟังก์ชันลงในstdเนมสเปซไม่ใช่สิ่งที่คุณควรทำ นอกจากนี้ดูเหมือนว่าจะไม่_MAX_INT_DIGเป็นแมโครมาตรฐานดังนั้นหากมีการกำหนดอย่างไม่ถูกต้องรหัสนี้มีศักยภาพที่ดีในการกระตุ้นพฤติกรรมที่ไม่ได้กำหนด -1
iFreilicht

6
_MAX_INT_DIG คืออะไรและทำไมจึงเพิ่มเป็นสองเท่า
paulm

-2

ฉันคิดว่าการใช้stringstreamนั้นง่ายมาก:

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

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

สิ่งนี้ถูกกล่าวถึงในคำถามและน่าเสียดายที่ค่อนข้างช้า
Kotauskas

-3

คุณใช้อัลกอริทึมชนิดตัวนับเพื่อแปลงเป็นสายอักขระ ฉันได้รับเทคนิคนี้จากการเขียนโปรแกรมคอมพิวเตอร์Commodore 64 มันยังดีสำหรับการเขียนโปรแกรมเกม

  • คุณใช้จำนวนเต็มและนำแต่ละหลักที่ถ่วงน้ำหนักด้วยพลังของ 10 ดังนั้นสมมติว่าจำนวนเต็มคือ 950

    • หากจำนวนเต็มเท่ากับหรือมากกว่า 100,000 ให้ลบ 100,000 และเพิ่มตัวนับในสตริงที่ ["000000"];
      ทำต่อไปเรื่อย ๆ จนกระทั่งไม่มีตัวเลขอยู่ในตำแหน่งที่ 100,000 อีกต่อไป ปล่อยพลังอีกสิบ

    • หากจำนวนเต็มเท่ากับหรือมากกว่า 10,000 ให้ลบ 10,000 และเพิ่มตัวนับในสตริงที่ ["000000"] + 1 ตำแหน่ง;
      ทำต่อไปเรื่อย ๆ จนกว่าจะไม่มีตัวเลขในตำแหน่ง 10,000 อีกต่อไป

  • ปล่อยพลังอีกสิบ

  • ทำซ้ำรูปแบบ

ฉันรู้ว่า 950 มีขนาดเล็กเกินไปที่จะใช้เป็นตัวอย่าง แต่ฉันหวังว่าคุณจะได้รับแนวคิด


การอธิบายอัลกอริทึมไม่เป็นประโยชน์มากนักแทนที่จะแสดงตัวอย่างในโค้ด
cdeerinck
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.