Réponses:
Voici une façon qui ne repose pas sur la précision limitée de la tentative d'analyse de la chaîne en tant que nombre:
NSCharacterSet* notDigits = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
if ([newString rangeOfCharacterFromSet:notDigits].location == NSNotFound)
{
// newString consists only of the digits 0 through 9
}
Voir +[NSCharacterSet decimalDigitCharacterSet]
et -[NSString rangeOfCharacterFromSet:]
.
[[NSCharacterSet characterSetWithCharactersInString:@"0123456789."] invertedSet]]
invertedSet
renvoie une classe qui enveloppe l'ensemble sous sa forme créée et renvoie la valeur opposée pour toutes les requêtes. Mais je ne sais pas avec certitude.
Je suggère d'utiliser la numberFromString:
méthode de la classe NSNumberFormatter , comme si le nombre n'est pas valide, il renverra nil; sinon, il vous renverra un NSNumber.
NSNumberFormatter *nf = [[[NSNumberFormatter alloc] init] autorelease];
BOOL isDecimal = [nf numberFromString:newString] != nil;
NO
votre chaîne. A savoir également: ils reviennent également YES
pour des nombres remplis d'espaces. Btw, je viens d'ajouter un extrait de code à votre réponse, j'espère que cela ne vous dérange pas.
Validez par expression régulière, par modèle "^[0-9]+$"
, avec la méthode suivante -validateString:withPattern:
.
[self validateString:"12345" withPattern:"^[0-9]+$"];
"^[0-9]+(.{1}[0-9]+)?$"
"."
.
"^[0-9]{4}$"
."."
et que la longueur est comprise entre 2 et 5.
"^[0-9]{2,5}$"
."^-?\d+$"
L'expression régulière peut être vérifiée sur le site Web en ligne .
La fonction d'assistance est la suivante.
// 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;
}
Test dans la cour de récréation.
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)
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 }
Et j'ai eu une erreurPlayground execution aborted: error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
return matchRange.location != NSNotFound;
^-?\d+$
, je l'ai vérifié sur le site: regex101.com
Vous pouvez créer un NSScanner et scanner simplement la chaîne:
NSDecimal decimalValue;
NSScanner *sc = [NSScanner scannerWithString:newString];
[sc scanDecimal:&decimalValue];
BOOL isDecimal = [sc isAtEnd];
Consultez la documentation de NSScanner pour plus de méthodes à choisir.
isAtEnd
.
Je pense que le moyen le plus simple de vérifier que chaque caractère dans une chaîne donnée est numérique est probablement:
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");
}
Utilisez l'une des autres méthodes de fabrique NSCharacterSet si vous voulez un contrôle complet sur les caractères acceptables.
Cette question originale concernait Objective-C, mais elle a également été publiée des années avant l'annonce de Swift. Donc, si vous venez ici de Google et que vous recherchez une solution qui utilise Swift, vous y allez:
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.")
}
Solution Swift 3 si besoin de vérifier que la chaîne ne comporte que des chiffres:
CharacterSet.decimalDigits.isSuperset(of: CharacterSet(charactersIn: myString))
.inverted
d'actions inutiles et autres.
pour être clair, cela fonctionne pour les entiers dans les chaînes.
Voici une petite catégorie d'aide basée sur la réponse de John ci-dessus:
dans un fichier .h
@interface NSString (NumberChecking)
+(bool)isNumber:(NSString *)string;
@end
dans un fichier .m
#import "NSString+NumberChecking.h"
@implementation NSString (NumberChecking)
+(bool)isNumber {
if([self rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]].location == NSNotFound) {
return YES;
}else {
return NO;
}
}
@end
usage:
#import "NSString+NumberChecking.h"
if([someString isNumber]) {
NSLog(@"is a number");
}else {
NSLog(@"not a number");
}
La solution Swift 3 pourrait être comme:
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)
}
}
}
La réponse de John Calsbeek est presque correcte mais omet certains cas de bord Unicode.
Selon la documentation dedecimalDigitCharacterSet
, cet ensemble comprend tous les caractères classés par Unicode comme Nd
. Ainsi leur réponse acceptera, entre autres:
१
(U + 0967 DEVANAGARI DIGIT ONE)᠑
(U + 1811 CHIFFRE MONGOLIEN UN)𝟙
(U + 1D7D9 CHIFFRE MATHÉMATIQUE À DOUBLE EFFET UN)Bien que dans un certain sens, cela soit correct - chaque caractère dans Nd
correspond à un chiffre décimal - ce n'est certainement pas ce à quoi le demandeur s'attendait. Au moment de la rédaction de cet article, il existe 610 points de code classés commeNd
, dont seulement dix sont les caractères attendus 0
(U + 0030) à 9
(U + 0039).
Pour résoudre le problème, spécifiez simplement exactement les caractères acceptables:
NSCharacterSet* notDigits =
[[NSCharacterSet characterSetWithCharactersInString:@"0123456789"] invertedSet];
if ([newString rangeOfCharacterFromSet:notDigits].location == NSNotFound)
{
// newString consists only of the digits 0 through 9
}
Encore une autre option:
- (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;
}
}
Exemple d'utilisation:
BOOL isValid = [self isValidNumber:@"1234" regex:@"^[0-9]+$"];
Une extension de la réponse de @John Calsbeek , et une clarification des commentaires de @Jeff et @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;
}
Les éléments suivants peuvent être ajoutés comme méthodes de catégorie pour 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;
}
Tester si une chaîne est un nombre peut être utile
int i = [@"12.3" rangeOfCharacterFromSet: [ [NSCharacterSet characterSetWithCharactersInString:@"0123456789."] invertedSet] ].location;
if (i == NSNotFound) {
//is a number
}
Extension Swift:
extension NSString {
func isNumString() -> Bool {
let numbers = NSCharacterSet(charactersInString: "0123456789.").invertedSet
let range = self.rangeOfCharacterFromSet(numbers).location
if range == NSNotFound {
return true
}
return false
} }
Pour Swift 3
var onlyDigits: CharacterSet = CharacterSet.decimalDigits.inverted
if testString.rangeOfCharacter(from: onlyDigits) == nil {
// String only consist digits 0-9
}
Lorsque vous avez des chiffres issus de langues mixtes , qui utilisent (ou non) les formats de chiffres 0-9, vous devrez exécuter une expression régulière qui recherchera n'importe quel nombre, la prochaine chose à faire est de convertir tous les chiffres en 0- 9 format (si vous avez besoin de la valeur réelle):
// 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
}
Le moyen le plus simple et le plus fiable est d'essayer de lancer comme Double
, si le résultat est nil
- il ne peut pas être formé en un nombre légitime.
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]
Plus d'informations dans la documentation: https://developer.apple.com/documentation/swift/double/2926277-init
.
caractère