it-swarm.com.ru

Выяснить, является ли строка числовой или нет

Как мы можем проверить, состоит ли строка только из чисел. Я вынимаю подстроку из строки и хочу проверить, является ли она числовой подстрокой или нет.

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

Вот один из способов, который не основан на ограниченной точности попыток разобрать строку как число:

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

Смотрите +[NSCharacterSet decimalDigitCharacterSet] и -[NSString rangeOfCharacterFromSet:] .

229
John Calsbeek

Я бы предложил использовать метод numberFromString: из класса NSNumberFormatter , так как если число недопустимо, он вернет nil; в противном случае он вернет вам NSNumber.

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

Проверяется регулярным выражением, шаблоном "^[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}$".

Регулярное выражение можно проверить в на веб-сайте онлайн .

Вспомогательная функция заключается в следующем.

// 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)
10
AechoLiu

Вы можете создать NSScanner и просто отсканировать строку:

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

Посмотрите документацию NSScanner чтобы узнать больше методов.

8
Regexident

Я думаю, что самый простой способ проверить, что каждый символ в данной строке является числовым, это:

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, если вы хотите полностью контролировать допустимые символы.

6
Tommy

Этот оригинальный вопрос был о 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.")
}
5
TwoStraws

чтобы быть понятным, это функции для целых чисел в строках.

вот небольшая категория помощников, основанная на ответе Джона выше:

в .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
MrTristan

Решение 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)
        }
    }
}
4
hhamm

Решение Swift 3, если необходимо убедиться, что строка содержит только цифры:

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

ответ Джона Калсбека почти верен, но пропускает некоторые случаи Unicode Edge. 

Согласно документации для decimalDigitCharacterSet , этот набор включает в себя все символы, классифицированные Unicode как Nd. Таким образом, их ответ примет, среди прочего:

  • (U + 0967 DEVANAGARI DIGIT ONE)
  • (U + 1811 МОНГОЛЬСКИЙ ЦИФР ОДИН)
  • ???? (U + 1D7D9 МАТЕМАТИЧЕСКИЙ ДВОЙНОЙ ЦИФРОВОЙ ЦИФРОВОЙ ОДИН)

Хотя в некотором смысле это правильно - каждый символ в Nd отображается в десятичную цифру - это почти наверняка не то, что ожидал аскер. На момент написания этой статьи существует 610 кодовых точек, классифицированных как Nd , только десять из которых являются ожидаемыми символами от 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
}
2
ravron

Еще один вариант:

- (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
LuisCien

Если у вас есть цифры из смешанных языков , которые используют (или не используют) форматы 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
OhadM

Для Swift 3

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

Расширение ответа@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
Abdurrahman Mubeen Ali

Самый простой и надежный способ - попытаться привести к 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
Ariel

Быстрое расширение:

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
Bhavesh Patel

Проверьте, является ли строка числом Может быть полезным

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

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