2017-08-17 2 views
0

Ich machte ein Programm, das Strings von Namen in einem Array speichert, es fragt nach Benutzereingabe mit gets.chomp, nach der Eingabe ADD Name, fügt er den Namen in ein Array mit Push und DEL Name, um diesen Namen aus dem Array zu löschen, jetzt möchte ich "REPLACE Name1 Name2" eingeben, um Name1 durch Name2 im Array zu ersetzen. Vielen Dank im Voraus :)Wechseln von Wörtern in einem String-Satz mit Ruby

class Base 
    @@names_array = Array.new(0) 

    def set_names_array(name) 
    @@names_array.push(name) 
    end 

    def get_names_array 
    return @@names_array 
    end 

    def delete_name(name) 
    @@names_array.delete(name) 
    end 
end 


class Op 
    loop_flag = true 
    puts "Type ADD 'name' to add a name, DEL 'name' to delete, and EXIT to end program." 

    while loop_flag 
    command = gets.chomp 
    @nameobj = Base.new 

    if command[0..2] == "ADD" 
     @@name = command[4, command.length] 

     @nameobj.set_names_array(@@name) 

     puts "#{@@name} was added." 
     puts "Names:" 
     puts "#{@nameobj.get_names_array}" 
    end 

    if command == "EXIT" 
     puts "Ended." 
     loop_flag = false 
    end 

    if command[0..2] == "DEL" 
     for i in @nameobj.get_names_array 
     if i == command[4, command.length] 
      @nameobj.delete_name(i) 
      puts "Names:" 
      puts "#{@nameobj.get_names_array}" 
     end 
     end 
    end 

    if command[0..2] == "REP" 
    # cannot do [4, command.length] because there will be 2 names with 
    # various lengths which aren't fixed. 
    end 

    end 
end 
+4

Sie wirklich, wirklich, * wirklich * sollte nicht Code wie das innerhalb einer 'Klasse' Definition setzen. Es dient keinem Zweck. Jede Interaktion mit dem Benutzer sollte innerhalb der tatsächlichen Methoden erfolgen, wenn Sie eine Klasse verwenden. – tadman

+0

Verwenden Sie auch 'commands = gets.chomp.split (/ \ s + /)', um Benutzereingaben in eine Reihe von Wörtern zu zerlegen. Dann können Sie die Wörter "case" und jeden Befehl mit einer geraden where-Klausel behandeln. – tadman

+0

Eine andere Beobachtung ist, dass Sie mit 'break' aus Loops ausbrechen können, also ist' loop do ... end' mit einem 'break' innerhalb besser als eine beliebige loop-endende Variable, die Sie manipulieren müssen. 'break' ist unmittelbar, das Setzen eines Flags ist nicht und kann nicht verhindern, dass anderes Verhalten auftritt. – tadman

Antwort

1

Sie diese Methode, um Base class hinzufügen:

def replace_names_array(name_to_replace, new_name) 
    @@names_array = @@names_array.map do |name| 
    name == name_to_replace ? new_name : name 
    end 
end 
1

Es gibt eine Menge Dinge zu beachten, aber das wichtigste ist, dass während sind Sie erlaubt Freiformcode innerhalb der Klassen- oder Moduldefinitionen in zu setzen, wird davon abgeraten, außer für Situationen, in denen Sie keine andere Wahl haben, als ob Sie eine Metaprogrammierung auf Klassen- oder Modulebene durchführen.

In praktisch jedem anderen Fall möchten Sie diesen Code entweder im Hauptkontext ausdrücken, der außerhalb dieser Definitionen liegt, oder in genau definierten Methoden, die Sie bei Bedarf aufrufen können.

Wenn Sie tiefer gehen, scheint die Base-Klasse, die Sie definiert haben, ausschließlich Variablen auf Klassenebene zu verwenden. Dies bedeutet, dass alle Objekte, die new produzieren, funktional identisch sind, auch wenn sie technisch unterschiedlich sind. Was Sie wahrscheinlich wollen, ist eine einfache Singleton Version:

module NameRegistry 
    def self.names 
    @names ||= [ ] 
    end 
end 

Mit dieser jetzt ziemlich einfach ist, die ich in einem zweiten demonstrieren werde. Die nächste Sache zu beheben ist die Parser-Klasse, indem sie ihre Verantwortung dramatisch reduziert. können Sie reguläre Ausdrücke verwenden, um eine einfache Grammatik zu definieren, die flexibel ist, und leicht für ungewöhnliche Anwendungsfälle angepasst werden kann:

class CommandParser 
    def parse(line) 
    case (line) 
    when /\AADD\s+(.*)\z/i 
     NameRegistry.names.push($1) 
    when /\ADEL\s+(.*)\z/i 
     NameRegistry.names.delete($1) 
    when /\AREP\s+(.*)\s+WITH\s+(.*)\z/i 
     if (NameRegistry.names.delete($1)) 
     NameRegistry.names.push($2) 
     end 
    when /\AEXIT\z/i 
     # Signal that this command was terminal 
     return false 
    end 

    # Default to success 
    true 
    end 
end 

Dies führt zu einem Klumpen des Haupt Code, der wie folgt aussieht:

puts "Type ADD 'name' to add a name, DEL 'name' to delete, and EXIT to end program." 

parser = CommandParser.new 

while (parser.parse(gets.chomp)) 
    puts "Names: #{NameRegistry.names.join(', ')}" 
end 
Verwandte Themen