Jak możemy sprawdzić, czy ciąg składa się tylko z liczb. Pobieram podciąg z ciągu i chcę sprawdzić, czy jest to podciąg numeryczny, czy nie.
NSString *newString = [myString substringWithRange:NSMakeRange(2,3)];
iphone
objective-c
cocoa-touch
ios
nsstring
Abhinav
źródło
źródło
.
znaku[[NSCharacterSet characterSetWithCharactersInString:@"0123456789."] invertedSet]]
invertedSet
zwraca klasę, która zawija zestaw, w którym została utworzona, i zwraca przeciwną wartość dla wszystkich zapytań. Ale nie wiem na pewno.Sugerowałbym użycie
numberFromString:
metody z klasy NSNumberFormatter , tak jakby numer był niepoprawny, zwróci nil; w przeciwnym razie zwróci Ci NSNumber.NSNumberFormatter *nf = [[[NSNumberFormatter alloc] init] autorelease]; BOOL isDecimal = [nf numberFromString:newString] != nil;
źródło
NO
Twój ciąg. Warto również wiedzieć: powracają równieżYES
po liczbach wypełnionych spacjami. Przy okazji, właśnie dodałem fragment kodu do Twojej odpowiedzi, mam nadzieję, że nie masz nic przeciwko.Sprawdź poprawność za pomocą wyrażenia regularnego, według wzorca
"^[0-9]+$"
, przy użyciu następującej metody-validateString:withPattern:
.[self validateString:"12345" withPattern:"^[0-9]+$"];
"^[0-9]+(.{1}[0-9]+)?$"
"."
."^[0-9]{4}$"
."."
, a długość wynosi od 2 do 5."^[0-9]{2,5}$"
."^-?\d+$"
Wyrażenie regularne można sprawdzić w witrynie internetowej online .
Funkcja pomocnicza jest następująca.
// 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; }
Wersja Swift 3:
Przetestuj na placu zabaw.
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)
źródło
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 }
I otrzymałem błądPlayground execution aborted: error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
return matchRange.location != NSNotFound;
^-?\d+$
, zweryfikowałem to na stronie: regex101.comMożesz utworzyć NSScanner i po prostu zeskanować ciąg:
NSDecimal decimalValue; NSScanner *sc = [NSScanner scannerWithString:newString]; [sc scanDecimal:&decimalValue]; BOOL isDecimal = [sc isAtEnd];
Sprawdź dokumentację NSScanner, aby uzyskać więcej metod do wyboru.
źródło
isAtEnd
.Myślę, że najłatwiejszym sposobem sprawdzenia, czy każdy znak w danym ciągu jest numeryczny, jest prawdopodobnie:
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"); }
Użyj jednej z innych metod fabryki NSCharacterSet, jeśli chcesz mieć pełną kontrolę nad dopuszczalnymi znakami.
źródło
To pierwotne pytanie dotyczyło Objective-C, ale zostało również opublikowane wiele lat przed ogłoszeniem Swift. Jeśli więc przyjeżdżasz tutaj z Google i szukasz rozwiązania wykorzystującego Swift, proszę bardzo:
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.") }
źródło
Rozwiązanie Swift 3, jeśli chcesz sprawdzić, czy ciąg ma tylko cyfry:
źródło
.inverted
i innych działań.aby było jasne, to działa dla liczb całkowitych w łańcuchach.
Oto mała kategoria pomocnicza oparta na odpowiedzi Johna powyżej:
w pliku h
@interface NSString (NumberChecking) +(bool)isNumber:(NSString *)string; @end
w pliku m
#import "NSString+NumberChecking.h" @implementation NSString (NumberChecking) +(bool)isNumber { if([self rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]].location == NSNotFound) { return YES; }else { return NO; } } @end
stosowanie:
#import "NSString+NumberChecking.h" if([someString isNumber]) { NSLog(@"is a number"); }else { NSLog(@"not a number"); }
źródło
Rozwiązanie Swift 3 mogłoby wyglądać następująco:
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) } } }
źródło
Rozszerzenie odpowiedzi @John Calsbeek i wyjaśnienie komentarzy @Jeff i @gyratory circus .
+ (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; }
Poniższe można dodać jako metody kategorii dla
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; }
źródło
Odpowiedź Johna Calsbeeka jest prawie poprawna, ale pomija niektóre przypadki Unicode.
Zgodnie z dokumentacją
decimalDigitCharacterSet
, ten zestaw zawiera wszystkie znaki sklasyfikowane przez Unicode jakoNd
. W ten sposób ich odpowiedź przyjmie m.in .:१
(U + 0967 DEVANAGARI DIGIT ONE)᠑
(U + 1811 MONGOLIAN DIGIT ONE)𝟙
(U + 1D7D9 MATEMATYCZNA PODWÓJNA CYFROWA CYFRA)Chociaż w pewnym sensie jest to poprawne - każdy znak
Nd
odwzorowuje cyfrę dziesiętną - prawie na pewno nie jest to to, czego oczekiwał pytający. W chwili pisania tego tekstu istnieje 610 punktów kodowych sklasyfikowanych jakoNd
, z których tylko dziesięć to oczekiwane znaki0
(od U + 0030) do9
(U + 0039).Aby rozwiązać problem, po prostu określ dokładnie te znaki, które są dopuszczalne:
NSCharacterSet* notDigits = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789"] invertedSet]; if ([newString rangeOfCharacterFromSet:notDigits].location == NSNotFound) { // newString consists only of the digits 0 through 9 }
źródło
Jeszcze inna opcja:
- (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; } }
Przykład użycia:
BOOL isValid = [self isValidNumber:@"1234" regex:@"^[0-9]+$"];
źródło
Sprawdź, czy ciąg jest liczbą. Może być pomocny
int i = [@"12.3" rangeOfCharacterFromSet: [ [NSCharacterSet characterSetWithCharactersInString:@"0123456789."] invertedSet] ].location; if (i == NSNotFound) { //is a number }
źródło
Szybkie rozszerzenie:
extension NSString { func isNumString() -> Bool { let numbers = NSCharacterSet(charactersInString: "0123456789.").invertedSet let range = self.rangeOfCharacterFromSet(numbers).location if range == NSNotFound { return true } return false } }
źródło
Dla Swift 3
var onlyDigits: CharacterSet = CharacterSet.decimalDigits.inverted if testString.rangeOfCharacter(from: onlyDigits) == nil { // String only consist digits 0-9 }
źródło
Jeśli masz cyfry z języków mieszanych , które używają (lub nie) formatów cyfr 0-9, będziesz musiał uruchomić wyrażenie regularne, które będzie szukało dowolnej liczby, a następnie przekonwertuj wszystkie cyfry na 0- 9 format (jeśli potrzebujesz rzeczywistej wartości):
// 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 }
źródło
Najłatwiejszym i najbardziej niezawodnym sposobem jest próba rzucenia, ponieważ
Double
jeśli wynik jestnil
- nie można go uformować w legalną liczbę.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]
Więcej informacji w dokumentacji: https://developer.apple.com/documentation/swift/double/2926277-init
źródło
Simple napisał rozszerzenie ciągu:
extension String { var isNumeric: Bool { return self.rangeOfCharacter(from: CharacterSet.decimalDigits.inverted) == nil } }
źródło