getting multiple integer values out of textfield - objective-c

I want to read many different integer values out of an textfield and for that I have this code:
NSString *string1,*string2;
string1= [textField stringValue];
int i,c;
c=0;
NSInteger values[50];
for (i=0; i<50; ) {
string2=[NSString stringWithFormat:#"%#%i%s",#" ",i,","];
NSRange range=[string1 rangeOfString:string2];
if (range.location != NSNotFound) {
values[c]=i;
c=c+1;
}
i=i+1;
}
there is no problem with that but it can't read the first number in string like that "2, 3, 15" but I want it that it can also read a string like that, so could anybody please help me with this problem.
And if I make string2 like this #"i", "," it causes problems with values like 15 because it reads 5 and 15

How about doing this instead:
NSArray *integerStrings = [[textField stringValue] componentsSeparatedByString:#","];
for (NSString *integerString in integerStrings) {
NSDecimalNumber *number = [NSDecimalNumber decimalNumberWithString:integerString];
// do whatever you want with the number...
}
Alternatively, if the numbers are always integers, the loop could be:
for (NSString *integerString in integerStrings) {
NSInteger number = [integerString integerValue];
// do whatever you want with the number...
}

Related

How to restrict number of fraction digits when parsing number from string?

I want to restrict the number of fraction digits a user is allowed to enter into a UITextField that only accepts (localized) numeric input.
Example with 4 fraction digits allowed:
Good: 42, 10.123, 12345.2345
Bad: 0.123456, 6.54321
Right now, I'm using NSNumberFormatter's numberFromString: in the UITextField delegate's textField:shouldChangeCharactersInRange:replacementString: to determine whether it's a legal numeric value.
Unfortunately, NSNumberFormatter seems to ignore maximumFractionDigits in numberFromString:. In tests using getObjectValue:forString:range:error: I had the same problem, and range also was the full length of the string afterwards (unless I start entering letters; then range indicates only the part of the string with digits):
NSNumberFormatter* formatter = [[NSNumberFormatter alloc] init];
formatter.maximumFractionDigits = 3;
formatter.roundingMode = NSNumberFormatterRoundHalfUp;
formatter.generatesDecimalNumbers = YES;
NSDecimalNumber* n = (NSDecimalNumber*)[formatter numberFromString:#"10.12345"];
NSLog(#"Number: %#", n.description); // expected: 10.123, but is: 10.12345
How to best restrict the number of fraction digits in user input?
after you get the unrestricted number, you can use stringWithFormat on that number to create a string with a certain number of decimal places.
eg.
double number = myTextField.text.doubleValue;
NSString *restrictedString = [NSString stringWithFormat:#"%.4f", number];
There are a few ways to do this, but the easiest is probably to split the string into two parts (you will have to localize the '.') and check the length of the second part, like this:
- (BOOL)LNNumberIsValid:(NSString *)string
{
NSArray *numArray = [string componentsSeparatedByString:#"."];
if ([numArray count] == 2)
if ([[numArray objectAtIndex:1] length] > 4)
return NO;
return YES;
}
// Tests
NSLog(#"42: %i", [self LNNumberIsValid:#"42"]); // 1
NSLog(#"10.123: %i", [self LNNumberIsValid:#"10.123"]); // 1
NSLog(#"12345.2345: %i", [self LNNumberIsValid:#"12345.2345"]); // 1
NSLog(#"0.123456: %i", [self LNNumberIsValid:#"0.123456"]); // 0
NSLog(#"6.54321: %i", [self LNNumberIsValid:#"6.54321"]); // 0
EDIT:
The problem with the code that you added to your question is that you are printing the description of the NSDecimalNumber, which is not localized or limited to the number of digits. The NSDecimalNumber itself stores everything that you give it, so you need to change the original string (like my example above) if you want to change that. However, once you have your NSDecimalNumber, you can use the same number formatter to convert it back to a string in the format that you like:
NSNumberFormatter* formatter = [[NSNumberFormatter alloc] init];
formatter.maximumFractionDigits = 3;
formatter.roundingMode = NSNumberFormatterRoundHalfUp;
formatter.generatesDecimalNumbers = YES;
NSDecimalNumber* n = (NSDecimalNumber*)[formatter numberFromString:#"10.12345"];
NSString *s = [formatter stringFromNumber:n];
NSLog(#"Number: %#", s); // expected: 10.123, and is: 10.123
The way I solved this is by checking the position of the decimal separator and making sure that the insertion either is before that position or the insertion would not exceed the maximum number of fraction digits.
Also, I check that the input of a new separator does not occur at a place that would lead to more then the allowed fraction digits and that not more than one separators can be inserted
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *separator = self.numberFormatter.decimalSeparator;
if(string.length == 0) {
// Empty String means deletion, always possible
return YES;
}
// Check for valid characters (0123456789 + decimal Separator)
for (int i = 0; i < [string length]; ++i) {
unichar c = [string characterAtIndex:i];
if (![self.legalCharSet characterIsMember:c])
{
return NO;
}
}
// Checks if input is separator
if([string isEqualToString:separator]) {
// Check that separator insertion would not lead to more than 2 fraction digits and that not more than one separators are inserted
// (the MIN() makes sure that length - kMaxFractionDigits won’t be below 0 as length and location are NSUIntegers)
return range.location >= self.valueField.text.length - MIN(self.valueField.text.length,kMaxFractionDigits) && [self.valueField.text containsString:separator] == NO;
} else {
// Check if a separator is already included in the string
NSRange separatorPos = [self.valueField.text rangeOfString: separator];
if(separatorPos.location != NSNotFound) {
// Make sure that either the input is before the decimal separator or that the fraction digits would not exceed the maximum fraction digits.
NSInteger fractionDigits = self.valueField.text.length - (separatorPos.location + 1);
return fractionDigits + string.length <= kMaxFractionDigits || range.location <= separatorPos.location;
}
}
return YES;
}
The method may not be bullet proof but it should be sufficient for common text insertions.

Is there any method that can take "one" and return "1"?

I've looked at NSNumberFormatter, but that hasn't worked, so is there a way of parsing written numbers and turning them in to actual numbers?
Something like this would work (for positive whole numbers anyway). This is just a starting point, you would have to check to see that the words were correct and maybe ignore capitalization to make it more robust:
[self parseNumberWords:#"five two three"];
-(NSInteger)parseNumberWords:(NSString *)input {
NSArray *wordArray = [NSArray arrayWithObjects:#"zero",#"one",#"two",#"three",#"four",#"five",#"six",#"seven",#"eight",#"nine", nil];
NSArray *words = [input componentsSeparatedByString:#" "];
NSInteger num = 0;
NSInteger j =0;
for (NSInteger i = [words count]; i>0 ;i--) {
num = num + [wordArray indexOfObject:[words objectAtIndex:i-1]] * pow(10, j);
j = j+1;
}
NSLog(#"%ld",num);
return num;
}
NSNumberFormatter will get you some of the way there, via NSNumberFormatterSpellOutStyle. The basic formatting that NSNumber does will finish it off.
NSNumberFormatter * nf = [[NSNumberFormatter alloc] init];
[nf setNumberStyle:NSNumberFormatterSpellOutStyle];
NSString * numberWordString = #"three one two";
NSMutableString * digitString = [[NSMutableString alloc] init];
// Break up the input string at spaces and iterate over the result
for(NSString * s in [numberWordString componentsSeparatedByString:#" "]){
// Let the formatter turn each string into an NSNumber, then get
// the stringValue from that, which will be a digit.
[digitString appendString:[[nf numberFromString:s] stringValue]] ;
}
NSLog(#"%#", digitString); // prints "312"
Obviously, you'll have to put some work in to handle different input formats, lowercase, bad input (this will crash if nf fails to format -- it'll return nil which is an illegal argument to appendString:), etc.

Compare two NSStrings

In my app there is a mechanism that requires that at a certain point two NSStrings will be the same to do something; for some reason when I compare the two, even when they are the same, it still doesn't recognize that. The code is something like this:
NSString * aString = [self someMethodThatGetsAString];
NSString * bString;
BOOL areStringsTheSame = NO;
while (areStringsTheSame != YES) {
bString = [self someMethodThatTakesNSStringsFromAnArrey];
if (bString == aString) {
areStringsTheSame = YES;
{ }
I even inserted an NSLog() and made sure that at a certain point they were the same (and as far as I know this is what == stands for...), but still it didn't get into the if to change the BOOL value.
Is there another way to do this comparison? Am I missing something?
You can use the method isEqualToString::
if ([bString isEqualToString:aString])
== compares the references (addresses of) the strings, and not the value of the strings.
This approach worked for me:
if ([firstString compare:secondString] == NSOrderedSame) {
//Do something when they are the same
} else {
//Do something when they are different
}
Recently I was shocked by the fact that two NSStrings that resemble each other on NSLog may be different. It is because sometimes NSString can contain a zero width space character. Be aware of that and consider:
#define ZERO_WIDTH_SPACE_STRING #"\u200B"
To conquer this you should clean your string from zero width white space characters before comparing:
NSMutableString *eMailToAdd = [NSMutableString string];
NSMutableCharacterSet *charSet = [[NSCharacterSet whitespaceCharacterSet] mutableCopy];
//[charSet formUnionWithCharacterSet:[NSCharacterSet punctuationCharacterSet]];
NSString *rawStr = [[tokenField textField] text];
for (int i = 0; i < [rawStr length]; i++)
{
if (![charSet characterIsMember:[rawStr characterAtIndex:i]])
{
[eMailToAdd appendFormat:#"%#",[NSString stringWithFormat:#"%c", [rawStr characterAtIndex:i]]];
}
}

can I store an id value in array of float type?

I used,
for(id value in values) to get the value from an NSArray. Now I want to store it in 2 dimensional float array[][]. When I try to assign the values to array it is giving error:incompatible types in assignment.
I tried to cast the value but I got error: pointer value used where a floating point value was expected. I need to store the values in an 2 dimensional array . How can I make it ?
Thank You.
#implementation fromFileRead1
NSString *fileNameString;
int numberOfEnemies, numberOfValues;
-(id)init
{
if( (self = [super init]) )
{
NSString *path = #"/Users/sridhar/Desktop/Projects/exampleOnFile2/enemyDetals.txt";
NSString *contentsOfFile = [[NSString alloc] initWithContentsOfFile:path];
NSArray *lines = [contentsOfFile componentsSeparatedByString:#"\n"];
numberOfEnemies = [lines count];
NSLog(#"The number of Lines: %d", numberOfEnemies);
for (id line in lines)
{
NSLog(#"Line %#", line );
NSString *string1 = line;
NSArray *split1 = [string1 componentsSeparatedByString:#","];
numberOfValues = [split1 count];
NSLog(#"The number of values in Row: %d", numberOfValues);
for (id value in split1)
{
NSLog(#"value %#", value);
float value1;
value1 = [split1 objectAtIndex:2]);
NSLog(#"VAlue of Value1 at index 2: %f", value1 );
}
}
}
return self;
}
#end
In enemyDetal.txt I have
1,3,3
2,3,2.8
10,2,1.6
Storing an object (e.g. id) in a float array is most certainly not what you want, and will give you the weirdest results.
The question is what you really want to do. If you have NSNumber objects in your array containing float values, then you can use [value floatValue] to convert your object to a float primitive.
If your intention was really to store a pointer as a float try (float)((int)value)). This might work but be warned that this you will most likely not be able to retrieve the pointer again.

NSString : number of a word [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Number of occurrences of a substring in an NSString?
I would like to know if there's a method which returns the occurrence of a given word.
NSString *string = #"ok no ok no no no ok";
// How to return 4 for the word no ?
Thanks for your help !
use this API: - (NSArray *)componentsSeparatedByString:(NSString *)separator
NSString* stringToSearch = #"ok no ok no no no ok";
NSString* stringToFind = #"no";
NSArray *listItems = [list componentsSeparatedByString:stringToFind];
int count = [listItems count] - 1;
You will get number of occurences of string #"no" in "count" variable
If you are writing a 10.5+ only application, you should be able to use NSString's stringByReplacingOccurrencesOfString:withString: method to do this with fairly minimal code, by checking the length before and after removing the string you're searching for.
Example below (untested as I'm working on 10.4, but can't see why it wouldn't work.) I wouldn't make your application 10.5+ only just to use this though, plenty of other methods suggested by Macmade and in the duplicate question.
NSString* stringToSearch = #"ok no ok no no no ok";
NSString* stringToFind = #"no";
int lengthBefore, lengthAfter, count;
lengthBefore = [stringToSearch length];
lengthAfter = [[stringToSearch stringByReplacingOccurrencesOfString:stringToFind withString:#""] length];
count = (lengthBefore - lengthAfter) / [stringToFind length];
NSLog(#"Found the word %i times", count);
You want to use an NSScanner for this sort of activity.
NSString *string = #"ok no ok no no no ok";
NSScanner *theScanner;
NSString *TARGET = #"no"; // careful selecting target string this would detect no in none as well
int count = 0;
theScanner = [NSScanner scannerWithString:string];
while ([theScanner isAtEnd] == NO)
{
if ([theScanner scanString:TARGET intoString:NULL] )
count++;
}
NSLog(#"target (%#) occurrences = %d", TARGET, count)
;
May not be the fastest way, but you can use the NSString componentsSeparatedByString method to separate your values into an array, and then work with that array to check how many times the string 'no' is contained...
Otherwise, work on a C string ptr, and loop, incrementing the ptr, while using strncmp() or so...