Std :: string, NSString'e nasıl dönüştürülür?


97

Merhaba ben bir standart dönüştürmek için çalışıyorum std::stringbir içine NSStringama çok şans sahip değilim.

Bir başarıyla dönüştürebilirsiniz NSStringa std::stringaşağıdaki kodla

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

Ancak aşağıdakileri denediğimde bir derleme zamanı hatası alıyorum

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

Aldığım hata

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

Burada bir şey mi kaçırıyorum?

Şimdiden teşekkürler.


4
Bu bir yazım hatası olmalı, ancak 'NSString * realm = "Hollywood";' içindeki dize değişmezi için '@' eksik. hat.
Vladimir

Yanıtlar:


111

Dönüşüm için std :: string'den c-string'i alın:

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

Belgelerin dediği gibi, bu iyi bir cevap gibi görünmüyor: / * Değer, kullanıcının varsayılan dilinden ve potansiyel olarak diğer faktörlerden türetilen kullanıcıya bağlı kodlama. Bu kodlamanın kullanılması, başka ipuçlarının olmadığı durumlarda, bilinmeyen kodlamalara sahip kullanıcı belgelerini yorumlarken bazen gerekli olabilir. Bu kodlama nadiren kullanılmalıdır. Buradaki bazı potansiyel değerlerin, oldukça basit NSString içeriğinin bile beklenmedik kodlama dönüşümleriyle sonuçlanabileceğini unutmayın - örneğin, çift yönlü kodlamalı noktalama karakterleri. * /
cyrilchampier

33
[NSString stringWithUTF8String: mystring.c_str ()] daha uygun görünüyor, çünkü std :: string muhtemelen UTF8'de kendi kodunuzdan geliyor.
cyrilchampier

Neden burada ( developer.apple.com/documentation/foundation/nsstring/… ) "Döndürülen nesne orijinal alıcıdan farklı olabilir" yazdığını biliyor musunuz ? Bu ne anlama geliyor ve farklı olup olmadığını nasıl anlarız?
isJulian00

@cyrilchapier ya .mm dosyamız "belirli bir kodlama belirtilmedi" diyorsa?
isJulian00

54

Öncelikle, bunun en ufak bir şekilde çalışması için Objective-C ++ kullanıyor olmanız gerekir; tüm *.mdosyalarınızı şu şekilde yeniden adlandırmanızı sağlamanın en kolay yolu*.mm

Bir C ++ ' std::stringyı an içine almanın en kullanışlı (kullanımdan kaldırılmamış) manuel yolu NSStringşudur:

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

Bu çoğu durumda işe yarayacaktır - ve özel kodlama tespiti ve dönüşümü yapmıyorsanız, UTF-8 size latin olmayan karakterlerin 'sadece çalışması' için iyi bir sonuç verecektir.

Daha büyük bir uygulama yapıyorsanız veya üzerinde çalışan tek kişi siz değilseniz, muhtemelen uygulaması daha kolay olan bir şey isteyeceksiniz.

Kakao geliştirme posta listesi arşivlerinden uyarlanmıştır

@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

Bu yerinde (ve uygun şekilde #import) şimdi şunları yapabilirsiniz:

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

Ve aynı std::wstringşey, kullanışlı olmaktan daha fazlası için.


1
Bu radikal ve birkaç iphone projesinde kullandım. Apple'ın birim testi çerçevesini çalıştırıyorsam ve bu yöntemleri kullanan bir kitaplığı test ediyorsam, dize dönüştürme yöntemlerini içeren dosyayı "Derleme Aşamaları" ndaki "Derleme Kaynaklarından" biri olarak dahil etmem gerektiğiydi. birim testi. Tuhaf.
David

1
Evet, birim testi aslında kendi küçük programıdır ve aynı koda erişmesi gerekir. Ayrıca, gerçekten test yazmak için tebrikler ;-)
rvalue

1
Neden burada ( developer.apple.com/documentation/foundation/nsstring/… ) "Döndürülen nesne orijinal alıcıdan farklı olabilir" yazdığını biliyor musunuz ? Bu ne anlama geliyor ve farklı olup olmadığını nasıl anlarız?
isJulian00

1
@izzyMachado, belgelerdeki bu tür bir dil tipik olarak, arabirim sözleşmesi kapsamında giriş dizesini ayrıştırmak, temizlemek veya standartlaştırmak için "hakkı" saklı tuttukları anlamına gelir. yani, gidiş-dönüş olmayabilir ve yine de karşılaştırabilir, ==ancak daha çok yapabilecekleri "en yakın" veya "en iyi" temsil olabilir. Bu durumda alıcı, NSStringsınıf uygulamasıdır ve döndürülen değer bir Objective-C nesnesi değildir, bu nedenle bunu bazı standart dillerle de kapsıyor olabilirler.
rvalue

İnitWithUTF8String kullandığımızda ve dize utf8 olmayan karakterler içerdiğinde bunun neden hala çalıştığını biliyor musunuz, dizeyi hala nasıl kullanabiliyor (UTF-8 ise) ve bir NSString olduğunda onu nasıl yazdırabiliyor?
isJulian00

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

bu NSString UTF8'i yapar mı? veya NSString hangi kodlama olurdu?
isJulian00

15

Apple artık bu dönüşümü yapmanızı istediği yeni bir yönteme sahip. XCode7'de, bunu bulmak için Düzenle> Dönüştür> Modern Hedef C Sözdizimine ... seçeneğini kullandım. Bir steno @ sembolü kullanır.

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

Aptalca bir soruysa özür dilerim, Ama emin olmak için, sCPPString.c_str () 'nin bir kopyasını sAppleString'e almak garantili mi? Demek istediğim, sCPPString puanın dışına çıkarsa, sAppleString içindeki bellek hala geçerli olacak mı? Ve stringWithUTF8String ve stringWithCString yöntemleri hakkında başka bir soru, İlki bir kopya oluşturuyor ve diğeri sadece bellek tamponunu mu ifade ediyor yoksa her ikisinin de bir kopya oluşturması garanti ediliyor mu? (İlkinin bir kopya yaptığını biliyorum ama diğerine ne olacak), sadece emin olmak istiyorum. Teşekkürler ...
MathNerd

3

Ayrıca şunu da buldum:

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

Bir şampiyon gibi çalışır.


4
Bu oldukça güvensiz ve çalışması garanti değil. standardString, eğer bir std :: string, bir C ++ nesnesidir. C ++ nesneleri, çeşitli işlevlere geçmek için güvenli değildir (çeşitli şablonlar bu sorunu C ++ 11'de çözer). Çalışırsa bu bir rastlantıdır ve hemen hemen her derleyici en azından sizi bunu yapmaya karşı uyaracaktır (eğer başlangıçta bir hata değilse).
Vitali

3

İşte kod parçacığı / örneği:

string str_simple = "HELLO WORLD";

//string to NSString
NSString *stringinObjC = [NSString stringWithCString:str_simple.c_str()
                                encoding:[NSString defaultCStringEncoding]];            
NSLog(stringinObjC);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.