【问题标题】:User input string or integer用户输入字符串或整数
【发布时间】:2014-05-02 07:43:12
【问题描述】:

我试图找出用户输入的是字符串还是整数。如果我根据用户输入的要求输入一个固定值,我可以找到它。我无法获得它的课程。

这行得通:

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

【问题讨论】:

  • #gets 总是给你字符串...顺便说一句
  • 确实如此。当我输入 gets.to_i 时,它总是给出整数。那么获取输入内容的方法是什么?
  • 这取决于你想要验证的类型......
  • 如果要查看字符串是否为数字,请看这里:stackoverflow.com/questions/5661466/…
  • 我想知道输入是fixnum、bignum、string还是float

标签: ruby


【解决方案1】:

我想我要问你的问题是用户如何输入字符串?

如果用户输入:

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

【讨论】:

  • eval?你在开玩笑吗?
  • eval 不仅评估文字,还评估 any Ruby 代码。
  • 是的,我意识到这一点。这取决于如何接受用户输入。但这似乎是获得预期结果的最佳方式。通过转换,甚至像 Kernel#Integer 等内核转换。您必须选择首先转换哪个或像 Stefan 在他的回答中所做的那样并创建一个有效类的列表,但这似乎不是预期的结果,它会将任何数字输入转换为浮点数,所以...
  • 你最好使用 Ruby 解析器,它不会执行给定的代码。
  • 嗯。没想到。
【解决方案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

【讨论】:

  • 很好地使用了Kernel#Integer;我在回答中重复使用了你的东西 =) +1
  • 嗨 Stefan,我 15 天前才开始学习 ruby​​。我已经学习了方法和类。但是我仍然没有足够的经验将您的答案正确地输入到我的代码中。你能帮助我吗 ?这将是假证明。
  • 太棒了。它奏效了。我应该如何缩小结果范围?当 i 为整数 10 时。它告诉我它可以是 string 、 fixnum 、 float 。如何得到它是一个fixnum?
  • @lenso_here 你不能 :) 它可能是字符串 "10" 或数字 10。用户只需点击12enter,由您来解释输入。
  • 情况越来越复杂了。 10 是一个整数。我想让它被识别为整数。我觉得你帮了很多忙。太感谢了。但是,我仍然处于编码的第一章。所以我需要更多时间。
【解决方案3】:

正如@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 并将确定它可能的类。

# 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;将被救出并收集 nil。

所以基本上,上面的行将遍历可能的类,并尝试使用我们从控制台获得的字符串来初始化它们。如果没有异常,我们收集类,否则为 nil。然后我们压缩数组(删除 nil),然后将包含“有效”类。

请注意,我们上面的代码仅支持 Kernel 类型,并且可以轻松调整以支持其他类。

【讨论】:

    【解决方案4】:

    这个怎么样?

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

    现在拨打is_number?user_input

    user_input.is_number?
    

    【讨论】:

      【解决方案5】:

      (gets.chomp == '0' || gets.chomp.to_i != 0) => true 输入是整数

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-09-19
        • 2020-08-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-11
        • 1970-01-01
        相关资源
        最近更新 更多