Problem z tablicami w Ruby

Mam problem z tablicami w Ruby.
Chcę ten kod z c++ przenieść do Ruby

[code]#include <iostream.h>

using namespace std;

int main()
{
int nominal[6]={500,200,100,50,20,10};
int reszta;
cin>>a;
int n=0;
int ile[6]={0,0,0,0,0,0};

for ( ; ; )
{
if (a>=nominal[n])
{
ile[n]=(a-a%nominal[n])/nominal[n];
}
a=a%nominal[n];
n=n+1;
if (n==6)
{break;}
}
cout<<"\n Monet 5zl:"<<ile[0];
cout<<"\n Monet 2zl:"<<ile[1];
cout<<"\n Monet 1zl:"<<ile[2];
cout<<"\n Monet 0,50zl:"<<ile[3];
cout<<"\n Monet 0,20zl:"<<ile[4];
cout<<"\n Monet 0,10zl:"<<ile[5];
cin>>n;
return 0;
}[/code]
Napisałem coś takiego (jest tego trochę więcej bo to projekt na studia)

[code]class Puszka
def initialize(nazwa, cena, ilosc)
@nazwa = nazwa
@cena = cena
@ilosc = ilosc
end
def to_s
“Napoj: #@nazwa, cena: #@cena zl, ilosc: #@ilosc
end
def wydaj
@ilosc=@ilosc-1
end
def zakup
if ($kasa < @cena) then puts “Za malo pieniedzy”
elsif @ilosc==0 then puts “Brak towaru, przepraszamy”
else self.wydaj
@@reszta=$kasa-@cena
self.obliczreszte
puts “Automat sprzedaje napoj #@nazwa i \nwydaje reszte w wysokosci #@@reszta zl”
end
end
def wplacmonete
n = 0
until n<6
a1=$nominal.at(n)
i=$ile[n]
b=$kasa10
if (b>=a1) then i = ((b-b.divmod(a1))/a1)
end
b=b.divmod(a1)
n=n+1
end
z = 0
until z<6
$stan2[z]=$stan.at(z)+$ile.at(z)
z=z+1
end
end
def obliczreszte
n = 0
until n<6
a1=$nominal.at(n)
i=$ile[n]
b=@@reszta
10
if (b>=a1) then i = ((b-b.divmod(a1))/a1)
end
b=b.divmod(a1)
n=n+1
end
z = 0
until z<6
$stan2[z]=$stan.at(z)-$ile.at(z)
z=z+1
end
end
def stanbanku
print "Monet o nominale 5,00zl: "
puts $stan.at(0)
print "Monet o nominale 2,00zl: "
puts $stan.at(1)
print "Monet o nominale 1,00zl: "
puts $stan.at(2)
print "Monet o nominale 0,50zl: "
puts $stan.at(3)
print "Monet o nominale 0,20zl: "
puts $stan.at(4)
print "Monet o nominale 0,10zl: "
puts $stan.at(5)
end
def stanbanku2
print "Monet o nominale 5,00zl: "
puts $stan2.at(0)
print "Monet o nominale 2,00zl: "
puts $stan2.at(1)
print "Monet o nominale 1,00zl: "
puts $stan2.at(2)
print "Monet o nominale 0,50zl: "
puts $stan2.at(3)
print "Monet o nominale 0,20zl: "
puts $stan2.at(4)
print "Monet o nominale 0,10zl: "
puts $stan2.at(5)
end
end

cola =Puszka.new(“Coca-cola”, 2.20, 30)
sprite =Puszka.new(“Sprite”, 1.80, 25)
fanta =Puszka.new(“Fanta”, 2.00, 35)
test =Puszka.new(“Test”, 0, 0)
$stan=Array.new
$stan=[50,50,50,50,50,50]
$stan2=Array.new
$nominal=Array.new
$nominal=[500,200,100,50,20,10]
$ile=Array.new
puts “Trwa sprawdzanie automatu, prosze czekac…”
puts “W automacie znajduja sie obecnie takie napoje:”
print "1. "
puts cola.to_s
print "2. "
puts sprite.to_s
print "3. "
puts fanta.to_s
puts “W automacie znajduja sie obecnie takie monety:”
test.stanbanku
puts “Sprawdzanie zostalo zakonczone sukcesem”
puts
puts
puts
puts “Witamy! Prosze wrzucic monete”
$kasa=gets.to_f
puts “Automat przyjal #$kasa zl”
test.wplacmonete
puts “Prosze wybrac jeden z napojow podanych \nponizej i nacisnac odpowiedni numer na klawiaturze,\nw przypadku rezygnacji z zakupow prosze nacisnac 0”
print "1. "
puts cola.to_s
print "2. "
puts sprite.to_s
print "3. "
puts fanta.to_s
@wybor=gets.to_i
if @wybor==1 then cola.zakup
elsif @wybor==2 then sprite.zakup
elsif @wybor==3 then fanta.zakup
elsif @wybor==0 then puts “Zegnamy”
else puts “Przykro nam, nie mamy takiego napoju”
end
puts “W automacie pozostaly nastepujace napoje:”
print "1. "
puts cola.to_s
print "2. "
puts sprite.to_s
print "3. "
puts fanta.to_s
puts “W automacie znajduja sie obecnie takie monety:”
test.stanbanku2
puts “Nacisnij dowolny klawisz aby kontynuowac…”
@thaend=gets.to_i[/code]
chodzi mi głównie o metody wplacmonete i obliczreszte
Moglby mi ktos udzielic jakis wskazowek jak to wyprostowac by dzialalo wedle oczekiwan?
Metoda wplacmonete ma dodac wrzucona monete do tablicy stan2 i glownie o to mi chodzi, jak juz bede wiedzial jak sobie z tym poradzic to dalej bedzie juz z gorki :wink:

Jeśli to się ma kupy trzymać to zdecydowanie powinieneś przemyśleć następujące sprawy:

  1. Po co używać zmiennych globalnych typu $ile, $stan?
  2. Po co używać zmiennych klasowych typu @@reszta (w ogóle skąd taki pomysł aby resztę trzymać w zmiennej klasowej???)
  3. Może należałoby zrobić klasę bank (może lepiej kasa albo automat), w której byłaby trzymana informacja o liczbie monet poszczególnych typów i liczbie puszek?
  4. Po co mieszać użycie [] i at? Mo to jakiś głębszy sens?
  5. Znasz instrukcję case???
  6. Po co w głównej części programu używać zmiennych instancyjnych?
  7. Czy wiesz, że metody mogą przyjmować parametry? Jeśli tak to użyj tego podstawowego mechanizmu przekazywania stanu, a nie uciekaj się do dziwnej mikstury zmiennych instancyjnych i globalnych.
  8. I jeszcze to dziwne formatowanie

if elsif elsif
Mam jeszcze kilka uwag, ale już mi się nie chce ich spisywać.

Ta odpowiedź nie ma być złośliwa - mam nadzieję, że tak jej nie odbierasz. Po prostu, gdybyś przyniósł mi taki kod na zaliczenie, to być nie zaliczył :slight_smile: Może lepiej pozostać przy wersji C++? A jeśli już musi być w Rubim, to radzę lepiej opanować jego podstawy.

[quote=apohllo]Jeśli to się ma kupy trzymać to zdecydowanie powinieneś przemyśleć następujące sprawy:

  1. Po co używać zmiennych globalnych typu $ile, $stan?

  2. Po co używać zmiennych klasowych typu @@reszta (w ogóle skąd taki pomysł aby resztę trzymać w zmiennej klasowej???)

  3. Może należałoby zrobić klasę bank (może lepiej kasa albo automat), w której byłaby trzymana informacja o liczbie monet poszczególnych typów i liczbie puszek?

  4. Po co mieszać użycie [] i at? Mo to jakiś głębszy sens?

  5. Znasz instrukcję case???

  6. Po co w głównej części programu używać zmiennych instancyjnych?

  7. Czy wiesz, że metody mogą przyjmować parametry? Jeśli tak to użyj tego podstawowego mechanizmu przekazywania stanu, a nie uciekaj się do dziwnej mikstury zmiennych instancyjnych i globalnych.

  8. I jeszcze to dziwne formatowanie

if elsif elsif
Mam jeszcze kilka uwag, ale już mi się nie chce ich spisywać.

Ta odpowiedź nie ma być złośliwa - mam nadzieję, że tak jej nie odbierasz. Po prostu, gdybyś przyniósł mi taki kod na zaliczenie, to być nie zaliczył :slight_smile: Może lepiej pozostać przy wersji C++? A jeśli już musi być w Rubim, to radzę lepiej opanować jego podstawy.[/quote]
Zmieniłem “trochę” program i wyrzuciłem z niego całkowicie tablice.
1 - te zmienne zniknęły całkowicie
2 i 3 - dodałem klasę Bank a zmienną reszta zrobiłem globalną (by mieć do niej dostęp zarówno z klasy Puszka jak i Bank)
4 - nieaktualne aczkolwiek wynikało to trochę z mojej błędnej interpretacji, myślałem że wyrażenie postaci tablica[n]=k wpisze w n-te miejsce tej tablicy wyrażenie k
5 - case znam ale przy tym wyborze puszki nie jest to jakaś szczególnie duża pętla, poza tym póki co chodziło mi głównie o to by program działał, na kosmetykę przyjdzie czas
6 - ?
7 wiem aczkolwiek mój wykładowca zamiast np. metody silnia(n) woli coś w postaci n.silnia (wszak w Rubym wszystko jest obiektem i takie gadanie)

ale dzięki za uwagi, postaram się coś zapamiętać i może zainteresuję się bardziej Rubym z własnej inicjatywy a nie przymusu napisania projektu po jednych zajęciach z tego języka (bo przez resztę semestru wałkowaliśmy C++). A projekt w C++ też musi być i w sumie już jest :wink:

Klasa Bank - ok. Ale dlaczego reszta w zmiennej globalnej??? Tego nadal pojąć nie mogę - zmienne globalne są źródłem wszelkiego zła, należy to wziąć sobie do serca, napisać nad łóżkiem albo powtarzać w czasie kąpieli.

Nie wpisze wyrażenia, ale jego wartość. Myślę, że o to właśnie chodziło. a[4] zwraca wartość 4 elementu tablicy a.
a[4] = 5 przypisuje wartość 4 elementowi tablicy a. To ma być proste i intuicyjne i takie właśnie jest :slight_smile:

Chodziło mi o ten fragment:

if @wybor==1 then cola.zakup elsif @wybor==2 then sprite.zakup elsif @wybor==3 then fanta.zakup elsif @wybor==0 then puts "Zegnamy" else puts "Przykro nam, nie mamy takiego napoju" end
To wręcz klasyczny przykład możliwość zastosowania instrukcji case - jest krócej i przejrzyściej, np.

case @wybor when 1 : cola.zakup when 2 : sprite.zakup when 3 : fanta.zakup when 0 : puts "Zegnamy" else : puts "blablabla" end

@wybor to zmienna instancyjna, której wykorzystanie w kontekście globalnym zupełnie mija się z celem.
Czy nie wystarczyłoby napisać wybor?

Ok, ale nie oznacza to chyba, że wszystkie wywołania metod można uczynić bezparametrycznymi (za cenę wykorzystania zmiennych globalnych). To są dwie zupełnie inne bajki. Pomyśl o tym tak - w przypadku silni dodajesz nową własność do obiektów pewnej klasy. Tę własność możesz właśnie wywołać w ten ładny, obiektowy sposób 5.silnia. Natomiast wywołanie typu wplacmonete nie podpada pod ten schemat. Tzn. częściowo podpada: automat.wplacmonete, ale musisz jeszcze przekazać parametr - jaką monetę wpłacasz i to MUSI być zrobione właśnie przez parametr formalny tego wywołania, np. automat.wplacmonete(10). Wszelkie inne rozwiązania są czystym gwałtem na podstawowych zasadach poprawnego programowania zorientowanego obiektowo. Kropka.

Rubi to piękny język :slight_smile: No cóż - skoro macie napisać projekt, po jednych zajęciach, to IMHO nie ma to zupełnie żadnego sensu (rozumiem, że jesteś gdzieś w okolicach pierwszego roku i że nie liznęliście żadnych podstaw modelowania obiektowego). Jego siła tkwi między innymi w prostocie i przejrzystości kodu, jaką można uzyskać dzięki stosowaniu podejścia obiektowego (w przeciwieństwie np. do Javy, w której obiektowość została nieźle spartaczona, ale to temat na długie jesienne wieczory, a nie duszne czerwcowe noce :slight_smile:

Jeśli chodzi o mnie, to jest to mój język nr 2, zaraz po LISPIe, który niestety ostatnio nie jest raczej na fali :slight_smile:
Warto go poznać, bo rozsądnie stosowany daje olbrzymie możliwości, ale co więcej - sprawia, że programowanie może być naprawdę przyjemne :wink: