iOS return one digit fragment from NSString - objective-c

I can't find an easy way to generate a one digit sized substring from an NSString. The NSString looks like "(N3)" but I need to store just the number portion "3" in an substring. Using:
NSString *subString = [dis substringFromIndex:2];
returns "3)".
Any ideas?

Well, if the string is one digit and its position is invariant, you could just use:
int Foo(NSString * dis) {
const unichar c = [dis characterAtIndex:2];
assert(isdigit(c) && "not a number");
return c - '0';
}

Related

Comparing string to a character of another string?

Here's my program so far. My intention is to have it so the if statement compares the letter in the string letterGuessed to a character in the string userInputPhraseString. Here's what I have. While coding in xCode, I get an "expected '['"error. I have no idea why.
NSString *letterGuessed = userInputGuessedLetter.text;
NSString *userInputPhraseString = userInputPhraseString.text;
int loopCounter = 0;
int stringLength = userInputPhraseString.length;
while (loopCounter < stringLength){
if (guessedLetter isEqualToString:[userInputPhraseString characterAtIndex:loopIndexTwo])
{
//if statement true
}
loopCounter++;
}
You are missing enclosing square brackets on this line:
if (guessedLetter isEqualToString:[userInputPhraseString characterAtIndex:loopIndexTwo])
It should be:
if ([guessedLetter isEqualToString:[userInputPhraseString characterAtIndex:loopIndexTwo]])
Edit that won’t fix your problem, though, because characterAtIndex: returns a unichar, not an NSString.
It's not clear what you are trying to do.. But I suppose that letterGuessed has one character... And that userInputPhraseString has many characters. So you want to know if letterGuessed is inside userInputPhraseString correct?
This is one solution without loops involved.. I replaced the input with fixed values for testing and tested the code.. It works.
NSString *letterGuessed = #"A"; //Change to your inputs
NSString *userInputPhraseString = #"BBBA"; //Since it has A it will be true in the test
NSCharacterSet *cset = [NSCharacterSet characterSetWithCharactersInString:letterGuessed];
NSRange range = [userInputPhraseString rangeOfCharacterFromSet:cset];
if (range.location != NSNotFound) { //Does letterGuessed is in UserInputPhraseString?
NSLog(#"YES"); //userInput Does contain A...
} else {
NSLog(#"NO");
}
In regards to your code... I fixed a couple of errors, first you are trying to get a UniChar (Integer) value for the character and want to compare it to a NSString which is an Object. Also fixed a couple of issues with syntax you had and used the right approach which is to return a range of characters. Again for doing what you want to accomplish the example above is the best approach I know, but for the sake of learning, here is your code fixed.
NSString *letterGuessed = #"A"; //Change to your inputs
NSString *userInputPhraseString = #"BBBA"; //Since it has A it will be true in the test
NSInteger loopCounter = 0; //Use NSInteger instead of int.
NSInteger stringLength = userInputPhraseString.length;
BOOL foundChar = NO; //Just for the sake of returning NOT FOUND in NSLOG
while (loopCounter < stringLength){
//Here we will get a letter for each iteration.
NSString *scannedLetter = [userInputPhraseString substringWithRange:NSMakeRange(loopCounter, 1)]; // Removed loopCounterTwo
if ([scannedLetter isEqualToString:letterGuessed])
{
NSLog(#"FOUND CHARACTER");
foundChar = YES;
}
loopCounter++;
}
if (!foundChar) NSLog(#"NOT FOUND");
NSRange holds the position, length.. So we move to a new position on every iteration and then get 1 character.
Also if this approach is what you want, I would strongly suggest a for-loop.

Compare char array with string in iOS program [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
How to compare char* and NSString?
If I have:
char XYZ[256]="";
how can I compare this char array with another string (e.g. "testing") in an iOS Objective-C program?
Use strcmp
char XYZ[256] = "";
char *string = "some other string";
int order = strcmp(XYZ, string);
RETURN VALUES
The strcmp() and strncmp() functions return an integer greater than, equal to, or less than 0, according as the string s1 is greater than, equal to, or less than the string s2. The comparison is done using unsigned characters, so that \200' is greater than\0'.
You can also convert them up to NSString, this makes a lot overhead, but brings your string to Objective-C object:
char XYZ[256] = "";
NSString *s = [[NSString alloc] initWithBytes:XYZ length:strlen(XYZ) encoding:[NSString defaultCStringEncoding]];
NSString *testing = #"testing";
if ([testing compare:s] == NSOrderedSame) {
NSLog(#"They are hte same!");
}
Note that strcmp is A LOT faster!
Just because it is iOS doesnt mean that you cannot "#include" string.h and use "strcmp" (now as stated above).
The alternative would be to create a new NSString and compare it using a comperable iOS Objective-C call:
NSString myString = [NSString stringWithCString:XYZ encodingNSASCIIStringEncoding];
if(YES == [myString isEqualToString:#"testing"]){
// Perform Code if the strings are equal
}else{
// Perform Code if the strings are NOT equal
}

In Objective-C, how to print out N spaces? (using stringWithCharacters)

The following is tried to print out N number of spaces (or 12 in the example):
NSLog(#"hello%#world", [NSString stringWithCharacters:" " length:12]);
const unichar arrayChars[] = {' '};
NSLog(#"hello%#world", [NSString stringWithCharacters:arrayChars length:12]);
const unichar oneChar = ' ';
NSLog(#"hello%#world", [NSString stringWithCharacters:&oneChar length:12]);
But they all print out weird things such as hello ÔÅÓñüÔÅ®Óñü®ÓüÅ®ÓñüÔ®ÓüÔÅ®world... I thought a "char array" is the same as a "string" and the same as a "pointer to a character"? The API spec says it is to be a "C array of Unicode characters" (by Unicode, is it UTF8? if it is, then it should be compatible with ASCII)... How to make it work and why those 3 ways won't work?
You can use %*s to specify the width.
NSLog(#"Hello%*sWorld", 12, "");
Reference:
A field width, or precision, or both, may be indicated by an asterisk
( '*' ). In this case an argument of type int supplies the field width
or precision. Applications shall ensure that arguments specifying
field width, or precision, or both appear in that order before the
argument, if any, to be converted.
This will get you what you want:
NSLog(#"hello%#world", [#"" stringByPaddingToLength:12 withString:#" " startingAtIndex:0]);
I think the issue you have is you are misinterpreting what +(NSString *)stringWithCharacters:length: is supposed to do. It's not supposed to repeat the characters, but instead copy them from the array into a string.
So in your case you only have a single ' ' in the array, meaning the other 11 characters will be taken from whatever follows arrayChars in memory.
If you want to print out a pattern of n spaces, the easiest way to do that would be to use -(NSString *)stringByPaddingToLength:withString:startingAtIndex:, i.e creating something like this.
NSString *formatString = #"Hello%#World";
NSString *paddingString = [[NSString string] stringByPaddingToLength: n withString: #" " startingAtIndex: 0];
NSLog(formatString, paddingString);
This is probably the fastest method:
NSString *spacesWithLength(int nSpaces)
{
char UTF8Arr[nSpaces + 1];
memset(UTF8Arr, ' ', nSpaces * sizeof(*UTF8Arr));
UTF8Arr[nSpaces] = '\0';
return [NSString stringWithUTF8String:UTF8Arr];
}
The reason your current code isn't working is because +stringWithCharacters: expects an array with a length of characters of 12, while your array is only 1 character in length {' '}. So, to fix, you must create a buffer for your array (in this case, we use a char array, not a unichar, because we can easily memset a char array, but not a unichar array).
The method I provided above is probably the fastest that is possible with a dynamic length. If you are willing to use GCC extensions, and you have a fixed size array of spaces you need, you can do this:
NSString *spacesWithLength7()
{
unichar characters[] = { [0 ... 7] = ' ' };
return [NSString stringWithCharacters:characters length:7];
}
Unfortunately, that extension doesn't work with variables, so it must be a constant.
Through the magic of GCC extensions and preprocessor macros, I give you.... THE REPEATENATOR! Simply pass in a string (or a char), and it will do the rest! Buy now, costs you only $19.95, operators are standing by! (Based on the idea suggested by #JeremyL)
// step 1: determine if char is a char or string, or NSString.
// step 2: repeat that char or string
// step 3: return that as a NSString
#define repeat(inp, cnt) __rep_func__(#encode(typeof(inp)), inp, cnt)
// arg list: (int siz, int / char *input, int n)
static inline NSString *__rep_func__(char *typ, ...)
{
const char *str = NULL;
int n;
{
va_list args;
va_start(args, typ);
if (typ[0] == 'i')
str = (const char []) { va_arg(args, int), '\0' };
else if (typ[0] == '#')
str = [va_arg(args, id) UTF8String];
else
str = va_arg(args, const char *);
n = va_arg(args, int);
va_end(args);
}
int len = strlen(str);
char outbuf[(len * n) + 1];
// now copy the content
for (int i = 0; i < n; i++) {
for (int j = 0; j < len; j++) {
outbuf[(i * len) + j] = str[j];
}
}
outbuf[(len * n)] = '\0';
return [NSString stringWithUTF8String:outbuf];
}
The stringWithCharaters:length: method makes an NSString (or an instance of a subclass of NSString) using the first length characters in the C array. It does not iterate over the given array of characters until it reaches the length.
The output you are seeing is the area of memory 12 Unicode characters long starting at the location of your passed 1 Unicode character array.
This should work.
NSLog(#"hello%#world", [NSString stringWithCharacters:" " length:12]);

How to extract elements of NSArray and convert them(parseInt) to integer values?

I have a string which is a 13 digit number. I need to separate all the digits and find the sum of the individual digits. How can I do that?
I converted the string to NSArray like this :
NSArray *arrStrDigits = [str13DigitNumber componentsSeparatedByString:#""];
now I want to run a loop and get something like arrStrDigits[i]
I am new to Objective C :(. Please help me out!
Get the individual digits like this:
unichar digitChar = [str13DigitNumber characterAtIndex: someIndex];
// Should put in some validation that you have a digit here
int digit = digitChar - '0';
That just needs to go in a loop where you iterate someIndex from 0 to [str13DigitNumber length]
int total=0;
for(NSString *numberInString in arrStrDigits)
{
total+=[numberInString intValue];
}
Note: I am assuming you have int's in each position of your array.
Note 1: This answer is only related to what you ask (run a loop, nothing else).

Objective-C NSString for loop with characterAtIndex

I'm trying to loop through a NSString, character by character, but I'm getting a EXC_BAD_ACCESS error. Do you have an idea how to do this right? I've been googling for hours now but can't figure it out.
Here is my code (.m):
self.textLength = [self.text length];
for (int position=0; position < self.textLength; position++) {
NSLog(#"%#", [self.text characterAtIndex:position]);
if ([[self.text characterAtIndex:position] isEqualToString:#"."]){
NSLog(#"it's a .");
}
}
Thanks a lot!
Characters are not object. characterAtIndex returns unichar, which is actually an integer type unsigned short. You need to use %C instead of %# in NSLog. Also character is not a NSString, so you can't send it isEqualToString. You need to use ch == '.' to compare ch against '.'.
unichar ch = [self.text characterAtIndex:position];
NSLog(#"%C", ch);
if (ch == '.') {} // single quotes around dot, not double quotes
Note that, 'a' is character, "a" is C string and #"a" is NSString. They all are different types.
When you are using %# with unichar ch in NSLog, it is trying to print an object from memory location ch which is invalid. Thus you are getting a EXC_BAD_ACCESS.
characterAtIndex: returns a unichar, so you should use NSLog(#"%C", ...) instead of #"%#".
You also cannot use isEqualToString for a unichar, just use == '.' is fine.
If you want to find the position of all '.'s, you can use rangeOfString. Refer to:
String Programming Guide: Searching, Comparing, and Sorting Strings
Position of a character in a NSString or NSMutableString
characterAtIndex: returns a unichar, which is declared as typedef unsigned short unichar; The format specifier you are using in your calls to NSLog are incorrect, you could just do NSLog(#"%u",[self.text characterAtIndex:position]); or NSLog(#"%C",[self.text characterAtIndex:position]); if you want the actual character to print out.
Also, as a result of unichar being defined the way that it is, it's not a string, so you cannot compare it to other strings. Try something like:
unichar textCharacter = '.';
if ([self.text characterAtPosition:position] == testCharacter) {
// do stuff
}
If you want to find the location of a character in a string you can use this:
NSUInteger position = [text rangeOfString:#"."].location;
if the character or text is not found you will get a NSNotFound:
if(position==NSNotFound)
NSLog(#"text not found!");