Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

larswik

macrumors 68000
Original poster
Sep 8, 2006
1,552
11
I am trying to find a way to maka my Role Playing XP Tracker program easier to use. I have 1 NSTextField where they type in the numbers and another where you add a character.

So the GM would say "You took a 12B Damage". 12 being the hit points and B being the critical which in this example would be equal to 20 for a total of 22 hit points.

I currently convert the 12 in the NSTextField to in INT. Then take the 'B' and pass it as an argument in method with a bunch of IF statements (like a switch) and then B returns the INT 20. Add them together and get 22.

The people I play with said they would rather type '12B' into one NSTextField to make it faster. I know I could use code like this to extract each one.
Code:
for(int i =0 ;i<[myString length]; i++) {
  char = [myString characterAtIndex:i];
}

What would be a good way to convert it? char '1' and '2' would need to be int 12 and not int 1 and 2?

Any ideas on how to process?
 

JoshDC

macrumors regular
Apr 8, 2009
115
0
NSScanner will probably do it. Create a new scanner with the textfield's string and use scanInteger: to get the integer and scanCharactersFromSet:intoString: to get the character.

If you're targeting 10.7 NSRegularExpression may be of use, but I'd stick with NSScanner.
 

larswik

macrumors 68000
Original poster
Sep 8, 2006
1,552
11
Thanks Josh, I will read the NSScanner Docs tonight. I was hoping there was an easier way. Sounds like there was.

Thanks again!

-Lars
 

larswik

macrumors 68000
Original poster
Sep 8, 2006
1,552
11
I got the code to work tonight using the NSScanner and reading the doc's for NSScanner and NSCharacterSet. I wish there was a reverse of 'decimalDigitCharacterSet'. I was able to use this to remove all the numbers. Would have been nice to have one remove all the numbers.

Code:
- (IBAction)convertButton:(id)sender {
    
    tempString = [readInTextField stringValue]; //Read in TextField to NSString
    
    scanLetter = [[NSScanner alloc] initWithString:tempString]; // Instantiate NSScanner for Letters and numbers
    scanNumber = [[NSScanner alloc] initWithString:tempString];
    NSCharacterSet *cSet = [NSCharacterSet characterSetWithCharactersInString:tempString]; //Convert string to an NSCharacterSet
    
    [scanLetter setCharactersToBeSkipped:[NSCharacterSet decimalDigitCharacterSet]]; //Set up the scanner to remove all numbers.
    [scanLetter scanCharactersFromSet:cSet intoString:&tempString]; //Read in teh cSet and place them into the NSString
    [lettersReturnTextField setStringValue: tempString]; // set the TextField to the calue of NSString
    
    [scanNumber scanInt: &numbers]; // Scans in the numbers.
    tempString = [NSString stringWithFormat:@"%d", numbers]; // I formatted the Int to a NSString
    [numbersReturnTextField setStringValue:tempString]; // Set the TextField for the calue of the string.
        
    
    [scanLetter release];
    [scanNumber release];
}

For my purposes the user enter the numbers first and then a letter '56E'. I don;t know what is so special about a CharacterSet vs. an mutable string.

Thanks for your help. It was nice to learn something new!
 

JoshDC

macrumors regular
Apr 8, 2009
115
0
Seems a bit of an odd way to do it. You'd usually just use a single scanner. The scanner remembers it's location, so with "14E" once you've scanned the integer the scanner's location is 2. You then scan all uppercase characters to get the E.

Code:
    NSString *tempString = @"14E";
    NSCharacterSet *alphCharSet = [NSCharacterSet uppercaseLetterCharacterSet];
    
    NSInteger intValue = 0;
    NSString *character = nil;
    
    NSScanner *stringScanner = [NSScanner scannerWithString:tempString];
        
    if ([stringScanner scanInteger:&intValue]) {
        // We scanned the integer “14”
    }
    else {
        // Doesn't start with an integer, invalid?
    }
    
    if ([stringScanner scanCharactersFromSet:alphCharSet intoString:&character]) {
        // We scanned the character “E”
    }
 

chown33

Moderator
Staff member
Aug 9, 2009
10,732
8,408
A sea of green
I wish there was a reverse of 'decimalDigitCharacterSet'.

Expand your horizons. Look farther than just the thing in front of you. Look at other classes and methods that are named in whatever you're reading.

NSCharacterSet has a -invertedSet method.

NSMutableCharacterSet has a -invert method.
 

larswik

macrumors 68000
Original poster
Sep 8, 2006
1,552
11
Josh - It was the first time using the NSScanner. First I thought I needed to put the NSScanner in a loop because I thought it got 1 index item at a time. But when I ran it I saw that it would capture all of the same type then stop. So 12AB34 would show up as '12' for the integer and then AB34 should up in the letter area.

Chown33- I will look into that Method to invert. In the doc's this code sample through me off for a while 'NSString**', 2 asterisks? after a while it came to me that it was the address '&' and the pointer. (hope I said that right).

I included the project in a zip file. I will look at the code tonight again and refine it. But should this be in a loop and then with in the loop say IF it is a Character but in to a mutable letter string, else add to mutable number string?

Thanks again!!!
 

Attachments

  • NSScanner_Test.zip
    34.2 KB · Views: 42

JoshDC

macrumors regular
Apr 8, 2009
115
0
I'm assuming the format should always be <Integer><Letter>, and therefore something like 12AB34 should be invalid?

I think you're not quite understanding how NSScanner works. In your case it doesn't need to be put in a loop, and you only need one per string.

With a correct input you should only require:

Code:
[stringScanner scanInteger:&intValue];
[stringScanner scanCharactersFromSet:[NSCharacterSet uppercaseLetterCharacterSet]  intoString:&character];

This page can better explain how a scanner works (under “Using a Scanner”):
http://developer.apple.com/library/...rs.html#//apple_ref/doc/uid/20000147-BCIEFGHC
 

larswik

macrumors 68000
Original poster
Sep 8, 2006
1,552
11
Yes, you are correct, it would be that method. I was thinking about some type of error correction in case the put B12 instead of 12B. Also on the very rare occasion when you roll really well you end up with 2 crits (letters) 56DE.

I will play with the scanner more tonight and look over the link you sent. I am new to programming NSScanner.

Thanks!
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.