Tak jak obiecałem, oto moje uwagi do twojego programu.
Jeśli chodzi o komunikat błędu “Division by zero” - w pierwszej wersji programu próbowałeś się odwołać do zmiennej bez uprzedniego nadania jej wartości początkowej. W przypadku Pascala kompilator sam nadaje wartości początkowe deklarowanym zmiennym zależnie od typu:
zmienne całkowite i rzeczywiste - zero
zmienne typu string - łańcuch pusty (’’)
zmienne logiczne - false
ale nie warto na tym polegać i lepiej zrobić to samemu (może się zdarzyć, że inny kompilator tego nie będzie robił i wówczas wartość zmiennej będzie nieokreślona) Na Twoje nieszczęście akurat zmiennej, której nie zainicjowałeś została przypisana wartość 0.
Zmienne globalne najlepiej deklarować na początku programu, zaraz po deklaracjach uses i type, przed odwoływaniem się do tych zmiennych w funkcjach, czy procedurach (mimo iż kompilator pozwala robić to później, przed rozpoczęciem bloku głównego programu)
W Pascalu w nazwach zmiennych, czy procedur przyjęło się stosować tzw Styl wielbłądzi np: MojaPierwszaProcedura (podkreślenie to raczej w innych językach). Tu masz link do artykułu na temat Zasad pisania kodu
Funkcja czy procedura. W Pascalu jest podział na funkcje i procedury (w innych językach mogą być tylko funkcje). Zasada jest taka, że procedura tylko wykonuje pewne instrukcje, a funkcja oblicza jedną wartość oraz ją udostępnia. Wywołanie funkcji następuje za pomocą podania nazwy funkcji jako argumentu dowolnego wyrażenia. Lepiej pokazać to na przykładzie:
procedure Suma1(a, b: Integer, var Wynik: Integer);
begin
Wynik:= a + b;
end;
function Suma2(a, b: Integer): Integer;
begin
Suma2:= a + b;
end;
A teraz użycie w bloku głównym programu:
var a, b, Suma: Integer;
begin
a:= 1;
b:= 2;
(* procedura *)
Suma1(a, b, Suma); (* Procedura zapisuje wynik do zmiennej Suma *)
Writeln('Suma = ', Suma);
(* funkcja *)
Suma:= Suma2(a, b); (* Zmiennej Suma jest przypisywana wartość funkcji Suma2 *)
Writeln('Suma = ', Suma);
(* Zamiast dwóch linijek powyżej można krócej *)
Writeln('Suma = ', Suma2(a, b));
end.
Niektóre kompilatory Pascala pozwalają na wywoływanie funkcji jak procedur, ale w starszych wersjach (np turbo Pascal 5.5) kompilacja by się nie udała. W przypadku Twojego programu zastosowałbym procedury, może za wyjątkiem funkcji Wyznaczniki i Obliczenia (po odpowiedniej modyfikacji). Definiowanie bloku programu jako procedury. Generalnie warto to robić nawet, jeśli dana procedura, bądź funkcja miałaby być wywoływana tylko raz, pod warunkiem, że uprości to kod i zwiększy jego czytelność. Natomiast, jeżeli mamy dwie procedury, które wykonują podobne instrukcje, ale na innych zmiennych, to można je zastąpić jedną z odpowiednimi parametrami. Dłuższy kod wcale nie musi być lepszy. Poniżej procedura wczytująca dane
procedure WczytajDaneRownania(Tekst: string; a1, b1, c1: Char; var a, b, c: Real);
begin
Writeln(Tekst);
Write('Podaj czynnik ', a1, ': ');
Readln(a);
Write('Podaj czynnik ', b1, ': ');
Readln(b);
Write('Podaj czynnik ', c1, ': ');
Readln(c);
end;
Zauważ, że w definicji procedury fragment var a, b, c: Real nie oznacza wcale, że musimy operować na zmiennych globalnych a, b, c (to tylko zbieżność nazw). Poczytaj o parametrach formalnych i parametrach aktualnych. Wywołując procedurę możemy wstawić dowolne zmienne np. d, e, f. Widać to w drugim wywołaniu:
WczytajDaneRownania('Pierwsze równanie: ax + by = c', 'a', 'b', 'c', a, b, c);
WczytajDaneRownania('Drugie równanie: dx + ey = f', 'd', 'e', 'f', d, e, f);
Jeszcze jedna uwaga: w definicji procedury w miejscu, gdzie podajemy parametry niektóre są poprzedzone słowem var. Są to parametry przekazywane przez zmienną, a stosujemy je wówczas, gdy chcemy aby ich wartość była znana również poza procedurą (poczytaj również o parametrach przekazywanych przez wartość lub przez zmienną). Co do porównywania wyznaczników układu równań do zera. Myślę, że można to zrobić wprost, ponieważ przy ich obliczaniu występuje tylko mnożenie i dodawanie liczb wymiernych, a wiec zawsze będą liczbami wymiernymi i komputer będzie mógł przyrównać je do zera. Uff, trochę się tego nazbierało! Mam nadzieję, że doczytałeś do końca. Oto moja wersja programu po modyfikacjach, choć zapewne nie jest jeszcze doskonała. Można w nim wiele rzeczy zmienić, poprawić, więc … próbuj
program UkladRownan;
uses crt;
var
a,b,c,d,e,f: real;
wg,wx,wy,x,y: real;
procedure start;
begin
clrscr;
writeln('Program do obliczania ukladow rownan z dwoma niewiadomymi');
writeln;
end;
procedure WczytajDaneRownania(Tekst: string; a1, b1, c1: Char; var a, b, c: Real);
begin
Writeln(Tekst);
Write('Podaj czynnik ', a1, ': ');
Readln(a);
Write('Podaj czynnik ', b1, ': ');
Readln(b);
Write('Podaj czynnik ', c1, ': ');
Readln(c);
Writeln;
end;
procedure WyswietlUklad(a,b,c,d,e,f:real);
begin
writeln('Uklad rownan:');
writeln(a:0:2,'x + ',b:0:2,'y = ',c:0:2);
writeln(d:0:2,'x + ',e:0:2,'y = ',f:0:2);
end;
procedure Wyznaczniki(a,b,c,d,e,f: Real; var wg,wx,wy: real);
begin
wg:= a*e - d*b;
wx:= c*e - f*b;
wy:= a*f - d*c;
end;
procedure Rozwiazania(x,y,wx,wy,wg,a,b,c,d,e,f:real);
begin
if wg = 0 then
begin
if (wx = 0) and (wy = 0) then writeln ('Uklad nieoznaczony.')
else writeln('Uklad sprzeczny.');
end
else
begin
x:= wx/wg;
y:= wy/wg;
writeln('MA JEDNO ROZWIAZANIE:');
writeln;
writeln('x = ',x:0:3);
writeln('y = ',y:0:3);
end;
end;
begin
Start;
writeln;
WczytajDaneRownania('Pierwsze rownanie: ax + by = c', 'a', 'b', 'c', a, b, c);
WczytajDanerownania('Drugie rownanie: dx + ey = f', 'd', 'e', 'f', d, e, f);
WyswietlUklad(a,b,c,d,e,f);
Writeln;
Wyznaczniki(a,b,c,d,e,f,wg,wx,wy);
Rozwiazania(x,y,wx,wy,wg,a,b,c,d,e,f);
Readln;
end.