0

"Answering a cli prompt in ruby with open3?" is a possible duplicate question but it has no answer.

I need to write a program which compiles and executes a C program, gives inputs and returns the output. So far I came up with this:

For single input:

Open3.popen3('one.exe') do |stdin, stdout, stderr|
  stdin.puts "45\n"
  STDOUT.puts stdout.gets
end

and the outputs is:

Enter the temperature in degrees fahrenheit: The converted temperature is 7.222222

For two or more inputs:

Open3.popen3('two.exe') do |stdin, stdout, stderr|
  stdin.puts "45 45"
# This line works the same as the previous one.
# stdin.puts "45\r\n45"
  stdin.close

  STDOUT.puts stdout.gets
end

and the output is:

Enter first number: Enter second number: Sum is 90

The problem is, I did not get back the inputs I put in.

Is there a way I can correct it or maybe a better way to do this?

Community
  • 1
  • 1
Azam Ikram
  • 185
  • 1
  • 1
  • 10

1 Answers1

1

Consider this:

Create an input file using:

cat > test.input
bar
baz

Then press CTRL+D to terminate the input, which will cause the file test.input to be created.

In the same directory save this code as test.rb:

2.times do |i|
  user_input = gets.chomp
  puts "#{ i }: #{ user_input }"
end

Run the code using:

ruby test.rb < test.input

and you should see:

0: bar
1: baz

The reason this works is because gets reads the STDIN (by default) looking for a line-end, which in this case is the character trailing bar and baz. If I load the input file in IRB it's easy to see the content of the file:

input = File.read('test.input')
=> "bar\nbaz\n"

2.times says to read a line twice, so it reads both lines from the file and continues, falling out of the times loop.

This means you can create a file, pipe it into your script, and Ruby will do the right thing. I can rewrite the test.rb code to:

puts `sh ./test.sh < #{ ARGV[0] }`

and create test.sh:

for i in 1 2
do
  read line
  echo $i $line
done

then call it using:

ruby test.rb test.input

and get:

1 bar
2 baz

Since backticks are one of many ways to call a sub-shell or run code, you can adjust the calling code and/or the child, to read a file. Or have Ruby read the input and generate the file to be called. Or investigate using Expect, but I won't wish that on anyone.

That should help get you on the right path.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
  • Thanks for your response. I tried above examples and they work as expected, so i jump back to my original task, contents of **temp.rb** :`puts %x[sh ./test.sh < test.input]` content of **test.sh**: `./temp.o read line echo $line` and in test.input i just put 56 and the answer was still same it did not print the input. Output was: **Enter the temperature in degrees fahrenheit: The converted temperature is 13.333333** – Azam Ikram Mar 08 '16 at 01:18