文字列が数値かどうかを調べる


93

文字列が数字のみで構成されているかどうかを確認するにはどうすればよいですか。文字列から部分文字列を取り出して、それが数値部分文字列かどうかを確認したいと思います。

NSString *newString = [myString substringWithRange:NSMakeRange(2,3)];

回答:


241

以下は、文字列を数値として解析する際の限られた精度に依存しない方法の1つです。

NSCharacterSet* notDigits = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
if ([newString rangeOfCharacterFromSet:notDigits].location == NSNotFound)
{
    // newString consists only of the digits 0 through 9
}

+[NSCharacterSet decimalDigitCharacterSet]およびを参照してください-[NSString rangeOfCharacterFromSet:]


6
これは@ "231.123"にも当てはまるので、// newStringは0〜9の数字と.文字のみで構成されます
Nicolas Tyler

5
NSMutableCharacterSet * digitsAndDots = [NSMutableCharacterSet decimalDigitCharacterSet]; [digitsAndDots addCharactersInString:@ "。"]; NSCharacterSet * notDigitsNorDots = [digitsAndDots invertedSet]; //また、「invertedSet」を導入していただきありがとうございます。私はその存在を知りませんでした
codrut

5
注:このメソッドは@ ""を数値と見なします。該当する場合は、[newString lenght]> 0も確認する必要がある場合があります。間違っている場合はお知らせください。
markckim

2
@SupertecnoboffこれはIOSで変更されたもののようです。代わりにこれを使用して確認できます:[[NSCharacterSet characterSetWithCharactersInString:@"0123456789."] invertedSet]]
Nicolas Tyler

2
@KMGorbunov NSCharacterSetが実際にセット内のすべての文字を含むバッキングセットを格納しているとは思いません。invertedSet作成されたセットをフォームでラップしたクラスを返し、すべてのクエリに対して反対の値を返すのではないかと思います。しかし、私にははっきりとはわかりません。
John Calsbeek、

33

NSNumberFormatterクラスのnumberFromString:メソッドを使用することをお勧めします。数値が無効な場合、nilが返されます。それ以外の場合は、NSNumberを返します。

NSNumberFormatter *nf = [[[NSNumberFormatter alloc] init] autorelease];
BOOL isDecimal = [nf numberFromString:newString] != nil;

たとえば、@ "124sbd"の場合、有効な数値が返されないのですか?
トミー

いいえ、NSNumberFormatterとNSScannerの両方がNO文字列を返します。また、知っておく価値があります:YES空白で埋められた数値も返されます。ところで、私はあなたの答えに実際のコードスニペットを追加しました、気にしないでください。
Regexident

NSScannerは、「有効な整数表現」を見つけたドキュメントに従って、その文字列に対して「YES」を返す必要があります。さらに、iOS 4.3.2でのテストでもまったく同じでした。ただし、NSNumberFormatterはnilを返しました。
トミー

これは「。」をキャッチしません。これは私にとって必要条件です。@John Calsbeekからの回答はうまくいきました。
ダミアン

何百もの文字がすべて数字の文字列はどうなりますか?作成されるNSNumberに制限はありますか?
Biniou 2017年

11

正規表現、パターン"^[0-9]+$"、次の方法で検証します-validateString:withPattern:

[self validateString:"12345" withPattern:"^[0-9]+$"];
  1. 「123.123」を考慮した場合
    • パターンあり "^[0-9]+(.{1}[0-9]+)?$"
  2. 正確に4桁の数字の場合、なし"."
    • パターン付き"^[0-9]{4}$"
  3. なしの数字の場合"."、長さは2〜5の間です。
    • パターン付き"^[0-9]{2,5}$"
  4. マイナス記号付き: "^-?\d+$"

正規表現は、オンラインWebサイトで確認できます。

ヘルパー関数は以下の通りです。

// Validate the input string with the given pattern and
// return the result as a boolean
- (BOOL)validateString:(NSString *)string withPattern:(NSString *)pattern
{
    NSError *error = nil;
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:&error];

    NSAssert(regex, @"Unable to create regular expression");

    NSRange textRange = NSMakeRange(0, string.length);
    NSRange matchRange = [regex rangeOfFirstMatchInString:string options:NSMatchingReportProgress range:textRange];

    BOOL didValidate = NO;

    // Did we find a matching range
    if (matchRange.location != NSNotFound)
        didValidate = YES;

    return didValidate;
}

Swift 3バージョン:

遊び場でテストします。

import UIKit
import Foundation

func validate(_ str: String, pattern: String) -> Bool {
    if let range = str.range(of: pattern, options: .regularExpression) {
        let result = str.substring(with: range)
        print(result)
        return true
    }
    return false
}

let a = validate("123", pattern: "^-?[0-9]+")
print(a)

私はSwift 3でこれを試してみました。func numberOnly(string: String) -> Int { let expression = "" let regex = NSRegularExpression.init(pattern: expression, options: .caseInsensitive) let numberOfMatches = regex.numberOfMatches(in: string, options: .reportProgress, range: NSRange.init(location: 0, length: string.characters.count)) if numberOfMatches == 0 { return Int(string)! } return 0 }エラーが発生しましたPlayground execution aborted: error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
Mathi Arasan 2017

Swift 3で正しいものはわかりません。間違っている場合は修正してください。
Mathi Arasan 2017

いかがですかreturn matchRange.location != NSNotFound;
LimeRed

マイナス記号はどうですか?
トーマス

@Thomas With ^-?\d+$、私はサイトでそれを確認しました:regex101.com
AechoLiu

9

NSScannerを作成して、文字列をスキャンするだけです。

NSDecimal decimalValue;
NSScanner *sc = [NSScanner scannerWithString:newString];
[sc scanDecimal:&decimalValue];
BOOL isDecimal = [sc isAtEnd];

チェックアウトNSScannerのドキュメントから選択する多くの方法のために。


少なくとも最初の文字が数字であるかどうかを教えてくれませんか?
トミー

私の悪い。への最後の呼び出しを忘れましたisAtEnd
Regexident

6

特定の文字列内のすべての文字が数値であることを確認する最も簡単な方法は、おそらく次のとおりです。

NSString *trimmedString = [newString stringByTrimmingCharactersInSet:[NSCharacterSet decimalDigitCharacterSet]];

if([trimmedString length])
{
    NSLog(@"some characters outside of the decimal character set found");
}
else
{
    NSLog(@"all characters were in the decimal character set");
}

許容可能な文字を完全に制御したい場合は、他のNSCharacterSetファクトリメソッドのいずれかを使用します。


私はこのように好きです。見た目はすっきりしていませんが、NSStringに「数字以外」があるかどうかを確認するための、非常に簡単でコアとなる基盤に適した方法です。+他のロボットベースの方法よりもはるかに高速だと思います(ただし、ここではパフォーマンスをあまり見ていません)。
nembleton 2012

stringByTrimmingCharactersInSetは、文字列の開始と終了のみをトリミングすると思います
Brody Robertson

@BrodyRobertson:あります。これは、この回答にとって重要ではありません。このテストが失敗する例は何ですか?
トミー

@トミー、再評価した後、あなたの回答を理解しました。回答は有効であり、賛成票を投じますが、編集を許可して編集を許可する必要があります
Brody Robertson

6

この最初の質問はObjective-Cに関するものでしたが、Swiftが発表される何年も前に投稿されました。したがって、Googleから来て、Swiftを使用するソリューションを探している場合は、次のようにします。

let testString = "12345"
let badCharacters = NSCharacterSet.decimalDigitCharacterSet().invertedSet

if testString.rangeOfCharacterFromSet(badCharacters) == nil {
    print("Test string was a number")
} else {
    print("Test string contained non-digit characters.")
}

6

文字列が数字のみであることを確認する必要がある場合のSwift 3ソリューション:

CharacterSet.decimalDigits.isSuperset(of: CharacterSet(charactersIn: myString))

1
清潔で素敵な、最高のソリューション。私はこれが不必要な.invertedアクションや他のアクションをしないことが好きです。
Dannie P

4

明確にするために、これは文字列の整数に対して機能します。

上記のジョンの答えに基づいた小さなヘルパーカテゴリがあります:

.hファイル

@interface NSString (NumberChecking)

+(bool)isNumber:(NSString *)string;

@end

.mファイル

#import "NSString+NumberChecking.h"

@implementation NSString (NumberChecking)

+(bool)isNumber {
    if([self rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]].location == NSNotFound) {
        return YES;
    }else {
        return NO;
    }
}

@end

使用法:

#import "NSString+NumberChecking.h"

if([someString isNumber]) {
    NSLog(@"is a number");
}else {
    NSLog(@"not a number");
}

4

Swift 3ソリューションは次のようになります。

extension String {

    var doubleValue:Double? {
        return NumberFormatter().number(from:self)?.doubleValue
    }

    var integerValue:Int? {
        return NumberFormatter().number(from:self)?.intValue
    }

    var isNumber:Bool {
        get {
            let badCharacters = NSCharacterSet.decimalDigits.inverted
            return (self.rangeOfCharacter(from: badCharacters) == nil)
        }
    }
}

2

John Calsbeekの答えはほぼ正しいですが、一部のUnicodeエッジケースが省略されています。

ドキュメントによるとdecimalDigitCharacterSet、そのセットには、Unicodeによってとして分類されたすべての文字が含まれていNdます。したがって、彼らの答えは、とりわけ以下を受け入れます:

  • (U + 0967 DEVANAGARI DIGIT ONE)
  • (U + 1811 MONGOLIAN DIGIT ONE)
  • 𝟙 (U + 1D7D9数学ダブルストラク桁1)

ある意味これは正しいですが、の各文字はNd10進数字にマップされますが、ほとんどの場合、質問者が期待したものではありません。これを書いている時点では、610のコードポイントがとして分類されておりNd、そのうちの10文字のみが0(U + 0030)から9(U + 0039)までの予想文字です。

この問題を修正するには、受け入れ可能な文字を正確に指定するだけです。

NSCharacterSet* notDigits = 
    [[NSCharacterSet characterSetWithCharactersInString:@"0123456789"] invertedSet];
if ([newString rangeOfCharacterFromSet:notDigits].location == NSNotFound)
{
    // newString consists only of the digits 0 through 9
}

1

さらに別のオプション:

- (BOOL)isValidNumber:(NSString*)text regex:(NSString*)regex {
    @try {
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
        return [predicate evaluateWithObject:text];
    }
    @catch (NSException *exception) {
        assert(false); 
        return NO;
    }
}

使用例:

BOOL isValid = [self isValidNumber:@"1234" regex:@"^[0-9]+$"];

1

@John Calsbeekの回答の拡張 、および@Jeff@gyratoryサーカスのコメントの明確化。

+ (BOOL)doesContainDigitsOnly:(NSString *)string
{
    NSCharacterSet *nonDigits = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];

    BOOL containsDigitsOnly = [string rangeOfCharacterFromSet:nonDigits].location == NSNotFound;

    return containsDigitsOnly;
}

+ (BOOL)doesContainNonDigitsOnly:(NSString *)string
{
    NSCharacterSet *digits = [NSCharacterSet decimalDigitCharacterSet];

    BOOL containsNonDigitsOnly = [string rangeOfCharacterFromSet:digits].location == NSNotFound;

    return containsNonDigitsOnly;
}

以下をカテゴリーメソッドとして追加できます NSString

- (BOOL)doesContainDigitsOnly
{
    NSCharacterSet *nonDigits = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];

    BOOL containsDigitsOnly = [self rangeOfCharacterFromSet:nonDigits].location == NSNotFound;

    return containsDigitsOnly;
}

- (BOOL)doesContainNonDigitsOnly
{
    NSCharacterSet *digits = [NSCharacterSet decimalDigitCharacterSet];

    BOOL containsNonDigitsOnly = [self rangeOfCharacterFromSet:digits].location == NSNotFound;

    return containsNonDigitsOnly;
}

0

文字列が数値かどうかをテストします

int i = [@"12.3" rangeOfCharacterFromSet: [ [NSCharacterSet characterSetWithCharactersInString:@"0123456789."] invertedSet] ].location;

if (i == NSNotFound) {
     //is a number
}

0

スウィフト拡張:

extension NSString {
func isNumString() -> Bool {
    let numbers = NSCharacterSet(charactersInString: "0123456789.").invertedSet
    let range = self.rangeOfCharacterFromSet(numbers).location
    if range == NSNotFound {
        return true
    }
    return false
}  }

0

Swift 3の場合

var onlyDigits: CharacterSet = CharacterSet.decimalDigits.inverted
if testString.rangeOfCharacter(from: onlyDigits) == nil {
  // String only consist digits 0-9
}

0

あなたがからある数字がある場合混合言語、その使用(またはしないでください)0-9桁形式を、あなたは、任意の数を探します正規表現を実行する必要があります、次のことはするすべての桁を変換することです0- 9形式(実際の値が必要な場合):

// Will look for any language digits
let regex = try NSRegularExpression(pattern: "[^[:digit:]]", options: .caseInsensitive)
let digitsString = regex.stringByReplacingMatches(in: string,
                                                         options: NSRegularExpression.MatchingOptions(rawValue: 0),
                                                         range: NSMakeRange(0, string.count), withTemplate: "")
// Converting the digits to be 0-9 format
let numberFormatter = NumberFormatter()
numberFormatter.locale = Locale(identifier: "EN")
let finalValue = numberFormatter.number(from: digitsString)

if let finalValue = finalValue {
  let actualValue = finalValue.doubleValue
}

0

最も簡単で信頼性の高い方法はDouble、結果がnil- としてキャストしようとすることです。これを正当な数に形成することはできません。

let strings = ["test", "123", "123.2", "-123", "123-3", "123..22", ".02"]
let validNumbers = strings.compactMap(Double.init)

print(validNumbers)
// prints [123.0, 123.2, -123.0, 0.02]

ドキュメントの詳細:https : //developer.apple.com/documentation/swift/double/2926277-init


0

Simpleは文字列拡張を書きました:

extension String {
    var isNumeric: Bool {
        return self.rangeOfCharacter(from: CharacterSet.decimalDigits.inverted) == nil
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.