문자열이 숫자인지 아닌지 알아 내기


93

문자열이 숫자로만 구성되어 있는지 어떻게 확인할 수 있습니까? 문자열에서 부분 문자열을 꺼내 숫자 부분 문자열인지 확인하고 싶습니다.

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

답변:


241

다음은 문자열을 숫자로 구문 분석하려는 제한된 정밀도에 의존하지 않는 한 가지 방법입니다.

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 2015-09-29

2
@Supertecnoboff IOS에서 변경된 것 같습니다. 이를 확인하기 위해 대신 사용할 수 있습니다 :[[NSCharacterSet characterSetWithCharactersInString:@"0123456789."] invertedSet]]
— 니콜라스 타일러

2
@KMGorbunov NSCharacterSet이 실제로 세트의 모든 단일 문자를 포함하는 백업 세트를 저장한다고 생각하지 않습니다. 나는 invertedSet그것이 생성 된 양식을 래핑하고 모든 쿼리에 대해 반대 값을 반환하는 클래스를 반환한다고 생각 합니다. 그러나 나는 확실하지 않다.
— John Calsbeek

33

NSNumberFormatter 클래스 의 numberFromString:메서드를 사용하는 것이 좋습니다. 마치 숫자가 유효하지 않으면 nil을 반환합니다. 그렇지 않으면 NSNumber를 반환합니다.

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

@ "124sbd"와 같은 유효한 번호를 반환하지 않을까요?
— Tommy

아니요, NSNumberFormatter와 NSScanner는 모두 NO문자열을 반환 합니다. 또한 알아 두어야 할 사항 : YES공백으로 채워진 숫자에 대해서도 반환 합니다. Btw, 방금 귀하의 답변에 실제 코드 스 니펫을 추가했습니다.
— Regexident

NSScanner는 "유효한 정수 표현"을 찾은 문서에 따라 해당 문자열에 대해 'YES'를 반환해야합니다. 또한 iOS 4.3.2의 테스트에서 정확히 수행했습니다. 그러나 NSNumberFormatter는 nil을 반환했습니다.
— Tommy

이것은 '.'를 잡지 않습니다. 그것은 나에게 요구 사항입니다. @John Calsbeek의 답변이 훌륭하게 작동했습니다.
— Damian

수백 자의 모든 숫자가 포함 된 문자열은 어떻게됩니까? 생성 된 NSNumber에 제한이 있습니까?
— Biniou

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+$"

정규식을 체크인 할 수 있습니다. 은 온라인 웹 사이트 .

도우미 기능은 다음과 같습니다.

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

나는 스위프트 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).
— 마티 Arasan

나는 신속한 3에 대한 올바른 것을 모른다. 내가 틀렸다면 나를 고쳐라.
— Mathi Arasan 2017-08-04

방법에 대해 단지return matchRange.location != NSNotFound;
— LimeRed

마이너스 기호는 어떻습니까?
— Thomas

@Thomas With ^-?\d+$, 사이트에서 확인했습니다. regex101.com
— AechoLiu

9

NSScanner를 만들고 단순히 문자열을 스캔 할 수 있습니다.

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

선택할 수있는 더 많은 방법은 NSScanner의 문서 를 확인하십시오 .


적어도 첫 번째 문자가 숫자인지 여부 만 알려주지 않습니까?
— Tommy

내 잘못이야. 에 대한 최종 전화를 잊었습니다 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

나는 stringByTrimmingCharactersInSet 만 시작 트림과 문자열의 끝 있다고 생각
— 브로디 로버트슨

@BrodyRobertson : 그렇습니다. 이 답변에 대해 조금도 중요하지 않습니다. 이 테스트가 실패 할 것이라고 생각하는 예는 무엇입니까?
— Tommy

@Tommy, 나는 당신의 대답을 이해하고이 유효하고 upvote에 있지만됩니다 재평가 후 당신이 날 revote 할 수 있도록 편집 할 필요
— 브로디 로버트슨

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

명확하게 말하자면, 이것은 문자열의 정수에 대해 작동합니다.

위의 John의 대답을 기반으로 한 작은 도우미 범주가 있습니다.

.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의 대답 은 거의 정확하지만 일부 유니 코드 가장자리 사례를 생략합니다.

에 대한 설명서에decimalDigitCharacterSet 따라 해당 세트에는 유니 코드로 분류 된 모든 문자가 Nd. 따라서 그들의 대답은 다음을 받아 들일 것입니다.

  • १ (U + 0967 DEVANAGARI DIGIT ONE)
  • ᠑ (U + 1811 MONGOLIAN DIGIT ONE)
  • 𝟙 (U + 1D7D9 수학 이중 구조 DIGIT ONE)

어떤 의미에서 이것은 옳지 만-의 각 문자 Nd는 십진수로 매핑됩니다-거의 확실하게 질문자가 예상 한 것과는 다릅니다. 이 글을 쓰는 현재 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

의 확장 @ 존 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

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
}  }

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.