Running cmd commands through ruby

1.5k views Asked by At

I am writing a program which execute an other program written in c, here is my first try

require 'Open3'

system 'tcc temp.c'

Open3.popen3('temp.exe') do |stdin, stdout, stderr|
   stdin.puts '21\n'
   STDOUT.puts stdout.gets
end

actual output:

Enter the temperature in degrees fahrenheit: The converted temperature is -6.11

desired output:

Enter the temperature in degrees fahrenheit: 21
The converted temperature is -6.11

and if you know a better way to do that please tell me, i am new to ruby.

2

There are 2 answers

1
Todd A. Jacobs On

You seem to have at least two potential issues:

  1. Your newline will not expand inside single quotes. To include a newline within a string, you need to use double-quotes such as "21\n".
  2. In some cases, you actually need a carriage return rather than a newline. This is especially true when trying to do Expect-like things with a terminal. For example, you may find you need \r instead of \n in your string.

You definitely need to fix the first thing, but you may need to try the second as well. This is definitely one of those "your mileage may vary" situations.

1
Jordan Running On

It seems like you're expecting 21 to appear on your screen because it does when you run temp.exe and type in 21. The reason it appears on your screen under those circumstances is that you're typing them into your shell, which "echoes" back everything you type.

When you run the program via Ruby, though, there's no shell and no typing, so 21 doesn't appear on your screen even though it's correctly being sent to the program's standard input.

The simplest solution is pretty simple. Just write it to Ruby's standard output as well:

require 'Open3'

system 'tcc temp.c'

Open3.popen3('temp.exe') do |stdin, stdout, stderr|
  STDOUT.puts "21"
  stdin.puts '"21"
  STDOUT.puts stdout.gets
end

(You'll note that I took out \nIO#puts adds that for you.)

This is a little repetitive, though. You might define a simple method to take care of it for you:

def echo(io, *args)
  puts *args
  io.puts *args
end

Then:

Open3.popen3('temp.exe') do |stdin, stdout, stderr|
  echo(stdin, "21")
  puts stdout.gets
end