2014-05-02 218 views
2

我試圖找出用戶是輸入一個字符串還是一個整數。如果我根據用戶輸入的要求輸入固定值,我可以找到它。我無法上課。用戶輸入字符串或整數

這工作:

name = 5 
type = name.class 

這不起作用:

print "Enter the value to findout its class " 
name = gets 
type = name.class 
if type == String 
    puts "this is a string" 
elsif type == Fixnum 
    puts "this is a fixnum" 
else 
    puts "this is unknown type" 
end 
+6

'#gets'總是給你的字符串... BTW –

+0

這是真的。當我輸入gets.to_i時,它總是給出整數。那麼,什麼是方法來獲得輸入? –

+0

這取決於你想要的有效類型... –

回答

2

我想我會問你的問題是如何在用戶有望進入一個字符串?

如果用戶輸入:

10 #=> Fixnum 
1_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000 #=> Bignum 
1.0 #=> Float 
"hello" #=> String 
'hello' #=> String 

然後,你可以這樣做:

def test_input 
    input = gets.chomp 
    puts eval(input).class 
rescue NameError 
    puts "Unknown Input Class" 
end 

這實際上應該與所有定義的對象一起工作,如果你只是想趕上你提到的這四個然後:

def test_input 
    input = gets.chomp 
    klass = eval(input).class 
    raise NameError unless [Fixnum, Bignum, Float, String].include?(klass) 
    puts klass 
rescue NameError 
    puts "Unknown Input Class" 
end 

編輯

爲了避免直接用戶輸入(這是一個漏洞)使用eval,Gumbo建議使用解析器代替。

$ gem install parser 

#!/usr/bin/ruby 
require 'parser/current' 

def test_input 
    input = Parser::CurrentRuby.parse(gets.chomp) 

    puts case input.type 
    when :str then "String" 
    when :float then "Float" 
    when :int 
    eval(input.to_sexp.slice(/\d+/)).class 
    # Yes using eval again to get Fixnum vs Bignum, but this time 
    # we know what the input will be, and that's ok to eval 
    else 
    "Unknown Input Class" 
    end 
end 
+0

'eval'?你在跟我開玩笑嗎? – Gumbo

+0

它的工作原理,不是嗎?問題是什麼? – jphager2

+0

'eval'不僅僅評估文字,還評估*任何Ruby代碼。 – Gumbo

2

你可以稱之爲Kernel#StringKernel#IntegerKernel#Float找到「有效」類,即類可以將輸入轉化成。

def valid_classes(value) 
    classes = [] 
    classes << String(value) rescue nil 
    classes << Integer(value) rescue nil 
    classes << Float(value) rescue nil 
    classes.map(&:class) 
end 

valid_classes("foo")     #=> [String] 
valid_classes("123.456")    #=> [String, Float] 
valid_classes("123")     #=> [String, Fixnum, Float] 
valid_classes("100000000000000000000") #=> [String, Bignum, Float] 

其他符號也可以被識別:

valid_classes("1_000")     #=> [String, Fixnum] 
valid_classes("1e20")     #=> [String, Float] 
valid_classes("0b111")     #=> [String, Fixnum] 

如果您需要更多的控制,使用正則表達式。

這裏有一個簡單的REPL:

loop do 
    print "Enter a value to find out its class: " 
    input = gets.chomp 
    puts "'#{input}' could be a: #{valid_classes(input).join(', ')}" 
end 
+0

大量使用'Kernel#Integer';我在你的答案中重用了你的東西=)+1 – Abdo

+0

嗨Stefan,我剛剛在15天前開始學習Ruby。我已經學過方法和類。但是我仍然沒有足夠的經驗來正確地輸入你的答案到我的代碼中。你可以幫我嗎 ?這將是假的證據。 –

+0

@lenso_here更新了我的答案,希望這有助於 – Stefan

1

由於@ArupRakshit在他的評論中提及上面,gets總是讓你一個String

你想要做的是獲取用戶的輸入並確定它是什麼。

例如,"1"String,但是1Fixnum

[2] pry(main)> "1".class 
=> String 
[3] pry(main)> 1.class 
=> Fixnum 

在您的評論上面,你提到gets.to_i給你一個整數。這有一個問題。 String#to_i返回0對於不是數字的字符串:

[6] pry(main)> gets.to_i 
hello 
=> 0 

[7] pry(main)> "hello".to_i 
=> 0 

所以基本上你得到一個String,將確定其可能的類(ES)。

# add more Kernel methods here 
POSSIBLE_CLASSES = [Integer, Float, Bignum, String] 

str = gets.chomp # chomp gets rid of the \n that gets appended 
       # to your String because you press enter 

# As @Stefan does it, but with meta-programming 
POSSIBLE_CLASSES.collect { |p| 
    (Kernel.method(p.name).call(str); p) rescue nil 
}.compact 

最後一行的說明:

Kernel.Integer("1")返回1 Kernel.Float("1.0")回報1.0

所以基本上,我想調用內核的方法,它的名字是一樣的我的班。

Kernel.method(method_name)將方法返回給我,然後使用字符串str調用該方法。

Kernel.Integer("hello")會拋出ArgumentError;將獲救,並將收回零。

所以基本上,上面的代碼將循環遍歷可能的類並嘗試用我們從控制檯獲取的字符串初始化它們。如果沒有例外,我們收集課程,否則爲零。然後我們壓縮數組(刪除nils),然後包含'有效'類。

請注意,我們的代碼僅支持Kernel類型,並且可以輕鬆調整以支持其他類。

0

這個怎麼樣?

class String 
    def is_number? 
    true if Float(self) rescue false 
    end 
end 

現在上user_input

user_input.is_number? 
0

調用is_number?(gets.chomp == '0' || gets.chomp.to_i!= 0)=>對輸入真正是整數