วิธีการแปลงจาก int เป็นถ่าน *


99

วิธีเดียวที่ฉันรู้คือ:

#include <sstream>
#include <string.h>
using namespace std;

int main() {
  int number=33;
  stringstream strs;
  strs << number;
  string temp_str = strs.str();
  char* char_type = (char*) temp_str.c_str();
}

แต่มีวิธีใดบ้างที่พิมพ์น้อยลง?


8
ทำไมคุณถึงต้องการ C-string แทนที่จะเป็นสตริง C ++?
KillianDS

1
ใช้sprintf
Ashish Kasma

คำตอบ:


133
  • ใน C ++ 17 ใช้std::to_charsเป็น:

    std::array<char, 10> str;
    std::to_chars(str.data(), str.data() + str.size(), 42);
    
  • ใน C ++ 11 ใช้std::to_stringเป็น:

    std::string s = std::to_string(number);
    char const *pchar = s.c_str();  //use char const* as target type
    
  • และใน C ++ 03 สิ่งที่คุณทำนั้นใช้ได้ดียกเว้นใช้constเป็น:

    char const* pchar = temp_str.c_str(); //dont use cast
    

1
ส่วนแรกไม่ได้ตอบคำถามจริงๆ (แม้ว่าจะเป็นข้อมูลที่เป็นประโยชน์เนื่องจากฉันไม่ทราบถึงฟังก์ชันนั้น)
jcoder

1
ดีกว่า :) นอกจากนี้ฉันควรอ่านเพิ่มเติมเกี่ยวกับ c ++ 11 อีกครั้ง ฉันรู้เกี่ยวกับคุณสมบัติใหญ่ ๆ แต่สิ่งนี้ทำให้ฉันรู้ว่าอาจมีสิ่งเล็ก ๆ ที่ฉันพลาด
jcoder

1
@Adambean: ทำไม "ไม่ควรเกี่ยวข้องกับ std :: string"? . หนึ่งควรใช้ตามค่าเริ่มต้นแทนstd::string char*
Nawaz

1
std :: string ไม่สามารถใช้ได้เสมอไปโดยเฉพาะกับโปรเจ็กต์เก่า ๆ เกม C ++ จำนวนมากยังคงอยู่ห่างจาก std :: string การเปลี่ยนจาก int เป็น std :: string ถึง char * ไม่เหมือนกับ int ถึง char *
Adambean

1
@Adambean: ถ้าเป็น C ++ ฉันจะถือว่าstd::stringมีให้โดยค่าเริ่มต้นเว้นแต่จะระบุไว้อย่างชัดเจนในคำถามเอง มีเหตุผล? นอกจากนี้เนื่องจากคำถามนั้นใช้std::string(และstd::stringstream) คุณจึงไม่มีเหตุผลมากที่จะไม่เห็นด้วยกับคำถามนี้
Nawaz

12

ฉันคิดว่าคุณสามารถใช้ sprintf:

int number = 33;
char* numberstring[(((sizeof number) * CHAR_BIT) + 2)/3 + 2];
sprintf(numberstring, "%d", number);

1
คุณควรเปลี่ยน char * เป็น char ตอนนี้ numberstring เป็นอาร์เรย์ของพอย
น์เตอร์

1
นอกจากนี้คุณต้องมีอักขระ 12 ตัวเพื่อแปลงจำนวนเต็ม 32 บิตเป็นการแทนค่าฐาน 10 ที่สิ้นสุดด้วย nul 10 ไม่เพียงพอสำหรับ-2147483647.
Steve Jessop

12
มีคำอธิบายอย่างไร? (((sizeof number) * CHAR_BIT) + 2)/3 + 2ดูเหมือนเวทมนตร์ ...
Mike S


5

วิธีการแก้ปัญหาแบบ C อาจจะใช้itoaแต่วิธีที่ดีกว่าคือการพิมพ์หมายเลขนี้เป็นสตริงโดยใช้/sprintf snprintfตรวจสอบคำถามนี้:จะแปลงจำนวนเต็มเป็นสตริงได้อย่างไร?

โปรดทราบว่าitoaฟังก์ชันไม่ได้กำหนดไว้ใน ANSI-C และไม่ได้เป็นส่วนหนึ่งของ C ++ แต่ได้รับการสนับสนุนโดยคอมไพเลอร์บางตัว เป็นฟังก์ชันที่ไม่ได้มาตรฐานดังนั้นคุณควรหลีกเลี่ยงการใช้งาน ตรวจสอบคำถามนี้ด้วย: Alternative to itoa () สำหรับการแปลงจำนวนเต็มเป็นสตริง C ++?

โปรดทราบว่าการเขียนโค้ดสไตล์ C ในขณะที่เขียนโปรแกรมด้วยภาษา C ++ ถือเป็นการปฏิบัติที่ไม่ดีและบางครั้งเรียกว่า "สไตล์ที่น่ากลัว" คุณต้องการแปลงเป็นchar*สตริงสไตล์ C หรือไม่? :)


5

ฉันจะไม่พิมพ์ const ออกไปในบรรทัดสุดท้ายเพราะมันมีเหตุผล หากคุณไม่สามารถอยู่กับ const char * ได้คุณควรคัดลอกอาร์เรย์ char เช่น:

char* char_type = new char[temp_str.length()];
strcpy(char_type, temp_str.c_str());

คุณหมายถึงconst char* char_type = temp_str.c_str();ดีกว่า?
rsk82

1
ใช่. c_str ให้คุณชี้ไปยังบัฟเฟอร์ภายในของอ็อบเจ็กต์สตริง หากคุณละทิ้ง const ไปคุณหรือโปรแกรมเมอร์คนอื่นอาจคิดว่าการเปลี่ยนบัฟเฟอร์ผ่านตัวแปรที่ไม่ใช่ const นั้นเป็นไปได้ แต่มันไม่ใช่ อ็อบเจ็กต์สตริงดั้งเดิมไม่ทราบอะไรเกี่ยวกับการเปลี่ยนแปลงเหล่านี้ ในทางกลับกันสตริงยังคงเป็นเจ้าของบัฟเฟอร์ หากอ็อบเจ็กต์สตริงอยู่นอกขอบเขตหน่วยความจำที่อยู่ด้านหลังตัวชี้จะถูกลบโดยตัวทำลายอ็อบเจ็กต์สตริงทำให้คุณมีพอยน์เตอร์ห้อยอยู่ การดำเนินการคัดลอกจะขจัดปัญหาทั้งสอง
user331471

1
อีกทางหนึ่งstd::vector<char> temp_vec(temp_str.begin(), temp_str.end()); temp_vec.push_back(0); char *char_type = &vec[0];. สิ่งนี้ทำให้คุณมีหน่วยความจำที่ไม่แน่นอนแม้ว่าคุณจะยังคงต้องรักษาเวกเตอร์ไว้ให้นานตราบเท่าที่คุณต้องการใช้ตัวชี้
Steve Jessop

1
หรือแค่ใช้stringและไม่ต้องกังวลกับความเก่าธรรมดาโง่char *จากเก่าธรรมดา C. <bits of flame ตั้งใจ>
Griwes

@Griwes: คำถามคือจะไปchar*อย่างไรไม่ "มีจุดใดที่เรียกจาก C ++ ไปยังไลบรารีที่มีอยู่ซึ่งเขียนด้วยภาษา C หรือไม่หรือฉันควรนำมาใช้ใหม่ใน C ++" ;-p
Steve Jessop


2

เอาล่ะ .. ประการแรกฉันต้องการบางอย่างที่ตอบคำถามนี้ได้ แต่ฉันต้องการมันอย่างรวดเร็ว! น่าเสียดายที่วิธี "ดีกว่า" คือโค้ดเกือบ 600 บรรทัด !!! ให้อภัยชื่อมันที่ไม่ได้เกี่ยวอะไรกับมัน ชื่อที่ถูกต้องคือInteger64ToCharArray (ค่า int64_t);

https://github.com/JeremyDX/All-Language-Testing-Code/blob/master/C%2B%2B%20Examples/IntegerToCharArrayTesting.cpp

อย่าลังเลที่จะลองทำความสะอาดโค้ดนั้นโดยไม่ขัดขวางประสิทธิภาพ

อินพุต:ค่า 64 บิตที่ลงชื่อใด ๆ จากช่วงต่ำสุดถึงสูงสุด

ตัวอย่าง:

std::cout << "Test: " << AddDynamicallyToBuffer(LLONG_MAX) << '\n';
std::cout << "Test: " << AddDynamicallyToBuffer(LLONG_MIN) << '\n';

เอาท์พุต:

Test: 9223372036854775807
Test: -9223372036854775808

การทดสอบความเร็วดั้งเดิม: ( Integer64ToCharArray (); )

กรณีที่ดีที่สุดมูลค่า 1 หลัก

ลูป: 100,000,000, เวลาที่ใช้: 1,381 (ล้าน), เวลาต่อลูป 13 (นาโน)

กรณีที่เลวร้ายยิ่งค่า 20 หลัก

ลูป: 100,000,000, เวลาที่ใช้: 22,656 (มิลลิวินาที), เวลาต่อลูป 226 (นาโน

การทดสอบความเร็วในการออกแบบใหม่: ( AddDynamicallyToBuffer (); )

กรณีที่ดีที่สุดมูลค่า 1 หลัก

ลูป: 100,000,000, เวลาที่ใช้: 427 (ล้าน), เวลาต่อลูป 4 (นาโน)

32 Bit Worst Case - มูลค่า 11 หลัก

ลูป: 100,000,000, เวลาที่ใช้: 1,991 (มิลลิวินาที), เวลาต่อลูป 19 (นาโน)

Negative 1 Trillion Worst Case - มูลค่า 14 หลัก

ลูป: 100,000,000, เวลาที่ใช้: 5,681 (ล้าน), เวลาต่อลูป 56 (นาโน)

64 Bit Worse Case - ค่า 20 หลัก

ลูป: 100,000,000, เวลาที่ใช้: 13,148 (ล้าน), เวลาต่อลูป 131 (นาโน)

มันทำงานอย่างไร!

เราใช้เทคนิค Divide and Conquer และเมื่อเรามีความยาวสูงสุดของสตริงแล้วเราก็ตั้งค่าอักขระแต่ละตัวทีละตัว ดังที่แสดงไว้ในการทดสอบความเร็วด้านบนความยาวที่มากขึ้นจะได้รับบทลงโทษที่มีประสิทธิภาพมาก แต่ก็ยังเร็วกว่าวิธีการวนซ้ำแบบเดิมและไม่มีการเปลี่ยนแปลงรหัสระหว่างสองวิธีอื่นจากนั้นการวนซ้ำจะไม่ใช้งานอีกต่อไป

ในการใช้งานของฉันดังนั้นชื่อฉันจึงคืนค่าชดเชยแทนและฉันไม่ได้แก้ไขบัฟเฟอร์ของอาร์เรย์ถ่าน แต่ฉันจะเริ่มอัปเดตข้อมูลจุดยอดและฟังก์ชันมีพารามิเตอร์เพิ่มเติมสำหรับการชดเชยดังนั้นจึงไม่ได้เริ่มต้นเป็น -1



0

คุณยังสามารถใช้การหล่อ

ตัวอย่าง:

string s;
int value = 3;
s.push_back((char)('0' + value));

2
จะเกิดอะไรขึ้นถ้าค่าเป็นลบหรือไม่ใช่ตัวเลข?
Ziya ERKOC

0

การแปลงค่าจำนวนเต็มของเราเป็น std :: string เพื่อให้เราสามารถทราบได้ว่ายาวเท่าใด

จากนั้นเราสร้างความยาวอาร์เรย์ char ของสตริงตัวอักษรขนาด +1 ดังนั้นเราจึงสามารถคัดลอกค่าของเราไปยังสตริงจากนั้นจึงสร้างอาร์เรย์ถ่าน

#include <string>

char* intToStr(int data) {
    std::string strData = std::to_string(data);

    char* temp = new char[strData.length() + 1];
    strcpy(temp, strData.c_str());

   return temp;
}

1
โปรดอย่าโพสต์เฉพาะรหัสดิบเป็นคำตอบ อธิบายเสมอว่าโค้ดทำอะไรและทำไม
CodeSamurai777

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