7

How to check if a string contains a valid number considering localized number formats.

This question is not primary about converting a number. I can do that with NSNumberFormatter. And if I can't then I don't even need to do it and can leave the string as string. But I need to check whether it contains a valid numer.

BTW, we are in the middle of a textField:shouldChangeCharactersInRange: ... delegate method. Here I want to prevent keying in illegal characters by returning NO.

This is the code that I have:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {

    // Only test for numbers if it is a certain text field. 
    if (textField == self.numValueTextField) {
        NSString *resultingString = [textField.text stringByReplacingCharactersInRange: range withString: string];

        // The user deleting all input is perfectly acceptable.
        if ([resultingString length] == 0) {
            return true;
        }

        double holder;

        NSScanner *scan = [NSScanner scannerWithString: resultingString];

        BOOL isNumeric = [scan scanDouble: &holder] && [scan isAtEnd];

        if (isNumeric) {

            [self.detailItem setValue:number forKey:kValueDouble];
        }

        return isNumeric;
    }
    return YES;  // default for any other text field - if any.
}

That works fine but it implies English notations. Meaning the floating point must be a pont. But it could be a comma or whatever in certain parts of the world.

I do know how to check for certain characters. So I could check for 0-9, comma and point. But is there a 'proper' way of doing that?

If it is of importance: I am in an iOS environment.

4

4 に答える 4

8

数値フォーマッタはデフォルトで現在のロケールの情報を使用するため、このチェックを行うことができるはずです。文字列をフォーマットしてみてください。結果が の場合、nil有効ではありません。

static NSNumberFormatter * formatter = [NSNumberFormatter new];
//... build string
NSNumber * num = [formatter numberFromString:resultingString];
BOOL isNumeric = (num != nil);

例えば:

NSNumberFormatter * formatter = [NSNumberFormatter new];

// US uses period as decimal separator
[formatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];

NSLog(@"%@", [formatter numberFromString:@"3.1415"]);   // Valid NSNumber
NSLog(@"%@", [formatter numberFromString:@"3.14.15"]);  // nil
NSLog(@"%@", [formatter numberFromString:@"31415"]);    // Valid
NSLog(@"%@", [formatter numberFromString:@"3,1415"]);   // nil

// Italy uses a comma as decimal separator
[formatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"it"]];
NSLog(@"%@", [formatter numberFromString:@"3.1415"]);    // nil
NSLog(@"%@", [formatter numberFromString:@"3.14.15"]);   // nil
NSLog(@"%@", [formatter numberFromString:@"31415"]);     // Valid
NSLog(@"%@", [formatter numberFromString:@"3,1415"]);    // Valid

または、 を使用することを好むかもしれません。これは、単純にまたはをgetObjectValue:forString:range:error:返し、解析の成功を示し、さらに詳細に関心がある場合はエラー オブジェクトも提供します。YESNO

于 2013-03-11T22:43:46.653 に答える
0

率直に言って、部分的な数値でも機能するはずの有効な数値のテストは、実装が非常に難しいものです。

  1. で既に実装されているチェックを再実装しようとしないでくださいNSNumberFormatter。言語が異なれば、異なる小数点記号が使用されますが、数字も異なります (編集: 残念ながら、NSNumberFormatter非アラビア数字も検証できません)。

  2. 有効な数値ではないが、有効な数値になる特殊なケースが多数あります。たとえば、空の文字列、マイナス記号、小数点記号、マイナス記号と小数点記号の組み合わせなどです。科学的表記法を許可すると、さらに複雑になります。

最も簡単な解決策は、最終的な数字だけをチェックすることです。ユーザーが確認したら、入力を確認します (Enter をタップ、入力ビューの外側をタップ)。

NSNumberFromatterただし、部分的な文字列を実際に検証できることにも注意してください。詳細については、そのスーパークラスNSFormatterを参照してください。

于 2014-05-06T22:47:42.807 に答える