Problem getting user input

P

Peter Vanderhaden

I wrote a script that gets user input like this:

$stdout.print "Do you want to change something else? (y/n): "
$changeSE = gets.chomp
if $changeSE =~ /^y/
changeSomethingElse
end

After the prompt is printed, the script waits for the user to enter yes
or no via stdinput. The script was written in a procedural format as
opposed to OO. (I did that only because I'm in the process of learning
OO, and needed the script asap.) I decided to rewrite the script using
OO. Unfortunately, this part of the script doesn't work anymore. The
prompt prints, then the script keeps going on its merry way. I've
included the source for the script below. Can anyone (or everyone) see
what I'm not doing correctly? If so, I'd appreciate it if you could
explain how to correct the problem. I'd be extremely grateful for any
and all comments and assistance.
PV

1 #!/usr/bin/ruby
2 #
3 # fix1.rb - Fix common unitization file errors.
4 # 1. Remove header line.
5 # 2. Populate vendor label field with "NULL".
6 # 3. Change .TIF extension to lower case.
7 #
8 class Record
9
10 # Constructor.
11 def initialize (record_string)
12 @record = record_string
13 end
14
15 # Populates the volume label.
16 # regex: Start at the beginning of the line, match
17 # all non-comma characters, followed by 2 commas.
18 def fix_volume_label
19 # @record.sub!(/\d,,/,',NULL,')
20 @record.sub!(/^([^,]*),,/, '\1,NULL,')
21 end
22
23 # Change file extension to lowercase.
24 def fix_extension_case
25 @record.sub!('.TIF','.tif')
26 end
27
28 # Allow user to do a generic fix.
29 def changeSomethingElse
30 @record.sub!(before,after)
31 end
32
33 # Returns fixed record as a string
34 def to_str
35 @record
36 end
37
38 end
39
40 # Main thread of execution.
41 class FixOpt
42
43 def initialize
44
45 @ARGV = $* # list of arguments passed to the
script
46 @header_regex = /BegBates,Volume,Path/
47
48 @in_file = nil
49 # @out_file = nil
50 unless arguments_valid? @ARGV
51 usage
52 exit -1
53 end
54
55 # Does user want to change something else?
56 def checkChange
57 puts "Do you want to change something else (y/N): "
58 changeIt = gets
59 if changeIt =~ /^[yY]/
60 puts "Enter string to change: "
61 before = gets.chomp
62 puts "Enter new string: "
63 after = gets.chomp
64 puts "Global change? (N/y): "
65 global = gets.chomp
66 end
67 end # End checkChange method.
68
69 begin
70 @in_file = File.new @ARGV[0], "r"
71 rescue IOError
72 @in_file.close
73 puts "Error opening input file, terminating"
74 exit -1
75 end
76
77 end # End initialize method.
78
79 # Runs the program - the [C]ontroller portion of the MVC pattern.
80 def run
81 begin
82 checkChange
83 @in_file.each do |record_line|
84 next if record_line =~ @header_regex
85 record = Record.new(record_line)
86 record.fix_volume_label
87 record.fix_extension_case
88 if changeIt =~ /^[yY]/
89 record.changeSomethingElse
90 end
91 puts record.to_str
92 end
93 rescue IOError
94 @in_file.close
95 puts "Error reading from input file, terminating"
96 exit -1
97 end
98 @in_file.close
99 exit 0 # success!
100 end
101
102 # these methods are marked :private becuase they are never to be
called
103 # from anywhere outside of the class itself.
104 :private
105
106 # Validates command line arguments.
107 def arguments_valid? (argv)
108 # readable assumes the file exists, but doesn't check for it.
109 # File.stat(ARGV[0]).readable?
110 # Returns true if the named file exists and is a regular file.
111 File.file?(ARGV[0])
112 end
113
114 # Prints the usage message
115 def usage
116 puts
117 puts "Invalid filename entered: #{ARGV[0]}"
118 puts "Syntax: fix1.rb <filename>"
119 puts
120 end
121
122 end
123 fix_opt = FixOpt.new
124 fix_opt.run

If I use gets, the script just prints the prompt and seems to end.
If I use gets.chomp I get the following error:
$ ruby d:/scripts/ruby/fix1.rb 99999.opt
Do you want to change something else (y/N):
d:/scripts/ruby/fix1.rb:58:in `checkChange': private method `chomp'
called for nil:NilClass (NoMethodEr
ror)
from d:/scripts/ruby/fix1.rb:82:in `run'
from d:/scripts/ruby/fix1.rb:124
 
M

Morton Goldberg

I wrote a script that gets user input like this:

$stdout.print "Do you want to change something else? (y/n): "
$changeSE = gets.chomp
if $changeSE =~ /^y/
changeSomethingElse
end

After the prompt is printed, the script waits for the user to enter
yes
or no via stdinput. The script was written in a procedural format as
opposed to OO. (I did that only because I'm in the process of
learning
OO, and needed the script asap.) I decided to rewrite the script
using
OO. Unfortunately, this part of the script doesn't work anymore. The
prompt prints, then the script keeps going on its merry way. I've
included the source for the script below. Can anyone (or everyone)
see
what I'm not doing correctly? If so, I'd appreciate it if you could
explain how to correct the problem. I'd be extremely grateful for any
and all comments and assistance.
PV

1 #!/usr/bin/ruby
2 #
3 # fix1.rb - Fix common unitization file errors.
4 # 1. Remove header line.
5 # 2. Populate vendor label field with "NULL".
6 # 3. Change .TIF extension to lower case.
7 #
8 class Record
9
10 # Constructor.
11 def initialize (record_string)
12 @record = record_string
13 end
14
15 # Populates the volume label.
16 # regex: Start at the beginning of the line, match
17 # all non-comma characters, followed by 2 commas.
18 def fix_volume_label
19 # @record.sub!(/\d,,/,',NULL,')
20 @record.sub!(/^([^,]*),,/, '\1,NULL,')
21 end
22
23 # Change file extension to lowercase.
24 def fix_extension_case
25 @record.sub!('.TIF','.tif')
26 end
27
28 # Allow user to do a generic fix.
29 def changeSomethingElse
30 @record.sub!(before,after)
31 end
32
33 # Returns fixed record as a string
34 def to_str
35 @record
36 end
37
38 end
39
40 # Main thread of execution.
41 class FixOpt
42
43 def initialize
44
45 @ARGV = $* # list of arguments passed to the
script
46 @header_regex = /BegBates,Volume,Path/
47
48 @in_file = nil
49 # @out_file = nil
50 unless arguments_valid? @ARGV
51 usage
52 exit -1
53 end
54
55 # Does user want to change something else?
56 def checkChange
57 puts "Do you want to change something else (y/N): "
58 changeIt = gets
59 if changeIt =~ /^[yY]/
60 puts "Enter string to change: "
61 before = gets.chomp
62 puts "Enter new string: "
63 after = gets.chomp
64 puts "Global change? (N/y): "
65 global = gets.chomp
66 end
67 end # End checkChange method.
68
69 begin
70 @in_file = File.new @ARGV[0], "r"
71 rescue IOError
72 @in_file.close
73 puts "Error opening input file, terminating"
74 exit -1
75 end
76
77 end # End initialize method.
78
79 # Runs the program - the [C]ontroller portion of the MVC pattern.
80 def run
81 begin
82 checkChange
83 @in_file.each do |record_line|
84 next if record_line =~ @header_regex
85 record = Record.new(record_line)
86 record.fix_volume_label
87 record.fix_extension_case
88 if changeIt =~ /^[yY]/
89 record.changeSomethingElse
90 end
91 puts record.to_str
92 end
93 rescue IOError
94 @in_file.close
95 puts "Error reading from input file, terminating"
96 exit -1
97 end
98 @in_file.close
99 exit 0 # success!
100 end
101
102 # these methods are marked :private becuase they are never
to be
called
103 # from anywhere outside of the class itself.
104 :private
105
106 # Validates command line arguments.
107 def arguments_valid? (argv)
108 # readable assumes the file exists, but doesn't check for it.
109 # File.stat(ARGV[0]).readable?
110 # Returns true if the named file exists and is a regular file.
111 File.file?(ARGV[0])
112 end
113
114 # Prints the usage message
115 def usage
116 puts
117 puts "Invalid filename entered: #{ARGV[0]}"
118 puts "Syntax: fix1.rb <filename>"
119 puts
120 end
121
122 end
123 fix_opt = FixOpt.new
124 fix_opt.run

If I use gets, the script just prints the prompt and seems to end.
If I use gets.chomp I get the following error:
$ ruby d:/scripts/ruby/fix1.rb 99999.opt
Do you want to change something else (y/N):
d:/scripts/ruby/fix1.rb:58:in `checkChange': private method `chomp'
called for nil:NilClass (NoMethodEr
ror)
from d:/scripts/ruby/fix1.rb:82:in `run'
from d:/scripts/ruby/fix1.rb:124

I can not reproduce your problem. When I run

<code>
class Foo
def checkChange
puts "Do you want to change something else (y/N): "
changeIt = gets.chomp
if changeIt =~ /^[yY]/
puts "Enter string to change: "
before = gets.chomp
puts "Enter new string: "
after = gets.chomp
puts "Global change? (N/y): "
global = gets.chomp
end
p [changeIt, before, after, global]
end
end
Foo.new.checkChange
</code>

I see the following

<result>
Do you want to change something else (y/N):
Enter string to change:
Enter new string:
Global change? (N/y):
["y", "foo", "bar", "n"]
</result>

I will note the variables changeIt, before, after, and global are
local variables and will not available outside of the checkChange
method. That may be part of your problem.

Regards, Morton
 
S

Sebastian Hungerecker

Peter said:
If I use gets, the script just prints the prompt and seems to end.

I see in your script that ARGV is not empty. That means Kernel#gets is
gonna read from the files in ARGV and not from stdin. To rectify that
use $stdin.gets instead. Or empty ARGV before you call gets.


HTH,
Sebastian
 
P

Peter Vanderhaden

Sebastian,
THANK YOU, THANK YOU, THANK YOU!
The $stdin.gets works perfectly! I really appreciate all you
experienced folks helping out this newbie! I'm going to hilight this
stuff in PickAxe when I get done.
PV
 
M

Morton Goldberg

Sebastian,
THANK YOU, THANK YOU, THANK YOU!
The $stdin.gets works perfectly! I really appreciate all you
experienced folks helping out this newbie! I'm going to hilight this
stuff in PickAxe when I get done.
PV

Speaking of ARGV, you don't need this line in your code:

45 @ARGV = $* # list of arguments passed to the script

Just use the pre-defined ARGV instead of @ARGV

Regards, Morton
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top