วิธีแปลง std :: string เป็น NSString


97

สวัสดีฉันพยายามที่จะแปลงมาตรฐานstd::stringเป็นNSStringแต่ฉันไม่ได้มีโชคดีมาก

ฉันสามารถแปลงจาก an NSStringเป็น a ได้สำเร็จstd::stringด้วยรหัสต่อไปนี้

NSString *realm = @"Hollywood";
std::string REALM = [realm cStringUsingEncoding:[NSString defaultCStringEncoding]];

อย่างไรก็ตามฉันได้รับข้อผิดพลาดเกี่ยวกับเวลาคอมไพล์เมื่อฉันลองทำสิ่งต่อไปนี้

NSString *errorMessage = [NSString stringWithCString:REALM encoding:[NSString defaultCStringEncoding]];

ข้อผิดพลาดที่ฉันได้รับคือ

Cannot convert 'std::string' to 'const char*' in argument passing

ฉันขาดอะไรที่นี่?

ขอบคุณล่วงหน้า.


4
ต้องพิมพ์ผิด แต่คุณไม่มี "@" สำหรับสตริงลิเทอรัลใน "NSString * realm =" Hollywood ";" ไลน์.
Vladimir

คำตอบ:


111

รับ c-string จาก std :: string สำหรับการแปลง:

NSString *errorMessage = [NSString stringWithCString:REALM.c_str() 
                                   encoding:[NSString defaultCStringEncoding]];

สิ่งนี้ดูเหมือนจะไม่ใช่คำตอบที่ดีเนื่องจากเอกสารระบุว่า: / * การเข้ารหัสขึ้นอยู่กับผู้ใช้ว่าค่าใดมาจากภาษาเริ่มต้นของผู้ใช้และปัจจัยอื่น ๆ ที่อาจเกิดขึ้น บางครั้งอาจจำเป็นต้องใช้การเข้ารหัสนี้เมื่อแปลเอกสารผู้ใช้ด้วยการเข้ารหัสที่ไม่รู้จักในกรณีที่ไม่มีคำแนะนำอื่น ๆ การเข้ารหัสนี้ควรใช้ไม่บ่อยนักหากเป็นเช่นนั้น โปรดทราบว่าค่าที่เป็นไปได้บางค่าอาจส่งผลให้เกิดการแปลงการเข้ารหัสที่ไม่คาดคิดของเนื้อหา NSString ที่ค่อนข้างตรงไปตรงมาตัวอย่างเช่นอักขระเครื่องหมายวรรคตอนที่มีการเข้ารหัสแบบสองทิศทาง * /
cyrilchampier

33
[NSString stringWithUTF8String: mystring.c_str ()] ดูเหมือนจะเหมาะสมกว่าเนื่องจากสตริง std :: มีแนวโน้มที่จะมาจากโค้ดของคุณเองซึ่งน่าจะอยู่ใน UTF8
cyrilchampier

พวกคุณรู้หรือไม่ว่าทำไมที่นี่ ( developer.apple.com/documentation/foundation/nsstring/… ) จึงบอกว่า“ วัตถุที่ส่งคืนอาจแตกต่างจากเครื่องรับดั้งเดิม” นี่หมายความว่าอย่างไรและเราจะรู้ได้อย่างไรว่ามันต่างกัน
isJulian00

@cyrilchapier จะเป็นอย่างไรถ้าไฟล์. mm ของเราระบุว่า“ ไม่ได้ระบุการเข้ารหัสเฉพาะ”?
isJulian00

54

ประการแรกคุณต้องใช้ Objective-C ++ เพื่อให้ได้ผลน้อยที่สุด วิธีที่ง่ายที่สุดเพื่อให้แน่ใจว่าได้เปลี่ยนชื่อ*.mไฟล์ทั้งหมดของคุณเป็น*.mm

วิธีที่ใช้งานง่ายที่สุด (ไม่เลิกใช้งาน) ในการรับ C ++ std::stringเข้าสู่NSStringคือ:

std::string param; // <-- input
NSString* result = [NSString stringWithUTF8String:param.c_str()];
NSString* alternative = [[NSString alloc] initWithUTF8String:param.c_str()];

วิธีนี้จะใช้ได้ผลในกรณีส่วนใหญ่และหากคุณไม่ได้ทำการตรวจจับและแปลงการเข้ารหัสเฉพาะ UTF-8 จะให้ผลลัพธ์ที่ดีสำหรับการมีอักขระที่ไม่ใช่ภาษาละติน 'ใช้งานได้'

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

ดัดแปลงมาจากที่เก็บรายชื่อผู้รับจดหมาย Cocoa-dev

@interface NSString (cppstring_additions)
+(NSString*) stringWithwstring:(const std::wstring&)string;
+(NSString*) stringWithstring:(const std::string&)string;
-(std::wstring) getwstring;
-(std::string) getstring;
@end

@implementation NSString (cppstring_additions)

#if TARGET_RT_BIG_ENDIAN
const NSStringEncoding kEncoding_wchar_t = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingUTF32BE);
#else
const NSStringEncoding kEncoding_wchar_t = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingUTF32LE);
#endif

+(NSString*) stringWithwstring:(const std::wstring&)ws
{
    char* data = (char*)ws.data();
    unsigned size = ws.size() * sizeof(wchar_t);

    NSString* result = [[NSString alloc] initWithBytes:data length:size encoding:kEncoding_wchar_t];
    return result;
}
+(NSString*) stringWithstring:(const std::string&)s
{
    NSString* result = [[NSString alloc] initWithUTF8String:s.c_str()];
    return result;
}

-(std::wstring) getwstring
{
    NSData* asData = [self dataUsingEncoding:kEncoding_wchar_t];
    return std::wstring((wchar_t*)[asData bytes], [asData length] / sizeof(wchar_t));
}
-(std::string) getstring
{
    return [self UTF8String];
}

@end

ด้วยสิ่งนั้นในสถานที่ (และแก้ไขอย่างเหมาะสม#import) ตอนนี้คุณสามารถ:

NSString* result = [NSString stringWithstring:param];
string convertedBack = [result getstring];

และเช่นเดียวกันstd::wstringซึ่งมีประโยชน์มากกว่า


1
นี่คือ rad และฉันได้ใช้มันในโครงการ iphone สองสามโปรเจ็กต์ สิ่งหนึ่งที่ฉันสังเกตเห็นคือถ้าฉันใช้กรอบการทดสอบหน่วยของ Apple และฉันกำลังทดสอบไลบรารีที่ใช้วิธีการเหล่านี้ฉันจะต้องรวมไฟล์ที่มีวิธีการแปลงสตริงเป็นหนึ่งใน "แหล่งรวบรวม" ใน "ขั้นตอนการสร้าง" สำหรับ การทดสอบหน่วย แปลก.
David

1
ใช่การทดสอบหน่วยโดยพื้นฐานแล้วเป็นโปรแกรมเล็ก ๆ ของตัวเองและจำเป็นต้องเข้าถึงรหัสเดียวกัน นอกจากนี้ความรุ่งโรจน์สำหรับการทดสอบการเขียนจริง ;-)
rvalue

1
พวกคุณรู้หรือไม่ว่าทำไมที่นี่ ( developer.apple.com/documentation/foundation/nsstring/… ) จึงบอกว่า“ วัตถุที่ส่งคืนอาจแตกต่างจากเครื่องรับดั้งเดิม” นี่หมายความว่าอย่างไรและเราจะรู้ได้อย่างไรว่ามันต่างกัน
isJulian00

1
@izzyMachado ภาษาประเภทนั้นในเอกสารมักจะหมายความว่าพวกเขาสงวน "สิทธิ์" ภายใต้สัญญาอินเทอร์เฟซเพื่อแยกวิเคราะห์ฆ่าเชื้อหรือบัญญัติสตริงอินพุต กล่าวคืออาจไม่ใช่แบบไปกลับและยังคงเปรียบเทียบ==แต่เป็นตัวแทนที่ "ใกล้เคียงที่สุด" หรือ "ดีที่สุด" ที่สามารถทำได้ ตัวรับในกรณีนี้คือการนำNSStringคลาสไปใช้งานและค่าที่ส่งคืนไม่ใช่อ็อบเจกต์ Objective-C ดังนั้นพวกเขาอาจครอบคลุมด้วยภาษามาตรฐานบางภาษา
rvalue

คุณรู้หรือไม่ว่าเหตุใดจึงยังคงใช้งานได้เมื่อเราใช้ initWithUTF8String และสตริงมีอักขระที่ไม่ใช่ utf8 มันยังคงสามารถใช้สตริงได้อย่างไร (ถ้าเป็น UTF-8 มินต์) และพิมพ์ออกมาเมื่อมันกลายเป็น NSString?
isJulian00

21
NSString* mystring = [NSString stringWithUTF8String:stdstring.c_str()];

สิ่งนี้ทำให้ NSString UTF8 หรือไม่ หรือ NSString จะเข้ารหัสอะไร
isJulian00

15

ตอนนี้ Apple มีวิธีใหม่ที่ต้องการให้คุณทำ Conversion นี้ ใน XCode7 ฉันใช้ตัวเลือก Edit> Convert> To Modern Objective C Syntax ... เพื่อค้นหาสิ่งนี้ ใช้สัญลักษณ์ชวเลข @

std::string sCPPString = "Hello World!";
NSString *sAppleString = @(sCPPString.c_str());

ขออภัยหากเป็นคำถามโง่ ๆ แต่เพื่อความแน่ใจรับประกันว่าจะทำสำเนา sCPPString.c_str () ลงใน sAppleString หรือไม่ ฉันหมายความว่าถ้า sCPPString ไม่ได้คะแนนหน่วยความจำภายใน sAppleString จะยังคงใช้งานได้? และอีกคำถามเกี่ยวกับวิธีการ stringWithUTF8String และ stringWithCString อันแรกทำสำเนาและอีกข้ออ้างถึงบัฟเฟอร์หน่วยความจำหรือทั้งสองอย่างรับประกันว่าจะทำสำเนาด้วย (ฉันรู้ว่าคนแรกทำสำเนา แต่อีกอันหนึ่ง) ฉันขอแค่ให้แน่ใจ ขอบคุณ ...
MathNerd

3

ฉันยังพบว่า:

NSString *nsString = [NSString stringWithFormat:@"%s",standardString];

ทำงานเหมือนแชมป์


4
ค่อนข้างไม่ปลอดภัยและไม่รับประกันว่าจะได้ผล standardString ถ้า std :: string เป็นอ็อบเจ็กต์ C ++ อ็อบเจ็กต์ C ++ ไม่ปลอดภัยสำหรับการส่งผ่านไปยังฟังก์ชันตัวแปร (เทมเพลตตัวแปรช่วยแก้ปัญหานี้ใน C ++ 11) ถ้ามันใช้งานได้มันเป็นความบังเอิญและอย่างน้อยที่สุดทุกคอมไพเลอร์จะเตือนคุณไม่ให้ทำสิ่งนี้ (หากไม่ใช่ข้อผิดพลาดที่จะเริ่มต้นด้วย)
Vitali

3

นี่คือข้อมูลโค้ด / ตัวอย่าง:

string str_simple = "HELLO WORLD";

//string to NSString
NSString *stringinObjC = [NSString stringWithCString:str_simple.c_str()
                                encoding:[NSString defaultCStringEncoding]];            
NSLog(stringinObjC);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.