Câu trả lời:
Đây là một cách không dựa vào độ chính xác hạn chế khi cố gắng phân tích cú pháp chuỗi thành một số:
NSCharacterSet* notDigits = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
if ([newString rangeOfCharacterFromSet:notDigits].location == NSNotFound)
{
// newString consists only of the digits 0 through 9
}
Xem +[NSCharacterSet decimalDigitCharacterSet]
và -[NSString rangeOfCharacterFromSet:]
.
[[NSCharacterSet characterSetWithCharactersInString:@"0123456789."] invertedSet]]
invertedSet
đang trả về một lớp bao bọc tập hợp mà nó đã được tạo biểu mẫu và trả về giá trị ngược lại cho tất cả các truy vấn. Nhưng tôi không biết chắc chắn.
Tôi khuyên bạn nên sử dụng numberFromString:
phương thức từ lớp NSNumberFormatter , như thể số không hợp lệ, nó sẽ trả về nil; nếu không, nó sẽ trả về cho bạn một Số NSN.
NSNumberFormatter *nf = [[[NSNumberFormatter alloc] init] autorelease];
BOOL isDecimal = [nf numberFromString:newString] != nil;
NO
cho chuỗi của bạn. Cũng đáng biết: chúng cũng trả về YES
cho các số được đệm bằng khoảng trắng. Btw, tôi vừa thêm một số đoạn mã thực tế vào câu trả lời của bạn, hy vọng bạn không phiền.
Xác thực bằng biểu thức chính quy, theo mẫu "^[0-9]+$"
, với phương pháp sau -validateString:withPattern:
.
[self validateString:"12345" withPattern:"^[0-9]+$"];
"^[0-9]+(.{1}[0-9]+)?$"
"."
.
"^[0-9]{4}$"
."."
và độ dài từ 2 ~ 5.
"^[0-9]{2,5}$"
."^-?\d+$"
Biểu thức chính quy có thể được kiểm tra trong trang web trực tuyến .
Chức năng trợ giúp như sau.
// 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;
}
Thử nghiệm trong sân chơi.
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 }
Và tôi đã nhận lỗiPlayground execution aborted: error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
return matchRange.location != NSNotFound;
^-?\d+$
, tôi đã xác minh nó trên trang web: regex101.com
Bạn có thể tạo một NSScanner và chỉ cần quét chuỗi:
NSDecimal decimalValue;
NSScanner *sc = [NSScanner scannerWithString:newString];
[sc scanDecimal:&decimalValue];
BOOL isDecimal = [sc isAtEnd];
Xem tài liệu của NSScanner để biết thêm các phương pháp để lựa chọn.
isAtEnd
.
Tôi nghĩ cách dễ nhất để kiểm tra xem mọi ký tự trong một chuỗi nhất định là số có lẽ là:
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");
}
Sử dụng một trong các phương pháp gốc NSCharacterSet khác nếu bạn muốn kiểm soát hoàn toàn các ký tự được chấp nhận.
Câu hỏi ban đầu này là về Objective-C, nhưng nó cũng đã được đăng nhiều năm trước khi Swift được công bố. Vì vậy, nếu bạn đến đây từ Google và đang tìm kiếm một giải pháp sử dụng Swift, thì đây là cách:
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.")
}
Giải pháp Swift 3 nếu cần xác minh rằng chuỗi chỉ có các chữ số:
CharacterSet.decimalDigits.isSuperset(of: CharacterSet(charactersIn: myString))
.inverted
và các hành động khác.
để rõ ràng, chức năng này đối với các số nguyên trong chuỗi.
có một danh mục trợ giúp nhỏ dựa trên câu trả lời của John ở trên:
trong tệp .h
@interface NSString (NumberChecking)
+(bool)isNumber:(NSString *)string;
@end
trong tệp .m
#import "NSString+NumberChecking.h"
@implementation NSString (NumberChecking)
+(bool)isNumber {
if([self rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]].location == NSNotFound) {
return YES;
}else {
return NO;
}
}
@end
sử dụng:
#import "NSString+NumberChecking.h"
if([someString isNumber]) {
NSLog(@"is a number");
}else {
NSLog(@"not a number");
}
Giải pháp Swift 3 có thể giống như:
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)
}
}
}
Câu trả lời của John Calsbeek gần đúng nhưng bỏ qua một số trường hợp cạnh Unicode.
Theo tài liệu chodecimalDigitCharacterSet
, bộ đó bao gồm tất cả các ký tự được phân loại bởi Unicode như Nd
. Vì vậy, câu trả lời của họ sẽ được chấp nhận, trong số những người khác:
१
(U + 0967 DEVANAGARI SỐ MỘT)᠑
(U + 1811 MONGOLIAN DIGIT ONE)𝟙
(SỐ ĐÔI ĐÔI-STRUCK MỘT MÔN TOÁN U + 1D7D9)Mặc dù theo một nghĩa nào đó, điều này đúng - mỗi ký tự trong Nd
ánh xạ tới một chữ số thập phân - nó gần như chắc chắn không phải là những gì người hỏi mong đợi. Tính đến thời điểm viết bài này, có 610 điểm mã được phân loạiNd
, chỉ có mười trong số đó là các ký tự mong đợi 0
(U + 0030) đến9
(U + 0039).
Để khắc phục sự cố, chỉ cần chỉ định chính xác những ký tự có thể chấp nhận được:
NSCharacterSet* notDigits =
[[NSCharacterSet characterSetWithCharactersInString:@"0123456789"] invertedSet];
if ([newString rangeOfCharacterFromSet:notDigits].location == NSNotFound)
{
// newString consists only of the digits 0 through 9
}
Tuy nhiên, một lựa chọn khác:
- (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;
}
}
Ví dụ sử dụng:
BOOL isValid = [self isValidNumber:@"1234" regex:@"^[0-9]+$"];
Một phần mở rộng của @ John Calsbeek 'câu trả lời, và làm rõ @ Jeff và xiếc @gyratory ' s ý kiến.
+ (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;
}
Sau đây có thể được thêm vào làm các phương pháp danh mục cho 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;
}
Kiểm tra xem một chuỗi là một số Có thể hữu ích
int i = [@"12.3" rangeOfCharacterFromSet: [ [NSCharacterSet characterSetWithCharactersInString:@"0123456789."] invertedSet] ].location;
if (i == NSNotFound) {
//is a number
}
Tiện ích mở rộng 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
} }
Đối với Swift 3
var onlyDigits: CharacterSet = CharacterSet.decimalDigits.inverted
if testString.rangeOfCharacter(from: onlyDigits) == nil {
// String only consist digits 0-9
}
Khi bạn có các chữ số từ các ngôn ngữ hỗn hợp , sử dụng (hoặc không) các định dạng chữ số 0-9, bạn sẽ cần chạy một regex sẽ tìm kiếm bất kỳ số nào, điều tiếp theo là chuyển đổi tất cả các chữ số thành 0- 9 định dạng (nếu bạn cần giá trị thực):
// 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
}
Cách dễ nhất và đáng tin cậy nhất là cố gắng truyền Double
, nếu kết quả là nil
- nó không thể được tạo thành một số hợp pháp.
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]
Thông tin thêm trong tài liệu: https://developer.apple.com/documentation/swift/double/2926277-init
.
ký tự