How do I convert a NSString into a std::string? - objective-c

I have an NSString object and want to convert it into a std::string.
How do I do this in Objective-C++?

NSString *foo = #"Foo";
std::string bar = std::string([foo UTF8String]);
Edit: After a few years, let me expand on this answer. As rightfully pointed out, you'll most likely want to use cStringUsingEncoding: with NSASCIIStringEncoding if you are going to end up using std::string. You can use UTF-8 with normal std::strings, but keep in mind that those operate on bytes and not on characters or even graphemes. For a good "getting started", check out this question and its answer.
Also note, if you have a string that can't be represented as ASCII but you still want it in an std::string and you don't want non-ASCII characters in there, you can use dataUsingEncoding:allowLossyConversion: to get an NSData representation of the string with lossy encoded ASCII content, and then throw that at your std::string

As Ynau's suggested in the comment, in a general case it would be better to keep everything on the stack instead of heap (using new creates the string on the heap), hence (assuming UTF8 encoding):
NSString *foo = #"Foo";
std::string bar([foo UTF8String]);

As noted on philjordan.eu it could also be that the NSString is nil. In such a case the cast should be done like this:
// NOTE: if foo is nil this will produce an empty C++ string
// instead of dereferencing the NULL pointer from UTF8String.
This would lead you to such a conversion:
NSString *foo = #"Foo";
std::string bar = std::string([foo UTF8String], [foo lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);

Related

How to replace a char in an an char array? Xcode

i got the following char array in Objective-C (Xcode):
char *incomeMessage;
NSString *str = [[NSString alloc] initWithBytes:data.bytes length:data.length encoding:NSUTF8StringEncoding];
incomeMessage = [str UTF8String];
NSLog(#"%c", incomeMessage[0]);
NSLog(#"%c", incomeMessage[1]);
NSLog(#"%c", incomeMessage[2]);
NSLog(#"%c", incomeMessage[3]);
NSLog(#"%c", incomeMessage[4]);
NSLog(#"%c", incomeMessage[5]);
For example I get some results like this in console:
"3
2
6
1
8
4"
Now i want to replace the char in incomeMessage[2] by 4:
incomeMessage[2] = '4';
But then it gives me the error:
EXC_BAD_ACCESS
Do you have an idea, how to solve the problem?
According to the reference documentation, UTF8String returns a read-only (const char*) reference to the string data.
The reference material goes on to note:
This C string is a pointer to a structure inside the string object,
which may have a lifetime shorter than the string object and will
certainly not have a longer lifetime. Therefore, you should copy the C
string if it needs to be stored outside of the memory context in which
you use this property.
So I'd suggest following their advice and creating a copy of the array and then performing your modifications against that.
For example: http://ideone.com/mhjwZW
You might have better luck with something like:
NSString* str = [[NSString alloc] initWithBytes:data.bytes length:data.length encoding:NSUTF8StringEncoding];
char* incomeMessage = malloc([str lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1);
strcpy(incomeMessage, [str UTF8String]);
//now you can change things
incomeMessage[2] = '4';
//do this when you're done
free(incomeMessage);
Although, is there any particular reason why you want to use a C-string/character array as opposed to an NSMutableString? I think you might find replaceCharactersInRange:withString: a better approach generally. See also: stringByReplacingCharactersInRange:withString:.
i got the following char array in Objective-C (Xcode)
You don't, you know. All you have is a pointer. You have not set aside any actual memory; there is no array there.
incomeMessage = [str UTF8String];
All you've done in that line is repoint the pointer incomeMessage at your string's UTF8String. A string's UTF8String is immutable. Note this passage in the docs:
you should copy the C string if it needs to be stored outside of the memory context in which you use this property.
So basically, if you want to write into an array of char, your first task should be to make an array of char.

Weird error with NSString: No known class method for selector 'stringWithBytes:length:encoding:'

I am attempting to use scanf to assign a value to an NSString, as per the answers to this question by Omar. This is the code, taken straight from progrmr's answer:
char word[40];
int nChars = scanf("%39s", word); // read up to 39 chars (leave room for NUL)
NSString* word2 = [NSString stringWithBytes:word
length:nChars
encoding:NSUTF8StringEncoding];
However, I'm getting an error on the last line that makes absolutely no sense to me:
No known class method for selector 'stringWithBytes:length:encoding:'
What in the world could be causing this error?
And yes, I do have #import <Foundation/Foundation.h> at the top of the file.
NSString does not have a stringWithBytes:length:encoding: class method, but you can use
NSString* word2 = [[NSString alloc] initWithBytes:word
length:nChars
encoding:NSUTF8StringEncoding];
Note however, that scanf() returns the number of scanned items and
not the number of scanned characters. So nChars will contain 1 and not the string length, so you should set nChars = strlen(word) instead.
A simpler alternative is (as also mentioned in one answer to the linked question)
NSString* word2 = [NSString stringWithUTF8String:word];
NSString does not respond to the selector stringWithBytes:length:encoding:. You probably wanted initWithBytes:length:encoding:.
Story in short: you might want to consider a const char C-string suitable initializer for your NSString object. Also, allocate memory before sending any initializer message to the NSString object. I would expect something like:
char word[40];
int nChars = scanf("%39s", word);
NSString *word2 = [[NSString alloc] initWithCString:word encoding:NSASCIIStringEncoding];
Note that initWithCString per design only supports properly null '\0' terminated 8-bit character arrays. For unterminated bytes arrays you have initWithBytes:length:encoding: instead.
For Unicode characters you could consider initWithCharactersNoCopy:length:freeWhenDone:.

Can't manipulate a string?

NSString *string = #"HELLO";
For some reason, XCode won't auto-complete methods like remove characters or append etc... If that's the case, how can I, say, remove certain characters from my string? Say I want to remove all the L's.
NSString doesn't respond to those methods. NSMutableString does, but you've declared an immutable string variable and assigned to it a string literal. Since an Objective-C #"string literal" is always immutable (an instance of NSString but not NSMutableString), there's no way those messages can be sent to the object you're using.
If you want a mutable string, try:
NSMutableString *mutableString = [[#"HELLO" mutableCopy] autorelease];
That's an immutable string literal.
Here is a great post explaining it in further details:
What's the difference between a string constant and a string literal?
As for your question on how would you change it and remove the Ls:
NSString *hello = #"HELLO";
NSString *subString = [hello stringByReplacingOccurrencesOfString:#"L" withString:#""];
NSLog(#"subString: %#", subString);
That outputs "HEO"
Either that or you can create an NSMutableString by creating a copy of the mutable string like Jonathan mentioned. In both examples, you're copying it into a non-literal string.

How to convert NSString to C string?

I know that this question is a possible duplicate, but even after looking at some Google tutorials and questions even on this forum none of them gives me a decent answer about this subject.
I have:
NSString *str = #"text";
And I would like to do something like:
char cstring [512] = str;
(this only shows what I want to do, after looking at Apple's NSString Class Ref I didn't even think about using it).
Up to now I have:
char command [512] = [[NSString stringWithFormat:#"text"] cStringUsingEncoding:NSUTF8StringEncoding];
Still, with that I get errors.
Any solution?
try const char *command = [str UTF8String];
A c string is returned as a pointer, not as an array of characters. To use it, you can change your variable to a pointer.
const char *command = [theString cStringUsingEncoding:NSUTF8StringEncoding];
Since you want the UTF8 encoding, you can use the UTF8String convenience method.
const char *command = [theString UTF8String];
If you need the data to be stored in a character array, you can use the getCString:maxLength:encoding: method, passing the array as the buffer. This will allow you to store the string directly to the buffer, and will tell you if the buffer is too small.
char command[512];
if(![theString getCString:command maxLength:sizeof(command)/sizeof(*command) encoding:NSUTF8StringEncoding]) {
NSLog(#"Command buffer too small");
}

How do you convert C String to NSString?

I have been able to find methods like -[NSString stringWithCString:encoding:] but they do not seem to play well when the cstring is a pointer.
First up, don't use initWithCString, it has been deprecated.
Couple of ways you can do this:
const *char cString = "Hello";
NSString *myNSString = [NSString stringWithUTF8String:cString];
If you need another encoding like ASCII:
const *char cString = "Hello";
NSString *myNSString = [NSString stringWithCString:cString encoding:NSASCIIStringEncoding];
If you want to see all the string encodings available, in Xcode, hold command + option then double click on NSASCIIStringEncoding in the above code block.
You will be able to see where Apple have declared their enumeration for the string encoding types. Bit quicker than trying to find it in the documentation.
Some other ones you might need:
NSASCIIStringEncoding
NSUnicodeStringEncoding // same as NSUTF16StringEncoding
NSUTF32StringEncoding
Checkout Apple's NSString Class Reference (encodings are at the bottom of the page)
With modern Objective-C (since Xcode 5 at least) you can just do:
char const* cString = "Hello";
NSString *myNSString = #(cString);
stringWithCString:encoding: creates an NSString from a given C string. To create a C string from an NSString, use either the UTF8String method (generally preferred) or cStringUsingEncoding: (if you need an encoding other than UTF-8).