Getting Chars and ints from NSTextField

Discussion in 'Mac Programming' started by larswik, Aug 29, 2011.

  1. larswik macrumors 68000

    Joined:
    Sep 8, 2006
    #1
    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?
     
  2. JoshDC macrumors regular

    Joined:
    Apr 8, 2009
    #2
    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.
     
  3. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #3
    Thanks Josh, I will read the NSScanner Docs tonight. I was hoping there was an easier way. Sounds like there was.

    Thanks again!

    -Lars
     
  4. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #4
    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!
     
  5. JoshDC macrumors regular

    Joined:
    Apr 8, 2009
    #5
    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”
        }
    
     
  6. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #6
    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.
     
  7. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #7
    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!!!
     

    Attached Files:

  8. JoshDC macrumors regular

    Joined:
    Apr 8, 2009
    #8
    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
     
  9. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #9
    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!
     

Share This Page