How to replace a char in an an char array? Xcode - objective-c

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.

Related

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:.

NSString (or NSArray or something) to variable parameter list of C (char *) strings

Is there any easy way to convert an Objective-C holding class of NSStrings into parameters for a function accepting a variable list of char *? Specifically I have a function like:
-(void)someFunction:(NSSomething *) var
that I want to forward to a C function like
void someCFunction(char * var, ...)
Is there an easy way to go about this?
No, you can only do what you want if the number of arguments you're passing is known at compile time. If you just want to convert a single string, use the -UTF8String message:
// Example with two strings
NSString *str1 = ...;
NSString *str2 = ...;
someCFunction([str1 UTF8String], [str2 UTF8String]); // etc.
But if the number of strings will vary at runtime, you'll need to use a different API, if one is available. For example, if there's an API that took an array of strings, you could convert the Objective-C array into a C array:
// This function takes a variable number of strings. Note: in C/Objective-C
// (but not in C++/Objective-C++), it's not legal to convert 'char **' to
// 'char *const *', so you may sometimes need a cast to call this function
void someCFunction(const char *const *stringArray, int numStrings)
{
...
}
...
// Convert Objective-C array to C array
NSArray *objCArray = ...;
int numStrings = [objCArray count];
char **cStrArray = malloc(numStrings * sizeof(char*));
for (int i = 0; i < count; i++)
cStrArray[i] = [[objCArray objectAtIndex:i] UTF8String];
// Call the function; see comment above for note on cast
someCFunction((const char *const *)cStrArray, numStrings);
// Don't leak memory
free(cStrArray);
This would do the trick:
NSString *string = #"testing string"
const char * p1=[string UTF8String];
char * p2;
p2 = const_cast<char *>(p1);
Yes, this can be done, and is explained here:
How to create a NSString from a format string like #"xxx=%#, yyy=%#" and a NSArray of objects?
And here:
http://www.cocoawithlove.com/2009/05/variable-argument-lists-in-cocoa.html
With modifications for ARC here:
How to create a NSString from a format string like #"xxx=%#, yyy=%#" and a NSArray of objects?
Also, variable arguments are not statically or strongly typed, as the other poster seems to be suggesting. In fact, there is no clear indication in the callee of how many arguments you really have. Determining the number of arguments generally breaks down into having to either specify the number by an count parameter, using a null terminator, or inferring it from a format string a la (s)print* . This is frankly why the C (s)print* family of functions has been the source of many errors, now made much much safer by the XCode / Clang / GCC compiler that now warns.
As an aside, you can approach statically typed variable arguments in C++ by creating a template method that accepts an array of an unspecified size. This is generally considered bad form though as the compiler generates separate instances for each size of array seen by by the compiler (template bloat).

Converting char array into NSString object

As per my assignment I have to take in input from a user via a console to be used with NSString.
At the moment I have
char* name[100]; // declaring char array
NSString* firstName; // declaring the NSString
printf("Please enter first name \n");
printf("=> ");
scanf("%s", &name);
firstName = [NSString stringWithCString:name encoding:NSASCIIStringEncoding];
This works, however I am getting this warning
Incompatible pointer types sending 'char [100]' to parameter of type
'const char '
I don't want to be having these errors coming up in the code, I would like to also mention I'm using Xcode 4.2.
Can anyone explain to me why I'm getting these errors, and if I can possibly overcome them?
Many thanks in advance!
Change this:
char* name[100];
to
char name[100];
The first form creates an array of 100 pointers to char. The second one creates an array of 100 char elements. What might be confusing, is that name in that last case, is in fact a pointer, pointing to the first of these 100 char elements.
As printed with NSLog is assigned to initialize a NSString.
NSLog(#"%s", arrayChar);
NSString *str = [NSString stringWithFormat:#"%s", arrayChar];
NSLog(#"Array to String: %#",str);

How do I convert a NSString into a std::string?

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

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