Most efficient way to iterate over all the chars in an NSString - objective-c

What's the best way to iterate over all the chars in an NSString? Would you want to loop over the length of the string and use the method.
[aNSString characterAtIndex:index];
or would you want to user a char buffer based on the NSString?

I think it's important that people understand how to deal with unicode, so I ended up writing a monster answer, but in the spirit of tl;dr I will start with a snippet that should work fine. If you want to know details (which you should!), please continue reading after the snippet.
NSUInteger len = [str length];
unichar buffer[len+1];
[str getCharacters:buffer range:NSMakeRange(0, len)];
NSLog(#"getCharacters:range: with unichar buffer");
for(int i = 0; i < len; i++) {
NSLog(#"%C", buffer[i]);
}
Still with me? Good!
The current accepted answer seem to be confusing bytes with characters/letters. This is a common problem when encountering unicode, especially from a C background. Strings in Objective-C are represented as unicode characters (unichar) which are much bigger than bytes and shouldn't be used with standard C string manipulation functions.
(Edit: This is not the full story! To my great shame, I'd completely forgotten to account for composable characters, where a "letter" is made up of multiple unicode codepoints. This gives you a situation where you can have one "letter" resolving to multiple unichars, which in turn are multiple bytes each. Hoo boy. Please refer to this great answer for the details on that.)
The proper answer to the question depends on whether you want to iterate over the characters/letters (as distinct from the type char) or the bytes of the string (what the type char actually means). In the spirit of limiting confusion, I will use the terms byte and letter from now on, avoiding the possibly ambigious term character.
If you want to do the former and iterate over the letters in the string, you need to exclusively deal with unichars (sorry, but we're in the future now, you can't ignore it anymore). Finding the amount of letters is easy, it's the string's length property. An example snippet is as such (same as above):
NSUInteger len = [str length];
unichar buffer[len+1];
[str getCharacters:buffer range:NSMakeRange(0, len)];
NSLog(#"getCharacters:range: with unichar buffer");
for(int i = 0; i < len; i++) {
NSLog(#"%C", buffer[i]);
}
If, on the other hand, you want to iterate over the bytes in a string, it starts getting complicated and the result will depend entirely upon the encoding you choose to use. The decent default choice is UTF8, so that's what I will show.
Doing this you have to figure out how many bytes the resulting UTF8 string will be, a step where it's easy to go wrong and use the string's -length. One main reason this very easy to do wrong, especially for a US developer, is that a string with letters falling into the 7-bit ASCII spectrum will have equal byte and letter lengths. This is because UTF8 encodes 7-bit ASCII letters with a single byte, so a simple test string and basic english text might work perfectly fine.
The proper way to do this is to use the method -lengthOfBytesUsingEncoding:NSUTF8StringEncoding (or other encoding), allocate a buffer with that length, then convert the string to the same encoding with -cStringUsingEncoding: and copy it into that buffer. Example code here:
NSUInteger byteLength = [str lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
char proper_c_buffer[byteLength+1];
strncpy(proper_c_buffer, [str cStringUsingEncoding:NSUTF8StringEncoding], byteLength);
NSLog(#"strncpy with proper length");
for(int i = 0; i < byteLength; i++) {
NSLog(#"%c", proper_c_buffer[i]);
}
Just to drive the point home as to why it's important to keep things straight, I will show example code that handles this iteration in four different ways, two wrong and two correct. This is the code:
#import <Foundation/Foundation.h>
int main() {
NSString *str = #"буква";
NSUInteger len = [str length];
// Try to store unicode letters in a char array. This will fail horribly
// because getCharacters:range: takes a unichar array and will probably
// overflow or do other terrible things. (the compiler will warn you here,
// but warnings get ignored)
char c_buffer[len+1];
[str getCharacters:c_buffer range:NSMakeRange(0, len)];
NSLog(#"getCharacters:range: with char buffer");
for(int i = 0; i < len; i++) {
NSLog(#"Byte %d: %c", i, c_buffer[i]);
}
// Copy the UTF string into a char array, but use the amount of letters
// as the buffer size, which will truncate many non-ASCII strings.
strncpy(c_buffer, [str UTF8String], len);
NSLog(#"strncpy with UTF8String");
for(int i = 0; i < len; i++) {
NSLog(#"Byte %d: %c", i, c_buffer[i]);
}
// Do It Right (tm) for accessing letters by making a unichar buffer with
// the proper letter length
unichar buffer[len+1];
[str getCharacters:buffer range:NSMakeRange(0, len)];
NSLog(#"getCharacters:range: with unichar buffer");
for(int i = 0; i < len; i++) {
NSLog(#"Letter %d: %C", i, buffer[i]);
}
// Do It Right (tm) for accessing bytes, by using the proper
// encoding-handling methods
NSUInteger byteLength = [str lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
char proper_c_buffer[byteLength+1];
const char *utf8_buffer = [str cStringUsingEncoding:NSUTF8StringEncoding];
// We copy here because the documentation tells us the string can disappear
// under us and we should copy it. Just to be safe
strncpy(proper_c_buffer, utf8_buffer, byteLength);
NSLog(#"strncpy with proper length");
for(int i = 0; i < byteLength; i++) {
NSLog(#"Byte %d: %c", i, proper_c_buffer[i]);
}
return 0;
}
Running this code will output the following (with NSLog cruft trimmed out), showing exactly HOW different the byte and letter representations can be (the two last outputs):
getCharacters:range: with char buffer
Byte 0: 1
Byte 1:
Byte 2: C
Byte 3:
Byte 4: :
strncpy with UTF8String
Byte 0: Ð
Byte 1: ±
Byte 2: Ñ
Byte 3:
Byte 4: Ð
getCharacters:range: with unichar buffer
Letter 0: б
Letter 1: у
Letter 2: к
Letter 3: в
Letter 4: а
strncpy with proper length
Byte 0: Ð
Byte 1: ±
Byte 2: Ñ
Byte 3:
Byte 4: Ð
Byte 5: º
Byte 6: Ð
Byte 7: ²
Byte 8: Ð
Byte 9: °

While Daniel's solution will probably work most of the time, I think the solution is dependent on the context. For example, I have a spelling app and need to iterate over each character as it appears onscreen which may not correspond to the way it is represented in memory. This is especially true for text provided by the user.
Using something like this category on NSString:
- (void) dumpChars
{
NSMutableArray *chars = [NSMutableArray array];
NSUInteger len = [self length];
unichar buffer[len+1];
[self getCharacters: buffer range: NSMakeRange(0, len)];
for (int i=0; i<len; i++) {
[chars addObject: [NSString stringWithFormat: #"%C", buffer[i]]];
}
NSLog(#"%# = %#", self, [chars componentsJoinedByString: #", "]);
}
And feeding it a word like mañana might produce:
mañana = m, a, ñ, a, n, a
But it could just as easily produce:
mañana = m, a, n, ̃, a, n, a
The former will be produced if the string is in precomposed unicode form and the later if it's in decomposed form.
You might think this could be avoided by using the result of NSString's precomposedStringWithCanonicalMapping or precomposedStringWithCompatibilityMapping, but this is not necessarily the case as Apple warns in Technical Q&A 1225. For example a string like e̊gâds (which I totally made up) still produces the following even after converting to a precomposed form.
e̊gâds = e, ̊, g, â, d, s
The solution for me is to use NSString's enumerateSubstringsInRange passing NSStringEnumerationByComposedCharacterSequences as the enumeration option. Rewriting the earlier example to look like this:
- (void) dumpSequences
{
NSMutableArray *chars = [NSMutableArray array];
[self enumerateSubstringsInRange: NSMakeRange(0, [self length]) options: NSStringEnumerationByComposedCharacterSequences
usingBlock: ^(NSString *inSubstring, NSRange inSubstringRange, NSRange inEnclosingRange, BOOL *outStop) {
[chars addObject: inSubstring];
}];
NSLog(#"%# = %#", self, [chars componentsJoinedByString: #", "]);
}
If we feed this version e̊gâds then we get
e̊gâds = e̊, g, â, d, s
as expected, which is what I want.
The section of documentation on Characters and Grapheme Clusters may also be helpful in explaining some of this.
Note: Looks like some of the unicode strings I used are tripping up SO when formatted as code. The strings I used are mañana, and e̊gâds.

Neither. The "Optimize Your Text Manipulations" section of the "Cocoa Performance Guidelines" in the Xcode Documentation recommends:
If you want to iterate over the
characters of a string, one of the
things you should not do is use the
characterAtIndex: method to retrieve
each character separately. This method
is not designed for repeated access.
Instead, consider fetching the
characters all at once using the
getCharacters:range: method and
iterating over the bytes directly.
If you want to search a string for
specific characters or substrings, do
not iterate through the characters one
by one. Instead, use higher level
methods such as rangeOfString:,
rangeOfCharacterFromSet:, or
substringWithRange:, which are
optimized for searching the NSString
characters.
See this Stack Overflow answer on How to remove whitespace from right end of NSString for an example of how to let rangeOfCharacterFromSet: iterate over the characters of the string instead of doing it yourself.

I would definitely get a char buffer first, then iterate over that.
NSString *someString = ...
unsigned int len = [someString length];
char buffer[len];
//This way:
strncpy(buffer, [someString UTF8String]);
//Or this way (preferred):
[someString getCharacters:buffer range:NSMakeRange(0, len)];
for(int i = 0; i < len; ++i) {
char current = buffer[i];
//do something with current...
}

try enum string with blocks
Create Category of NSString
.h
#interface NSString (Category)
- (void)enumerateCharactersUsingBlock:(void (^)(NSString *character, NSInteger idx, bool *stop))block;
#end
.m
#implementation NSString (Category)
- (void)enumerateCharactersUsingBlock:(void (^)(NSString *character, NSInteger idx, bool *stop))block
{
bool _stop = NO;
for(NSInteger i = 0; i < [self length] && !_stop; i++)
{
NSString *character = [self substringWithRange:NSMakeRange(i, 1)];
block(character, i, &_stop);
}
}
#end
example
NSString *string = #"Hello World";
[string enumerateCharactersUsingBlock:^(NSString *character, NSInteger idx, bool *stop) {
NSLog(#"char %#, i: %li",character, (long)idx);
}];

This is little different solution for the question but I thought maybe this will be useful for someone. What I wanted was to actually iterate as actual unicode character in NSString. So, I found this solution:
NSString * str = #"hello 🤠💩";
NSRange range = NSMakeRange(0, str.length);
[str enumerateSubstringsInRange:range
options:NSStringEnumerationByComposedCharacterSequences
usingBlock:^(NSString *substring, NSRange substringRange,
NSRange enclosingRange, BOOL *stop)
{
NSLog(#"%#", substring);
}];

Although you would technically be getting individual NSString values, here is an alternative approach:
NSRange range = NSMakeRange(0, 1);
for (__unused int i = range.location; range.location < [starring length]; range.location++) {
NSLog(#"%#", [aNSString substringWithRange:range]);
}
(The __unused int i bit is necessary to silence the compiler warning.)

You should not use
NSUInteger len = [str length];
unichar buffer[len+1];
you should use memory allocation
NSUInteger len = [str length];
unichar* buffer = (unichar*) malloc (len+1)*sizeof(unichar);
and in the end use
free(buffer);
in order to avoid memory problems.

Related

Objective-C compare string object from NSArray to a string for equality

How do I properly compare a string that I am retrieving from an NSArray to a literal string? So far, I have filled an NSArray up with three blank spaces, " " in one method and now I am trying to replace 10 random indexes in the NSArray with the string "C10", but I don't want to replace what is there unless it is " " still.
Here I created the array of size 100 and filled each spot with 3 blank spaces.
-(void) initBoard{
_board = [board initWithCapacity: 100];
for(int i =0; i < 100; i++){
[_board addObject:#" "];
}
}
Here is the method that I'm having problems with the equality comparison.
-(void)makeChutes: (int) numOfChutes {
//Make argument number of Chutes randomly across the board.
for(int i = 0; i < numOfChutes || i>(-100);){
int random = arc4random_uniform(101);
if ([[_board objectAtIndex:random] isEqual:#" "]) {
NSString *fString = [NSString stringWithFormat:#"C%d", 10];
[_board replaceObjectAtIndex:random withObject:fString];
i++;//Only increments i if 3 blank spaces were at random index..
}
else{//Used to attempt to stop my accidental infinite loop.
i--;
NSLog(#"I, loop, ran %i times.", i);//Attempt failed:-(
}
}
}
I know the above code is a mess. In an attempt to stop the looping I made the i decrement every time it did not meet the for condition and then added an OR condition to my for loop, using ||, to try and stop it after 100 cycles. For some reason the || condition does not stop it from looping even while i is well south of -100.
My first question is how do I properly compare the string stored in the array at index "random" with the literal string of 3 blank spaces? I also tried the method isEqualToString, but it worked the same.
Secondly and less importantly, since I don't need it now, how do I properly code a bi-conditional for loop? I don't get any errors or warnings from Xcode with my for loop syntax and it compiles and runs, so I don't really get why it ignores my second conditions and keeps iterating even while i is < -100.
to know the exist or not and index of it simply use ContainsObject property over NSArray
[array containsObject:#"text"];
int indexOfObject = [array indexOfObject:#"text"];
Use this method for string comparison
[[_board objectAtIndex:random] isEqualToString:#" "]
Modified your code. I think this is what you are looking for
-(void)makeChutes: (int) numOfChutes
{
for(int i = 0; i < numOfChutes ;i++){
int random = arc4random_uniform(101);
if ([[_board objectAtIndex:random] isEqualToString:#" "])
{
[_board replaceObjectAtIndex:random withObject:#"C10"];
i++;
}
}
}
EDIT :
Solution from what you said in comments
-(void)makeChutes: (int) numOfChutes
{
int i=0;
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains[cd] ' '"];
NSArray *filteredArray = [_board filteredArrayUsingPredicate:predicate];
int arrayCount=[filteredArray count];
do {
int random = arc4random_uniform(101);
if ([[_board objectAtIndex:random] isEqualToString:#" "])
{
[_board replaceObjectAtIndex:random withObject:#"C10"];
i++;
if (arrayCount == i) {
i=numOfChutes;
}
}
} while (i<numOfChutes);
}
EDIT
From the DOCS
isEqualToString: Returns a Boolean value that indicates whether a
given string is equal to the receiver using a literal Unicode-based
comparison.
(BOOL)isEqualToString:(NSString *)aString Parameters aString The string with which to compare the receiver. Return Value YES if aString
is equivalent to the receiver (if they have the same id or if they are
NSOrderedSame in a literal comparison), otherwise NO.
Discussion The comparison uses the canonical representation of
strings, which for a particular string is the length of the string
plus the Unicode characters that make up the string. When this method
compares two strings, if the individual Unicodes are the same, then
the strings are equal, regardless of the backing store. “Literal” when
applied to string comparison means that various Unicode decomposition
rules are not applied and Unicode characters are individually
compared. So, for instance, “Ö” represented as the composed character
sequence “O” and umlaut would not compare equal to “Ö” represented as
one Unicode character.
My "initBoard" method was broken, causing the "makeChutes" method not to work as expected. Here is the correct initBoard:
-(void) initBoard{
_board = [[NSMutableArray alloc] initWithCapacity:100];
for(int i =0; i < 100; i++){
[_board addObject:#" "];
}
}
And the corrected makeChutes:
-(void)makeChutes: (int) numOfChutes{
//Make argument number of Chutes randomly across the board.
for(int i = 0; i < numOfChutes;){
int random = arc4random_uniform(100);//+1 of max index
if ([[_board objectAtIndex:random] isEqualTo:#" "]){
NSString *fString = [NSString stringWithFormat:#"C%d", 10];
[_board replaceObjectAtIndex:random withObject:fString];
i++;//Only increments i if 3 blank spaces were at random index.
}
}
}

Enumerate NSString characters via pointer

How can I enumerate NSString by pulling each unichar out of it? I can use characterAtIndex but that is slower than doing it by an incrementing unichar*. I didn't see anything in Apple's documentation that didn't require copying the string into a second buffer.
Something like this would be ideal:
for (unichar c in string) { ... }
or
unichar* ptr = (unichar*)string;
You can speed up -characterAtIndex: by converting it to it's IMP form first:
NSString *str = #"This is a test";
NSUInteger len = [str length]; // only calling [str length] once speeds up the process as well
SEL sel = #selector(characterAtIndex:);
// using typeof to save my fingers from typing more
unichar (*charAtIdx)(id, SEL, NSUInteger) = (typeof(charAtIdx)) [str methodForSelector:sel];
for (int i = 0; i < len; i++) {
unichar c = charAtIdx(str, sel, i);
// do something with C
NSLog(#"%C", c);
}
EDIT: It appears that the CFString Reference contains the following method:
const UniChar *CFStringGetCharactersPtr(CFStringRef theString);
This means you can do the following:
const unichar *chars = CFStringGetCharactersPtr((__bridge CFStringRef) theString);
while (*chars)
{
// do something with *chars
chars++;
}
If you don't want to allocate memory for coping the buffer, this is the way to go.
Your only option is to copy the characters into a new buffer. This is because the NSString class does not guarantee that there is an internal buffer you can use. The best way to do this is to use the getCharacters:range: method.
NSUInteger i, length = [string length];
unichar *buffer = malloc(sizeof(unichar) * length);
NSRange range = {0,length};
[string getCharacters:buffer range:range];
for(i = 0; i < length; ++i) {
unichar c = buffer[i];
}
If you are using potentially very long strings, it would be better to allocate a fixed size buffer and enumerate the string in chunks (this is actually how fast enumeration works).
I created a block-style enumeration method that uses getCharacters:range: with a fixed-size buffer, as per ughoavgfhw's suggestion in his answer. It avoids the situation where CFStringGetCharactersPtr returns null and it doesn't have to malloc a large buffer. You can drop it into an NSString category, or modify it to take a string as a parameter if you like.
-(void)enumerateCharactersWithBlock:(void (^)(unichar, NSUInteger, BOOL *))block
{
const NSInteger bufferSize = 16;
const NSInteger length = [self length];
unichar buffer[bufferSize];
NSInteger bufferLoops = (length - 1) / bufferSize + 1;
BOOL stop = NO;
for (int i = 0; i < bufferLoops; i++) {
NSInteger bufferOffset = i * bufferSize;
NSInteger charsInBuffer = MIN(length - bufferOffset, bufferSize);
[self getCharacters:buffer range:NSMakeRange(bufferOffset, charsInBuffer)];
for (int j = 0; j < charsInBuffer; j++) {
block(buffer[j], j + bufferOffset, &stop);
if (stop) {
return;
}
}
}
}
The fastest reliable way to enumerate characters in an NSString I know of is to use this relatively little-known Core Foundation gem hidden in plain sight (CFString.h).
NSString *string = <#initialize your string#>
NSUInteger stringLength = string.length;
CFStringInlineBuffer buf;
CFStringInitInlineBuffer((__bridge CFStringRef) string, &buf, (CFRange) { 0, stringLength });
for (NSUInteger charIndex = 0; charIndex < stringLength; charIndex++) {
unichar c = CFStringGetCharacterFromInlineBuffer(&buf, charIndex);
}
If you look at the source code of these inline functions, CFStringInitInlineBuffer() and CFStringGetCharacterFromInlineBuffer(), you'll see that they handle all the nasty details like CFStringGetCharactersPtr() returning NULL, CFStringGetCStringPtr() returning NULL, defaulting to slower CFStringGetCharacters() and caching the characters in a C array for fastest access possible. This API really deserves more publicity.
The caveat is that if you initialize the CFStringInlineBuffer at a non-zero offset, you should pass a relative character index to CFStringInlineBuffer(), as stated in the header comments:
The next two functions allow fast access to the contents of a string, assuming you are doing sequential or localized accesses. To use, call CFStringInitInlineBuffer() with a CFStringInlineBuffer (on the stack, say), and a range in the string to look at. Then call CFStringGetCharacterFromInlineBuffer() as many times as you want, with a index into that range (relative to the start of that range). These are INLINE functions and will end up calling CFString only once in a while, to fill a buffer. CFStringGetCharacterFromInlineBuffer() returns 0 if a location outside the original range is specified.
I don't think you can do this. NSString is an abstract interface to a multitude of classes that make no guarantees about the internal storage of the character data, so it's entirely possible there is no character array to get a pointer to.
If neither of the options mentioned in your question are suitable for your app, I'd recommend either creating your own string class for this purpose, or using raw malloc'ed unichar arrays instead of string objects.
This will work:
char *s = [string UTF8String];
for (char *t = s; *t; t++)
/* use as */ *t;
[Edit] And if you really need unicode characters then you have no option but to use length and characterAtIndex. From the documentation:
The NSString class has two primitive methods—length and characterAtIndex:—that provide the basis for all other methods in its interface. The length method returns the total number of Unicode characters in the string. characterAtIndex: gives access to each character in the string by index, with index values starting at 0.
So your code would be:
for (int index = 0; index < string.length; index++)
{
unichar c = [string characterAtIndex: index];
/* ... */
}
[edit 2]
Also, don't forget that NSString is 'toll-free bridged' to CFString and thus all the non-Objective-C, straight C-code interface functions are usable. The relevant one would be CFStringGetCharacterAtIndex

Apple Emoji / iterate through NSString

I want to iterate through the 'characters' of an Emoji input String (from a UITextField) and then, one after another, display those emoji icons with a UILabel.
for (int i=0; i < len; i++) {
unichar c = [transformedString characterAtIndex:i];
[label setText:[NSString stringWithFormat:#"%C", c]];
...
This works for ASCII text but not Emoji fonts (all except the heart symbol are empty). As I noticed, a single Emoji icon is represented by 2 characters in the string.
As far as I know, Emoji uses private area unicode chars.
Is there anyway to achieve this ?
Thank you very much, you save me some headache ...
You can used one of the enumerate* instance methods on NSString, with the option NSStringEnumerationByComposedCharacterSequences.
- (void)enumerateSubstringsInRange:(NSRange)range
options:(NSStringEnumerationOptions)opts
usingBlock:(void (^)(NSString *substring,
NSRange substringRange,
NSRange enclosingRange,
BOOL *stop))block
NSString uses UTF-16 which represents some codepoints as two 16 bit values. You could also manually check for these 'surrogate pairs' in the string and manually combine them, but then you'd still only be getting codepoints rather than characters.
[transformedString
enumerateSubstringsInRange:NSMakeRange(0,[transformedString length]
options:NSStringEnumerationByComposedCharacterSequences
usingBlock: ^(NSString *substring,NSRange,NSRange,BOOL *)
{
[label setText:substring];
}];

Character replacing in a string

suppose I have string like "this str1ng for test" now i want to check if character at position [i-1] and [i+1] are both alphabet but character at [i] is number, like this example in word "str1ng" then character at position [i] replaced by appropriate alphabet.
or vice versa.
I need this for post processing for output of OCR. TQ
You might have an easier time using Regular Expressions.
NSString are immutable, so you'll have to create a new NSMutableString from it, and mutate this copy, or to allocate a unichar* buffer, copy data from the NSString, perform the correction, and then recreate a new NSString from the result. Once you're working on a mutable copy of the string, you can use whatever algorithm you want.
So you'll need to have a function like that:
- (NSString*)correctOCRErrors:(NSString*)string
{
BOOL hasError = NO;
for (int i = 0; i < [string length]; ++ i)
{
if (isIncorrect([string characterAtIndex:i]))
{
hasError = YES;
break;
}
}
if (hasError)
{
unichar* buffer = (unichar*)malloc([string length]);
for (int i = 0; i < [string length]; ++ i)
{
unichar chr = [string characterAtIndex:i];
if (isIncorrect(chr))
chr = correctChar(chr);
buffer[i] = chr;
}
string = [[[NSString alloc] initWithCharactersNoCopy:buffer length:[string length] freeWhenDone:YES] autorelease];
}
return string;
}
You can access character in a NSString by passing a message charAtIndex:(NSUInteger)index.
And now you can get the ascii value at the particular index you are interested in and change it according to your requirement.
NSString Ref
Hope this is helpful !

Trying to Understand NSString::initWithBytes

I'm attempting conversion of a legacy C++ program to objective-C. The program needs an array of the 256 possible ASCII characters (8-bits per character). I'm attempting to use the NSString method initWithBytes:length:encoding: to do so. Unfortunately, when coded as shown below, it crashes (although it compiles).
NSString* charasstring[256];
unsigned char char00;
int temp00;
for (temp00 = 0; temp00 <= 255; ++temp00)
{
char00 = (unsigned char)temp00;
[charasstring[temp00] initWithBytes:&char00 length:1 encoding:NSASCIIStringEncoding];
}
What I'm missing?
First, the method is simply initWithBytes:length:encoding and not the NSString::initWithBytes you used in the title. I point this out only because forgetting everything you know from C++ is your first step towards success with Objective-C. ;)
Secondly, your code demonstrates that you don't understand Objective-C or use of the Foundation APIs.
you aren't allocating instances of NSString anywhere
you declared an array of 256 NSString instance pointers, probably not what you want
a properly encoded ASCII string does not include all of the bytes
I would suggest you start here.
To solve that specific problem, the following code should do the trick:
NSMutableArray* ASCIIChars = [NSMutableArray arrayWithCapacity:256];
int i;
for (i = 0; i <= 255; ++i)
{
[ASCIIChars addObject:[NSString stringWithFormat:#"%c", (unsigned char)i]];
}
To be used, later on, as follows:
NSString* oneChar = [ASCIIChars objectAtIndex:32]; // for example
However, if all you need is an array of characters, you can just use a simple C array of characters:
unsigned char ASCIIChars [256];
int i;
for (i = 0; i <= 255; ++i)
{
ASCIIChars[i] = (unsigned char)i;
}
To be used, later on, as follows:
unsigned char c = ASCIIChars[32];
The choice will depend on how you want to use that array of characters.