为什么/我的变量如何设置为nil

时间:2011-09-17 15:43:41

标签: ruby variable-assignment

我有一些代码将文件读入一个行数组,然后解析这些行以获取结构化数据。输入文件有各种不同的数据类型,需要以不同的方式处理,另外还有各种帐户(手机号码)的主要部分。

我循环查找帐户行,识别帐户,然后我想使用该帐户,直到我遇到下一个帐户行。两者之间的行可能代表属于该帐户的各种类型的数据。问题是,在找到帐户行并设置局部变量(cur_num)后,当我想使用它时,变量设置为nil。为什么,这是怎么回事?我正在学习Ruby,所以我想要的不仅仅是修复 - 我想了解它为什么会这样工作。

这是我的代码:

  count = 0
  cur_num = ""
  lines.each do |line|
  unless (line.strip.eql?(""))  # edited due to comment from normalocity
    if (line.slice(0,15) == "Mobile Number:,")
      cur_num = line.slice(15,12)
      count = 1
      puts "Current Number: #{cur_num}"
      #puts "Object Type: #{cur_num.class}"
    else 
      data = line.strip.split(',')
      if (data.length > 8)
        data.unshift(cur_num)
        #if (count.modulo(10) == 0 || count == 1)
          puts "[#{cur_num}] #{data.inspect}"
          #pp data
        #end
        count += 1
      end
    end
  end
end

输入数据结构的概述如下所示:

Account 1
    Data Section A
        data line 1
        data line 2
     Data Section B
        data line 1
        data line 2
Account 2
    Data Section A
        data line 1
        data line 2
     Data Section B
        data line 1
        data line 2

end

将代码添加到重复行数组中,如果您尝试复制,则应将其粘贴到上面的代码示例中。我把它放在最后,试图让我的问题更具可读性:

lines = []
lines.push("ATT Wireless Bill")
lines.push("")
lines.push("Mobile Number:,770-555-1212")
lines.push("item,date,time,number called,rate period,plan type,minutes,airtime charge,ld charge,total charge")
lines.push("")
lines.push("1,2011-01-02,6:56AM,404-555-1212,NW,UNW,4,0.00,0.00,0.00")
lines.push("")
lines.push("2,2011-01-03,6:56AM,404-555-1212,NW,UNW,4,0.00,0.00,0.00")
lines.push("")
lines.push("1,2011-01-03,7:56AM,404-555-1213,DT,UM2M,5,0.00,0.00,0.00")
lines.push("")
lines.push("Mobile Number:,770-555-1213")
lines.push("item,date,time,number called,rate period,plan type,minutes,airtime charge,ld charge,total charge")
lines.push("")
lines.push("1,2011-01-02,6:56AM,404-555-1212,NW,UNW,4,0.00,0.00,0.00")
lines.push("")
lines.push("2,2011-01-03,6:56AM,404-555-1212,NW,UNW,4,0.00,0.00,0.00")
lines.push("")
lines.push("1,2011-01-03,7:56AM,404-555-1213,DT,UM2M,5,0.00,0.00,0.00")
lines.push("")

2 个答案:

答案 0 :(得分:1)

回答答案Why / How is my variable getting set to nil

如果没有cur_num = "",则不会在循环外部初始化cur_num(lines.each)。 因此,cur_num在每个循环中初始化。

我希望会出现undefined local variable or method错误,但是如果if-branch没有执行,那么在每个循环中似乎都会创建cur_num。所以你有cur_num,但没有值(或更好:它是零)。

我添加了一个简短的例子来表明,即使代码没有执行,也会创建一个变量:

if false
  a = 1
else
  p a #works fine, a was created, but it is nil
  p b #undefined local variable or method `b' 
end

附录二:

以下代码显示,循环内的变量是“循环内部”。第二个(和后续)循环在没有变量a的情况下开始。

#~ a = 0  # uncomment to compare
5.times{
  if defined? a
    puts "a is defined as #{a.inspect}"
  else
    puts "a is not defined"
    a = 1 #define it now
  end
}

相关问题:The scope is confusing


我重新设计了你的代码。当我解析像你这样的文本时,我更喜欢使用带有正则表达式的case - 语句:

count = 0
cur_num = ""
DATA.each_line do |line|
  case line
    when /\A\s\Z*/ #skip empty lines
    when /Mobile Number:,(.{12})/
      cur_num = $1
      count = 1
      puts "Current Number: #{cur_num}"
      #puts "Object Type: #{cur_num.class}"
    else 
      data = line.strip.split(',')
      if data.length > 8
        data.unshift(cur_num)
        #if (count.modulo(10) == 0 || count == 1)
          puts "[#{cur_num}] #{data.inspect}"
          #pp data
        #end
        count += 1
      end #(data.length > 8)
  end #case line
end

__END__
ATT Wireless Bill

Mobile Number:,770-555-1212
item,date,time,number called,rate period,plan type,minutes,airtime charge,ld charge,total charge

1,2011-01-02,6:56AM,404-555-1212,NW,UNW,4,0.00,0.00,0.00

2,2011-01-03,6:56AM,404-555-1212,NW,UNW,4,0.00,0.00,0.00

1,2011-01-03,7:56AM,404-555-1213,DT,UM2M,5,0.00,0.00,0.00

Mobile Number:,770-555-1213
item,date,time,number called,rate period,plan type,minutes,airtime charge,ld charge,total charge

1,2011-01-02,6:56AM,404-555-1212,NW,UNW,4,0.00,0.00,0.00

2,2011-01-03,6:56AM,404-555-1212,NW,UNW,4,0.00,0.00,0.00

1,2011-01-03,7:56AM,404-555-1213,DT,UM2M,5,0.00,0.00,0.00

答案 1 :(得分:0)

在盯着这个超过一个小时之后,比较两个几乎相同的版本,一个有效,一个没有,我能够通过评论出一条线来使它失败或成功。 这是我正在运行的确切代码: [编辑注释,更改代码以防止代码示例中的垂直滚动条]

#!/usr/local/bin/ruby
my_input ="ATT Wireless Bill\n\nMobile Number:,770-555-1212\n\nitem,date,time,number called,rate period,plan type,minutes,airtime charge,ld charge,total charge\n\n1,2011-01-02,6:56AM,404-555-1212,NW,UNW,4,0.00,0.00,0.00\n\n"
my_input << "2,2011-01-03,6:56AM,404-555-1212,NW,UNW,4,0.00,0.00,0.00\n\n1,2011-01-03,7:56AM,404-555-1213,DT,UM2M,5,0.00,0.00,0.00\n\nMobile Number:,770-555-1213\n\nitem,date,time,number called,rate period,plan type,minutes,airtime charge,ld charge,total charge\n\n"
my_input << "1,2011-01-02,6:56AM,404-555-1212,NW,UNW,4,0.00,0.00,0.00\n\n2,2011-01-03,6:56AM,404-555-1212,NW,UNW,4,0.00,0.00,0.00\n\n1,2011-01-03,7:56AM,404-555-1213,DT,UM2M,5,0.00,0.00,0.00\n\n"
lines = my_input.split("\n")
count = 0
cur_num = "" # Line  7 - Comment out this line to see failure
lines.each do |line|
unless (line.strip.eql?(""))
  if (line.slice(0,15) == "Mobile Number:,")
    cur_num = line.slice(15,12)
    count = 1
    puts "Current Number: #{cur_num}"
    #puts "Object Type: #{cur_num.class}"
  else 
    data = line.strip.split(',')
    if (data.length > 8)
      data.unshift(cur_num)
      #if (count.modulo(10) == 0 || count == 1)
        puts "[#{cur_num}] #{data.inspect}"
        #pp data
      #end
      count += 1
    end
    end
  end
end

如果我注释第7行,那么第18行和第20行的cur_val为零。

有人可以解释一下原因吗?