Newbie: It works, how can I make it better?

J

Jay Bornhoft

I wrote this little prog giving the user two choices.

I would really appreciate any advice on how I can improve anything about
this program (structure, layout, etc)

Many thanks!

Code:
-----
# Name: 2choices-jb.rb
# Date: December 2006
# Author: Jason Bornhoft
# Email: (e-mail address removed)

puts ""
puts "Conversion Program"
puts "------------------\n"

puts "Would you like to convert:"
puts "1. F to C"
puts "2. C to F"
puts"Enter your choice now: "
choice = gets.chomp.to_i

if choice == 1
puts "Enter a temperature in F:"
fahr = gets.chomp.to_f
cent = ( (fahr - 32) / 1.8 )
puts fahr.to_s + " F is " + cent.round.to_s + " C."

elsif choice == 2
puts "Enter a temperature in C:"
cent = gets.chomp.to_f
fahr = ( (cent * 1.8) + 32 )
puts cent.to_s + " C is " + fahr.round.to_s + " F."
else
puts "That is a not a valid choice. Good bye!"
end
 
M

Marc Heiler

One mini-advice would be that there is no need for

puts ""


puts alone should be enough.


If you want, you can design a mini class for this.

Normally, especially in other languages, this is
overkill for simple programs ;)
But in ruby its nice and easy enough. And maybe practise for you.
 
W

William James

Jay said:
I wrote this little prog giving the user two choices.

I would really appreciate any advice on how I can improve anything about
this program (structure, layout, etc)

Many thanks!

Code:
-----
# Name: 2choices-jb.rb
# Date: December 2006
# Author: Jason Bornhoft
# Email: (e-mail address removed)

puts ""
puts "Conversion Program"
puts "------------------\n"

puts "Would you like to convert:"
puts "1. F to C"
puts "2. C to F"
puts"Enter your choice now: "
choice = gets.chomp.to_i

if choice == 1
puts "Enter a temperature in F:"
fahr = gets.chomp.to_f
cent = ( (fahr - 32) / 1.8 )
puts fahr.to_s + " F is " + cent.round.to_s + " C."

elsif choice == 2
puts "Enter a temperature in C:"
cent = gets.chomp.to_f
fahr = ( (cent * 1.8) + 32 )
puts cent.to_s + " C is " + fahr.round.to_s + " F."
else
puts "That is a not a valid choice. Good bye!"
end


print "
Conversion Program
------------------
Would you like to convert:
1. F to C
2. C to F
Enter your choice now: "

case gets.to_i
when 1
print "Enter a temperature in F: "
fahr = gets.to_f
cent = ( (fahr - 32) / 1.8 )
puts fahr.to_s + " F is " + cent.round.to_s + " C."

when 2
print "Enter a temperature in C: "
cent = gets.to_f
fahr = ( (cent * 1.8) + 32 )
puts "#{ cent } C is #{ fahr.round } F."

else
puts "That is a not a valid choice. Good bye!"
end

--- A more interesting way. -----

print "
Conversion Program
------------------
Would you like to convert:
1. F to C
2. C to F
Enter your choice now: "

def convert( from, to, func )
print "Enter a temperature in #{from}: "
temp = gets.to_f
puts "#{temp} #{from} is #{func[temp].round} #{to}."
end

case gets.to_i
when 1
convert( "F", "C", proc{|f| (f - 32) / 1.8 } )
when 2
convert( "C", "F", proc{|f| f * 1.8 + 32 } )
else
puts "That is a not a valid choice. Good bye!"
end
 
D

Devin Mullins

William said:
def convert( from, to, func )
print "Enter a temperature in #{from}: "
temp = gets.to_f
puts "#{temp} #{from} is #{func[temp].round} #{to}."
end

case gets.to_i
when 1
convert( "F", "C", proc{|f| (f - 32) / 1.8 } )
when 2
convert( "C", "F", proc{|f| f * 1.8 + 32 } )
else
puts "That is a not a valid choice. Good bye!"
end

Err... why not make it a block?

def convert( from, to )
print "Enter a temperature in #{from}: "
temp = gets.to_f
puts "#{temp} #{from} is #{yield(temp).round} #{to}."
end

case gets.to_i
when 1
convert( "F", "C") {|f| (f - 32) / 1.8 }
when 2
convert( "C", "F") {|f| f * 1.8 + 32 }
else
puts "That is a not a valid choice. Good bye!"
end

Also, check out http://highline.rubyforge.org/ for your prompting needs.

Devin
 
W

William James

Devin said:
Err... why not make it a block?

Why did you write "Err..."? Writing is a different process from
speaking. Making inarticulate noises when speaking provides
time to marshal one's thoughts. Imitating this when writing
is simply sarcastic, rude, and insolent---but you probably
knew that already.

A newbie may find +yield+ harder to understand than +proc+.
 
G

Giles Bowkett

Why did you write "Err..."? Writing is a different process from
speaking. Making inarticulate noises when speaking provides
time to marshal one's thoughts. Imitating this when writing
is simply sarcastic, rude, and insolent---but you probably
knew that already.

Jesus. And I thought **I** needed to get laid.
A newbie may find +yield+ harder to understand than +proc+.

Well, that is quite possible.
 
D

Devin Mullins

William said:
Why did you write "Err..."? Writing is a different process from
speaking. Making inarticulate noises when speaking provides
time to marshal one's thoughts. Imitating this when writing
is simply sarcastic, rude, and insolent---but you probably
knew that already.

No, I didn't know that, and I wouldn't be offended if you "Err"ed me. I
deliberately write in a vocal style. I find it more fun. Funner.

(Well, in this case, let's assume "Err..." means "Maybe I'm missing the
obvious here, but..." Happy?)

Devin
 
R

rwtnorton

puts ""
puts "Conversion Program"
puts "------------------\n"

puts "Would you like to convert:"
puts "1. F to C"
puts "2. C to F"
puts"Enter your choice now: "
choice = gets.chomp.to_i

if choice == 1
puts "Enter a temperature in F:"
fahr = gets.chomp.to_f
cent = ( (fahr - 32) / 1.8 )
puts fahr.to_s + " F is " + cent.round.to_s + " C."

elsif choice == 2
puts "Enter a temperature in C:"
cent = gets.chomp.to_f
fahr = ( (cent * 1.8) + 32 )
puts cent.to_s + " C is " + fahr.round.to_s + " F."
else
puts "That is a not a valid choice. Good bye!"
end

I'm using Ruby, but I'll take a stab at it (learn from my mistakes).

Well, I started off OK (using classes for temp conversion) and then
things got ugly (probably putting too much in the manager class).

At any rate, here it is. (aka, here's how not to do it. ;-)


#! /usr/bin/env ruby

class TemperatureConverter
attr_reader :from_unit, :to_unit, :conversion

def initialize( from_unit='', to_unit='', conversion=proc {|x| x } )
@from_unit = from_unit
@to_unit = to_unit
@conversion = conversion
end

def convert( arg )
@conversion.call( arg )
end
end

class FahrenheitToCelsiusConverter < TemperatureConverter
def initialize
super( 'F', 'C', proc {|f| (f - 32.0) / 1.8 } )
end
end

class CelsiusToFahrenheitConverter < TemperatureConverter
def initialize
super( 'C', 'F', proc {|c| (c * 1.8) + 32 } )
end
end

class TemperatureConversionManager
attr_reader :prompt
def initialize( *converters )
@converters = converters
@prompt = <<END_OF_PROMPT

Conversion Program
------------------
Would you like to convert:
END_OF_PROMPT

index = 0
@prompt += @converters.map do |converter|
"#{index += 1}. #{converter.from_unit} to #{converter.to_unit}"
end.join( "\n" )
@prompt += "\nEnter your choice now: "
end

def run
print prompt
user_choice = choose_converter - 1
if user_choice < 0 or user_choice >= @converters.size
puts "That is not a valid choice. Goodbye."
else
prompt_and_display_conversion( @converters[ user_choice ] )
end
end

def choose_converter
gets.chomp.to_i
end

def get_temperature
gets.chomp.to_f
end

def temperature_prompt( converter )
"Please enter temperature in #{converter.from_unit}: "
end

def prompt_and_display_conversion( converter )
print temperature_prompt( converter )
user_input = get_temperature
converted_temp = converter.convert( user_input )
puts <<END_OF_RESULTS
#{user_input} #{converter.from_unit} is #{converted_temp}
#{converter.to_unit}
END_OF_RESULTS
end
end

TemperatureConversionManager.new(
FahrenheitToCelsiusConverter.new,
CelsiusToFahrenheitConverter.new
).run



Corrections / advice / criticisms are welcome.
(I think that I prefer the original version.)

Richard
 
R

rwtnorton

puts ""
puts "Conversion Program"
puts "------------------\n"

puts "Would you like to convert:"
puts "1. F to C"
puts "2. C to F"
puts"Enter your choice now: "
choice = gets.chomp.to_i

if choice == 1
puts "Enter a temperature in F:"
fahr = gets.chomp.to_f
cent = ( (fahr - 32) / 1.8 )
puts fahr.to_s + " F is " + cent.round.to_s + " C."

elsif choice == 2
puts "Enter a temperature in C:"
cent = gets.chomp.to_f
fahr = ( (cent * 1.8) + 32 )
puts cent.to_s + " C is " + fahr.round.to_s + " F."
else
puts "That is a not a valid choice. Good bye!"
end

I'm using Ruby, but I'll take a stab at it (learn from my mistakes).

Well, I started off OK (using classes for temp conversion) and then
things got ugly (probably putting too much in the manager class).

At any rate, here it is. (aka, here's how not to do it. ;-)


#! /usr/bin/env ruby

class TemperatureConverter
attr_reader :from_unit, :to_unit, :conversion

def initialize( from_unit='', to_unit='', conversion=proc {|x| x } )
@from_unit = from_unit
@to_unit = to_unit
@conversion = conversion
end

def convert( arg )
@conversion.call( arg )
end
end

class FahrenheitToCelsiusConverter < TemperatureConverter
def initialize
super( 'F', 'C', proc {|f| (f - 32.0) / 1.8 } )
end
end

class CelsiusToFahrenheitConverter < TemperatureConverter
def initialize
super( 'C', 'F', proc {|c| (c * 1.8) + 32 } )
end
end

class TemperatureConversionManager
attr_reader :prompt
def initialize( *converters )
@converters = converters
@prompt = <<END_OF_PROMPT

Conversion Program
------------------
Would you like to convert:
END_OF_PROMPT

index = 0
@prompt += @converters.map do |converter|
"#{index += 1}. #{converter.from_unit} to #{converter.to_unit}"
end.join( "\n" )
@prompt += "\nEnter your choice now: "
end

def run
print prompt
user_choice = choose_converter - 1
if user_choice < 0 or user_choice >= @converters.size
puts "That is not a valid choice. Goodbye."
else
prompt_and_display_conversion( @converters[ user_choice ] )
end
end

def choose_converter
gets.chomp.to_i
end

def get_temperature
gets.chomp.to_f
end

def temperature_prompt( converter )
"Please enter temperature in #{converter.from_unit}: "
end

def prompt_and_display_conversion( converter )
print temperature_prompt( converter )
user_input = get_temperature
converted_temp = converter.convert( user_input )
puts <<END_OF_RESULTS
#{user_input} #{converter.from_unit} is #{converted_temp}
#{converter.to_unit}
END_OF_RESULTS
end
end

TemperatureConversionManager.new(
FahrenheitToCelsiusConverter.new,
CelsiusToFahrenheitConverter.new
).run



Corrections / advice / criticisms are welcome.
(I think that I prefer the original version.)

Richard

s/^I'm using Ruby/I'm new to using Ruby/

Sorry.
 
R

Robert Klemme

I wrote this little prog giving the user two choices.

I would really appreciate any advice on how I can improve anything about
this program (structure, layout, etc)

Since you're doing a single conversion only, you could as well use
command line arguments. I have also added automatic detection of the
conversion direction with Fahrenheit being the default input value using
regular expressions. You could use that technique in an interactive
version as well thus improving usability (because you do have to enter
one value only vs. two values).

Sample execution

$ ruby cf.rb 10c "10 f" 20

Temperature conversion

+10.0C is -12.2F
+10.0F is +50.0C
+20.0F is +68.0C

Kind regards

robert


puts <<HEAD

Temperature conversion

HEAD

ARGV.each do |val|
case val
when /^(\d+)(?:\s*f)?$/i
celsius = $1.to_f
printf "%+3.1fF is %+3.1fC\n", celsius, (celsius * 1.8) + 32
when /^(\d+)\s*c$/i
fahrenheit = $1.to_f
printf "%+3.1fC is %+3.1fF\n", fahrenheit, (fahrenheit - 32) / 1.8
else
$stderr.puts "ERROR: could not convert '#{val}'"
end
end
 
J

Jonathan Hudson

Temperature conversion

+10.0C is -12.2F
+10.0F is +50.0C
+20.0F is +68.0C

Not according to units:

$ units
2438 units, 71 prefixes, 32 nonlinear units

You have: tempC(10)
You want: tempF
50
You have: tempF(10)
You want: tempC
-12.222222
You have: tempF(20)
You want: tempC
-6.6666667

I think you may have your formulae backwards.

-jonathan
 
J

Jay Bornhoft

else
puts "That is a not a valid choice. Good bye!"
end

Thank you all for your guidance... and now I have another question...
If instead of ending the program for an invalid choice...

How do I loop back to the beginning of the program to let them make a
valid choice?


Thx, J
 
D

Drew

Jay said:
Thank you all for your guidance... and now I have another question...
If instead of ending the program for an invalid choice...

How do I loop back to the beginning of the program to let them make a
valid choice?


Thx, J

Seems to me the easiest way to go back would be to use just what you
said - a loop. A while loop would probably suffice, perhaps something
like the following:

while (line = gets) != "quit"
case line
# set of where statements
end
 
R

r

Corrections / advice / criticisms are welcome.
(I think that I prefer the original version.)

Me too. I like your heredoc usage, but overall it's too much gold
plating, looks like java to me. I would feel the pain of the next guy
to maintain this. All the meat would have to be recompressed into one
paragraph.
-R
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top