Getting Input One Line at a Time

Problem

You e writing an interactive console program, and you want to get line-based input from the user. You present the user with a prompt, and he types some data before hitting enter.

Solution

Instead of reading standard input all at once, read it a line at a time with gets or readline.

This method populates a data structure with values obtained from user input:

def confirmation_hearings questions = [[What is your name?, :name], [How old are you?, :age], [Why would you like to be Secretary of the Treasury?, :why]] answers = questions.inject({}) do |answers, qv| question, value = qv print question + answers[value] = gets.chomp answers end puts "Okay, you e confirmed!" return answers end confirmation_hearings # What is your name? # <= Leonard Richardson # How old are you? # <= 27 # Why would you like to be Secretary of the Treasury? # <= Mainly for the money # Okay, you e confirmed! # => {:age=>"26", :why=>"Mainly for the money", :name=>"Leonard Richardson"}

Discussion

Most console programs take their input from command-line switches or from a file passed in on standard input. This makes it easy to programatically combine console programs: you can pipe cat into grep into last without any of the programs having to know that they e connected to each other. But sometimes its more user-friendly to ask for input interactively: in text-based games, or data entry programs with workflow.

The only difference between this technique and traditional console applications is that you e writing to standard output before you e completely done reading from standard input. You can pass an input file into a program like this, and itll still work. In this example, a Ruby program containing the questionnaire code seen in the Solution is fed by an input file:

$ ./confirmation_hearings.rb < answers # => What is your name? How old are you? Why would you like to be # Secretary of the Treasury? Okay, you e confirmed!

The program works, but the result looks differenteven though the standard output is actually the same. When a human is running the program, the newline created when they hit enter is echoed to the screen, making the second question appear on a separate line from the first. Those newlines don get echoed when they e read from a file.

The HighLine library requires that you install a gem ( highline), but it makes sophisticated line-oriented input much easier. You can make a single method call to print a prompt, retrieve the input, and validate it. This code works the same way as the code above, but its shorter, and it makes sure you enter a reasonable age for the question "How old are you?"

require ubygems require highline/import def confirmation_hearings answers = {} answers[:name] = ask(What is your name? ) answers[:age] = ask(How old are you? , Integer) { |q| q.in = 0..120 } answers[:why] = ask(Why would you like to be Secretary of the Treasury? ) puts "Okay, you e confirmed!" return answers end confirmation_hearings # What is your name? # <= Leonard Richardson # How old are you? # <= twenty-seven # You must enter a valid Integer. # ? # <= 200 # Your answer isn within the expected range (included in 0..120) # ? # <= 27 # …

See Also

Категории