string tokenizer in ios - objective-c

I like to tokenize a string to characters and store the tokens in a string array. I am trying to use following code which is not working as I am using C notation to access the array. What needs to be changed in place of travel path[i]?
NSArray *tokanizedTravelPath= [[NSArray alloc]init];
for (int i=0; [travelPath length]; i++) {
tokanizedTravelPath[i]= [travelPath characterAtIndex:i];

You can't store unichars in an NSArray*. What exactly are you trying to accomplish? An NSString* is already a great representation for a collection of unichars, and you already have one of those.

You need a NSMutableArray to set every element of the array (otherwise you can't change its objects).Also, you can only insert objects in the array, so you can:
- Insert a NSString containing the character;
- Use a C-style array instead.
This is how to do with the NSMutableArray:
NSMutableArray *tokanizedTravelPath= [[NSMutableArray alloc]init];
for (int i=0; i<[travelPath length]; i++)
{
[tokanizedTravelPath insertObject: [NSString stringWithFormat: #"%c", [travelPath characterAtIndex:i]] atIndex: i];
}

I count 3 errors in your code, I explain them at the end of my answer.
First I want to show you a better approach to split a sting into it characters.
While I agree with Kevin that an NSString is a great representation of unicode characters already, you can use this block-based code to split it into substrings and save it to an array.
Form the docs:
enumerateSubstringsInRange:options:usingBlock:
Enumerates the
substrings of the specified type in the specified range of the string.
NSString *hwlloWord = #"Hello World";
NSMutableArray *charArray = [NSMutableArray array];
[hwlloWord enumerateSubstringsInRange:NSMakeRange(0, [hwlloWord length])
options:NSStringEnumerationByComposedCharacterSequences
usingBlock:^(NSString *substring,
NSRange substringRange,
NSRange enclosingRange,
BOOL *stop)
{
[charArray addObject:substring];
}];
NSLog(#"%#", charArray);
Output:
(
H,
e,
l,
l,
o,
" ",
W,
o,
r,
l,
d
)
But actually your problems are of another nature:
An NSArray is immutable. Once instantiated, it cannot be altered. For mutable array, you use the NSArray subclass NSMutableArray.
Also, characterAtIndex does not return an object, but a primitive type — but those can't be saved to an NSArray. You have to wrap it into an NSString or some other representation.
You could use substringWithRange instead.
NSMutableArray *tokanizedTravelPath= [NSMutableArray array];
for (int i=0; i < [hwlloWord length]; ++i) {
NSLog(#"%#",[hwlloWord substringWithRange:NSMakeRange(i, 1)]);
[tokanizedTravelPath addObject:[hwlloWord substringWithRange:NSMakeRange(i, 1)]];
}
Also your for-loop is wrong, the for-loop condition is not correct. it must be for (int i=0; i < [travelPath length]; i++)

Related

How can I convert an NSRange to a delimited string of its values?

Given an NSRange, such as:
NSRange range = NSMakeRange(1, 22);
What's the best way to convert it to a comma-separated string of its values?
#"1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22"
The best I could come up with was to iterate over the range and insert its values into an NSArray, and then call -componentsJoinedByString: on the array. But that seems pretty wasteful, not to mention inelegant. Is there no better way?
My version using an array:
NSMutableArray *vals = [NSMutableArray arrayWithCapacity:range.length];
for (NSUInteger i = range.location; i < range.length; i++){
[vals addObject:#(i)];
}
NSString *string = [vals componentsJoinedByString:#","];
You can use NSIndexSet with indexSetWithIndexesInRange: to generate a list of values, and then iterate through them with enumerateIndexesUsingBlock:. E.g.
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:range];
NSMutableArray *indices = [NSMutableArray array];
[indexSet enumerateIndexesUsingBlock:^(NSUInteger i, BOOL *stop) {
[indices addObject:#(i)];
}];
NSString *string = [indices componentsJoinedByString:","];
NSMutableString *string=[#"" mutableCopy];
for (int i = range.location; i<range.length-1; i++){
[string appendFormat:#"%d,", i];
}
[string appendString#"%d", range.length-1];
If you want to hide the code, you can turn it into a function that would take the range and turn it into a string, that way this is hidden from your code. Or maybe turn it into a NSString class method, something like
[NSString stringWithRangeValues:range];
That would be like:
+ (NSString *)stringWithRangeValues:(NSRange)range{
NSMutableString *string=[#"" mutableCopy];
for (int i = range.location; i<range.lenght-1; i++){
[string appendFormat:#"%d,", i];
}
[string appendString#"%d", range.length-1];
return [NSString stringWithString:string];
}

divide string into characters

I have an NSString *titleName which changes according to an if statement. So the length (number of characters) in the string changes. I would like to divide titleName into a MutableArray of separate strings consisting of its individual characters. I would then like to use these separate strings as the text in different UILabels. I am not sure as how to go about this.
Through some research I have tried to create the NSMutable array like this
NSMutableArray *letterArray = substringWithRange:((i = 0);i<[titleName2 length];i++));
but this gives me an error Use of undeclared identifier 'substringWithRange.
Can someone help me.
I decided to use componentsSeparatedByString instead and just created my various strings with a , between each letter. Thanks for anybody's thoughts though.
The code you pasted is not valid objective-C.
To keep the same algorithm you should write something like :
NSMutableArray *letterArray = [NSMutableArray array];
NSUInteger length = [titleName2 length];
for (NSUInteger i = 0; i < length; ++i) {
[letterArray addObject:[titleName2 substringWithRange:NSMakeRange(i, 1)]];
}
It's probably much "cheaper" to hold a C-array of unichar characters that make-up the string. It will also be quicker to create:
NSString *input = #"How now brown cow?";
unichar chars[[input length]];
for (NSInteger i = 0; i < [input length]; i++)
chars[i] = [input characterAtIndex:i];
Alternatively you could use malloc() to create the C-array:
NSString *input = #"How now brown cow?";
unichar *chars = (unichar *)malloc([input length]);
for (NSInteger i = 0; i < [input length]; i++)
chars[i] = [input characterAtIndex:i];
and then use free(), later, to, err, free the memory:
free(chars);
Cheaper still, would be to not split-up the string at all...
Try this below code
NSMutableArray *letterArray = [NSMutableArray array];
for (int i = 0;i<[titleName2 length];i++)
{
[letterArray addObject: [titleName2 substringWithRange:NSMakeRange(i,1)]];
}
DLog(#"%#", letterArray);
Other option to get characters of string
NSMutableArray *letterArray = [NSMutableArray array];
for (int i=0; i < [titleName2 length]; i++)
{
[letterArray addObject:[NSString stringWithFormat:#"%c", [titleName2 characterAtIndex:i]]];
}
DLog(#"characters - %#", letterArray);

How do I split a string with special characters into a NSMutableArray

I'am trying to seperate a string with danish characters into a NSMutableArray. But something is not working. :(
My code:
NSString *danishString = #"æøå";
NSMutableArray *characters = [[NSMutableArray alloc] initWithCapacity:[danishString length]];
for (int i=0; i < [danishString length]; i++)
{
NSString *ichar = [NSString stringWithFormat:#"%c", [danishString characterAtIndex:i ]];
[characters addObject:ichar];
}
If I do at NSLog on the danishString it works (returns æøå);
But if I do a NSLog on the characters (the array) I get some very stange characters - What is wrong?
/Morten
First of all, your code is incorrect. characterAtIndex returns unichar, so you should use #"%C"(uppercase) as the format specifier.
Even with the correct format specifier, your code is unsafe, and strictly speaking, still incorrect, because not all unicode characters can be represented by a single unichar. You should always handle unicode strings per substring:
It's common to think of a string as a sequence of characters, but when
working with NSString objects, or with Unicode strings in general, in
most cases it is better to deal with substrings rather than with
individual characters. The reason for this is that what the user
perceives as a character in text may in many cases be represented by
multiple characters in the string.
You should definitely read String Programming Guide.
Finally, the correct code for you:
NSString *danishString = #"æøå";
NSMutableArray *characters = [[NSMutableArray alloc] initWithCapacity:[danishString length]];
[danishString enumerateSubstringsInRange:NSMakeRange(0, danishString.length) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
[characters addObject:substring];
}];
If with NSLog(#"%#", characters); you see "strange character" of the form "\Uxxxx", that's correct. It's the default stringification behavior of NSArray by description method. You can print these unicode characters one by one if you want to see the "normal characters":
for (NSString *c in characters) {
NSLog(#"%#", c);
}
In your example, ichar isn't type of NSString, but unichar. If you want NSStrings try getting a substring instead :
NSString *danishString = #"æøå";
NSMutableArray *characters = [[NSMutableArray alloc] initWithCapacity:[danishString length]];
for (int i=0; i < [danishString length]; i++)
{
NSRange r = NSMakeRange(i, 1);
NSString *ichar = [danishString substringWithRange:r];
[characters addObject:ichar];
}
You could do something like the following, which should be fine with Danish characters, but would break down if you have decomposed characters. I suggest reading the String Programming Guide for more information.
NSString *danishString = #"æøå";
NSMutableArray* characters = [NSMutableArray array];
for( int i = 0; i < [danishString length]; i++ ) {
NSString* subchar = [danishString substringWithRange:NSMakeRange(i, 1)];
if( subchar ) [characters addObject:subchar];
}
That would split the string into an array of individual characters, assuming that all the code points were composed characters.
It is printing the unicode of the characters. Anyhow, you can use the unicode (with \u) anywhere.

Objective-C Iterating through an NSString to get characters

I have this function:
void myFunc(NSString* data) {
NSMutableArray *instrs = [[NSMutableArray alloc] initWithCapacity:[data length]];
for (int i=0; i < [data length]; i++) {
unichar c = [data characterAtIndex:i];
[instrs addObject:c];
}
NSEnumerator *e = [instrs objectEnumerator];
id inst;
while (inst = [e nextObject]) {
NSLog("%i\n", inst);
}
}
I think it fails at [instrs addObject:c]. It's purpose is to iterate through the hexadecimal numbers of an NSString. What causes this code to fail?
A unichar is not an object; it's an integer type.
NSMutableArray can only hold objects.
If you really want to put it into an NSMutableArray, you could wrap the integer value in an NSNumber object: [instrs addObject:[NSNumber numberWithInt:c]];
But, what's the point of stuffing the values into an array in the first place? You know how to iterate through the string and get the characters, why put them into an array just to iterate through them again?
Also note that:
the "%i" NSLog format expects an integer; you can't pass it an object
for hexadecimal output, you want "%x", not "%i"
If the function is only meant to display the characters as hexadecimal values, you could use:
void myFunc(NSString* data)
{
NSUInteger len = [data length];
unichar *buffer = calloc(len, sizeof(unichar));
if (!buffer) return;
[data getCharacters:buffer range:NSMakeRange(0, len)];
for (NSUInteger i = 0; i < len; i++)
NSLog(#"%04x", (unsigned) buffer[i]);
free(buffer);
}
This is just a little bit more efficient than your approach (also, in your approach you never release the instrs array, so it will leak in a non-garbage-collected environment).
If the string contains hexadecimal numbers, then you will want to repeatedly use an NSScanner's scanHexInt: method until it returns NO.
void myFunc(NSString* data)
{
NSScanner *scanner = [[NSScanner alloc] initWithString:data];
unsigned number;
while ([scanner scanHexInt:&number])
NSLog(#"%u", number);
[scanner release];
}

Accept string values in NSArray from the user

hi i want to accept string values into the object of NSArray at run time from the user heres what i tried
-(void)fun
{
NSArray *arr = [[NSArray alloc]init];
for(int i =0;i<3;i++)
{
scanf("%s",&arr[i]);
}
printf("Print values\n");
for(int j =0; j<3;j++)
{
printf("\n%s",arr[j]);
}
}
i am getting an error can you please help me out regarding this and is their any alternative to scanf in objective c.
Thank you
scanf() with a %s format will read the string into a C array, not an NSArray object. You need to read the string into a C array, then make an NSString object to add to your NSArray. You also need to have a mutable array to make your code work. Example:
NSMutableArray *arr = [[NSMutableArray alloc] initWithCapacity:3];
for (int i = 0; i < 3; i++)
{
char buf[100];
scanf("%s", buf);
NSString *str = [NSString stringWithCString:buf encoding:NSASCIIStringEncoding];
[arr addObject:str];
}
You can use NSLog() to print your strings later on.
use NSMutableArray instead;
than you can use also
[arr addObject:tempVar];