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


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.