web-dev-qa-db-fra.com

Comment vérifier si NSString contient une valeur numérique?

J'ai une chaîne qui est générée à partir d'une formule, cependant je ne veux utiliser cette chaîne que si tous ses caractères sont numériques, sinon je veux faire quelque chose de différent, par exemple afficher un message d'erreur.

J'ai jeté un coup d'œil mais j'ai du mal à trouver quoi que ce soit qui va dans le sens de ce que je veux faire. J'ai consulté NSScanner, mais je ne sais pas s'il vérifie toute la chaîne, mais je ne sais pas vraiment comment vérifier si ces caractères sont numériques.

- (void)isNumeric:(NSString *)code{

    NSScanner *ns = [NSScanner scannerWithString:code];
    if ( [ns scanFloat:NULL] ) //what can I use instead of NULL?
    {
        NSLog(@"INSIDE IF");
    }
    else {
    NSLog(@"OUTSIDE IF");
    }
}

Ainsi, après quelques heures supplémentaires de recherche, je suis tombé sur une implémentation qui me donne exactement ce que je recherche.

donc, si vous cherchez à vérifier s'il y a des caractères alphanumériques dans votre NSString cela fonctionne ici

-(bool) isNumeric:(NSString*) hexText
{

    NSNumberFormatter* numberFormatter = [[[NSNumberFormatter alloc] init] autorelease];

    NSNumber* number = [numberFormatter numberFromString:hexText];

    if (number != nil) {
        NSLog(@"%@ is numeric", hexText);
        //do some stuff here      
        return true;
    }

    NSLog(@"%@ is not numeric", hexText);
    //or do some more stuff here
    return false;
}

j'espère que cela t'aides. 

29
C.Johns

Quelque chose comme ça marcherait:

@interface NSString (usefull_stuff)
- (BOOL) isAllDigits;
@end

@implementation NSString (usefull_stuff)

- (BOOL) isAllDigits
{
    NSCharacterSet* nonNumbers = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
    NSRange r = [self rangeOfCharacterFromSet: nonNumbers];
    return r.location == NSNotFound && self.length > 0;
}

@end

puis utilisez-le simplement comme ceci:

NSString* hasOtherStuff = @"234 other stuff";
NSString* digitsOnly = @"123345999996665003030303030";

BOOL b1 = [hasOtherStuff isAllDigits];
BOOL b2 = [digitsOnly isAllDigits];

Vous n'avez pas à envelopper la fonctionnalité dans une extension de catégorie privée comme celle-ci, mais cela facilite la réutilisation.

J'aime cette solution mieux que les autres car elle ne débordera jamais de certains fichiers int/float analysés via NSScanner - le nombre de chiffres peut être pratiquement de n'importe quelle longueur. 

50
TomSwift

Considérez NSString integerValue - il retourne une NSInteger. Cependant, il acceptera certaines chaînes qui ne sont pas entièrement numériques et ne fournit pas de mécanisme pour déterminer des chaînes qui ne le sont pas du tout. Cela peut ou peut ne pas être acceptable.

Par exemple, " 13 " -> 13, "42foo" -> 42 et "helloworld" -> 0.

Bonne codage.


Maintenant, puisque ce qui précède était en quelque sorte une tangente à la question, voir déterminer si string est numérique . Code extrait du lien, avec commentaires ajoutés:

BOOL isNumeric(NSString *s)
{
   NSScanner *sc = [NSScanner scannerWithString: s];
   // We can pass NULL because we don't actually need the value to test
   // for if the string is numeric. This is allowable.
   if ( [sc scanFloat:NULL] )
   {
      // Ensure nothing left in scanner so that "42foo" is not accepted.
      // ("42" would be consumed by scanFloat above leaving "foo".)
      return [sc isAtEnd];
   }
   // Couldn't even scan a float :(
   return NO;
}

Ce qui précède fonctionne avec juste scanFloat - par exemple. non scanInt - car la plage d'un float est beaucoup plus grande que celle d'un entier (même un entier de 64 bits).

Cette fonction vérifie "totalement numérique" et acceptera "42" et "0.13E2" mais rejettera " 13 ", "42foo" et "helloworld".

15
user166390

Comme ça:

- (void)isNumeric:(NSString *)code{

    NSScanner *ns = [NSScanner scannerWithString:code];
    float the_value;
    if ( [ns scanFloat:&the_value] )
    {
        NSLog(@"INSIDE IF");
        // do something with `the_value` if you like
    }
    else {
    NSLog(@"OUTSIDE IF");
    }
}
8
Matt Connolly

C'est très simple.

+ (BOOL)isStringNumeric:(NSString *)text
{
    NSCharacterSet *alphaNums = [NSCharacterSet decimalDigitCharacterSet];
    NSCharacterSet *inStringSet = [NSCharacterSet characterSetWithCharactersInString:text];        
    return [alphaNums isSupersetOfSet:inStringSet];
}
7
arturdev

Face au même problème dans Swift. 
Dans Swift, vous devez utiliser ce code, selon la réponse de TomSwift:

func isAllDigits(str: String) -> Bool {

    let nonNumbers = NSCharacterSet.decimalDigitCharacterSet()

    if let range = str.rangeOfCharacterFromSet(nonNumbers) {
        return true
    }
    else {
        return false
    }
}

P.S. Vous pouvez également utiliser d'autres NSCharacterSets ou leurs combinaisons pour vérifier votre chaîne!

2

Pour les nombres simples tels que "12234" ou "231231.23123", la réponse peut être simple.

Il existe une loi de transformation pour les nombres int: quand une chaîne avec un entier se transforme en nombre entier (ou long) puis, à nouveau, la reconvertit en une autre chaîne, ces chaînes seront égales.

En Objective C, cela ressemblera à:

NSString *numStr=@"1234",*num2Str=nil;
num2Str=[NSString stringWithFormat:@"%lld",numStr.longlongValue];

if([numStr isEqualToString: num2Str]) NSLog(@"numStr is an integer number!");

En utilisant cette loi de transformation, nous pouvons créer une solution
pour détecter les numéros double ou long:

NSString *numStr=@"12134.343"
NSArray *numList=[numStr componentsSeparatedByString:@"."];

if([[NSString stringWithFormat:@"%lld", numStr.longLongValue] isEqualToString:numStr]) NSLog(@"numStr is an integer number"); 
else 
if( numList.count==2 &&
               [[NSString stringWithFormat:@"%lld",((NSString*)numList[0]).longLongValue] isEqualToString:(NSString*)numList[0]] &&
               [[NSString stringWithFormat:@"%lld",((NSString*)numList[1]).longLongValue] isEqualToString:(NSString*)numList[1]] )
            NSLog(@"numStr is a double number");
else 
NSLog(@"numStr is not a number");

Je n'ai pas copié le code ci-dessus à partir de mon code de travail, il peut donc y avoir des erreurs, mais je pense que le problème principal est clair… .. Bien sûr, cette solution ne fonctionne pas avec des chiffres comme «1E100» prendre en compte la taille de la partie entière et fractionnaire. En utilisant la loi décrite ci-dessus, vous pouvez effectuer la détection de numéro dont vous avez besoin.

0
sinoptic

La réponse de C.Johns est fausse. Si vous utilisez un formateur, vous risquez que Apple modifie sa base de code à un moment donné et que le formateur crache un résultat partiel. La réponse de Tom est également fausse. Si vous utilisez la méthode rangeOfCharacterFromSet et recherchez NSNotFound, il enregistrera une valeur true si la chaîne contient même un nombre. De même, d'autres réponses de ce fil de discussion suggèrent d'utiliser la méthode de la valeur entière. Cela est également faux car cela enregistrera un vrai si un seul entier est présent dans la chaîne. Le PO a demandé une réponse qui assure que la chaîne entière est numérique. Essaye ça:

NSCharacterSet *searchSet = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];

Tom avait raison à propos de cette partie. Cette étape vous donne les caractères de chaîne non numériques. Mais alors nous faisons ceci:

NSString *trimmedString = [string stringByTrimmingCharactersInSet:searchSet];

return (string.length == trimmedString.length);

Le jeu de caractères inversé de Tom peut TRIMER une chaîne. Nous pouvons donc utiliser cette méthode pour tester l'existence de nombres non numériques dans la chaîne en comparant leurs longueurs.

0
Scott Yelvington