Ruby에서 안전한 정수 구문 분석
저는 있어이요, 게봐해말,▁say라고 하는 요.'123'
로 변환하고 .123
.
당신이 간단히 할 수 있다는 것을 압니다.some_string.to_i
하지만 그것은 변환됩니다.'lolipops'
0
그건 제가 염두에 두고 있는 효과가 아닙니다.나는 내가 뭔가 잘못된 것을 전환하려고 할 때, 멋지고 고통스럽게 그것이 내 얼굴에서 폭발하기를 원합니다.Exception
않으면 ▁a▁▁betweenish다▁otherwise니없습▁i'를 구별할 수 없습니다.0
그리고 숫자가 전혀 아닌 것.
편집: 저는 정규식 속임수 없이 표준적인 방법을 찾고 있었습니다.
Ruby에는 다음과 같은 기능이 내장되어 있습니다.
Integer('1001') # => 1001
Integer('1001 nights')
# ArgumentError: invalid value for Integer: "1001 nights"
Joseph Pecoraro의 답변에서 언급했듯이, 다음과 같이 십진수가 아닌 유효한 문자열을 확인할 수 있습니다.0x
및 육형으로각의 0b
이진수의 경우 0부터 시작하여 8진수로 구문 분석될 잠재적으로 더 까다로운 숫자입니다.
Ruby 1.9.2는 위의 문제를 피할 수 있도록 radix에 대한 선택적인 두 번째 인수를 추가했습니다.
Integer('23') # => 23
Integer('0x23') # => 35
Integer('023') # => 19
Integer('0x23', 10)
# => #<ArgumentError: invalid value for Integer: "0x23">
Integer('023', 10) # => 23
이 방법은 다음과 같습니다.
i.to_i if i.match(/^\d+$/)
또한 현재 승인된 솔루션이 16진수, 8진수 및 2진수 구문 분석에 미치는 영향에 유의하십시오.
>> Integer('0x15')
# => 21
>> Integer('0b10')
# => 2
>> Integer('077')
# => 63
로 하는 루비 에서.0x
또는0X
16진수입니다.0b
또는0B
2진법일 입니다.0
팔분일 의 이것이 할 수 .이 동작이 원하는 동작이 아닌 경우 문자열이 패턴과 일치하는지 먼저 확인하는 다른 솔루션과 조합할 수 있습니다.처럼./\d+/
정규 표현 등
허용된 솔루션의 또 다른 예상치 못한 동작(1.8, 1.9는 정상):
>> Integer(:foobar)
=> 26017
>> Integer(:yikes)
=> 26025
따라서 전달되는 내용이 확실하지 않으면 다음을 추가해야 합니다..to_s
.
마이런의 답변은 마음에 들지만 "나는 더 이상 자바/C#을 사용하지 않기 때문에 다시는 상속을 사용하지 않을 것이다"라는 루비병을 앓고 있습니다.클래스를 여는 것은 위험할 수 있으므로 특히 Ruby의 핵심 라이브러리의 일부일 때는 적게 사용해야 합니다.절대 사용하지 말라는 것은 아니지만, 일반적으로 피하기 쉽고 사용 가능한 더 나은 옵션이 있습니다. 예를 들어,
class IntegerInString < String
def initialize( s )
fail ArgumentError, "The string '#{s}' is not an integer in a string, it's just a string." unless s =~ /^\-?[0-9]+$/
super
end
end
그런 다음 숫자가 될 수 있는 문자열을 사용하고 싶을 때는 무엇을 하고 있는지 명확하고 코어 클래스를 방해하지 않습니다.
n = IntegerInString.new "2"
n.to_i
# => 2
IntegerInString.new "blob"
ArgumentError: The string 'blob' is not an integer in a string, it's just a string.
이진수 확인 등 초기화에 다른 모든 종류의 검사를 추가할 수 있습니다.하지만 가장 중요한 것은 루비는 사람들을 위한 것이고 사람들을 위한 것은 명확함을 의미한다는 것입니다.변수 이름과 클래스 이름을 통해 개체의 이름을 지정하면 상황이 훨씬 명확해집니다.
지난 프로젝트에서 이 문제를 해결해야 했습니다. 구현 방식은 비슷했지만 조금 달랐습니다.
class NotAnIntError < StandardError
end
class String
def is_int?
self =~ /^-?[0-9]+$/
end
def safe_to_i
return self.to_i if is_int?
raise NotAnIntError, "The string '#{self}' is not a valid integer.", caller
end
end
class Integer
def safe_to_i
return self
end
end
class StringExtensions < Test::Unit::TestCase
def test_is_int
assert "98234".is_int?
assert "-2342".is_int?
assert "02342".is_int?
assert !"+342".is_int?
assert !"3-42".is_int?
assert !"342.234".is_int?
assert !"a342".is_int?
assert !"342a".is_int?
end
def test_safe_to_i
assert 234234 == 234234.safe_to_i
assert 237 == "237".safe_to_i
begin
"a word".safe_to_i
fail 'safe_to_i did not raise the expected error.'
rescue NotAnIntError
# this is what we expect..
end
end
end
someString = "asdfasd123"
number = someString.to_i
if someString != number.to_s
puts "oops, this isn't a number"
end
아마도 가장 깨끗한 방법은 아니지만, 효과가 있을 것입니다.
Re: 크리스의 대답
당신의 구현은 "1a" 또는 "b2"와 같은 것들을 끝까지 다룹니다.대신에 이것은 어떻습니까?
def safeParse2(strToParse)
if strToParse =~ /\A\d+\Z/
strToParse.to_i
else
raise Exception
end
end
["100", "1a", "b2", "t"].each do |number|
begin
puts safeParse2(number)
rescue Exception
puts "#{number} is invalid"
end
end
다음 출력은 다음과 같습니다.
100
1a is invalid
b2 is invalid
t is invalid
언급URL : https://stackoverflow.com/questions/49274/safe-integer-parsing-in-ruby
'source' 카테고리의 다른 글
Git가 자동으로 공백과 탭 사이를 전환할 수 있습니까? (0) | 2023.06.20 |
---|---|
왜 git branch --up-stream을 복구하기 위해 호출합니까? (0) | 2023.06.20 |
ASP.NET 웹 API를 사용하여 이미지를 반환하는 권장 방법이 있습니까? (0) | 2023.06.20 |
Gradle 캐시를 지우는 방법은 무엇입니까? (0) | 2023.06.20 |
Spring Boot 화이트라벨 오류 페이지(type=Not Found, status=404) (0) | 2023.06.20 |