Nie było sensu dalej ciągnąć mojego poprzedniego tematu, ponieważ zrobiłby ię zbyt duży bałagan, więc zakładam nowy Robię bazę danych zawierającą informacje na temat rezerwacji w hotelu. To, czego potrzebuję, to między innymi plik prechowujący zmienną, która służy jako wskaźnik do następnego rekordu w pliku ‘rezerwacje.dat’ Po wykonaniu programu wyskakuje błąd exitcode 100. Poniżej zamieszczam problematyczne elementy programu:
A że tak powiem z innej strony - po co w ogóle trzymasz ten wskaźnik? Czy nie wystarczy po prostu odczytać wielkość pliku z danymi (‘rezerwacje.dat’) i na tej podstawie określić liczbę jego rekordów?
Patrzę na ten Twój program i wydaje mi się, że powinieneś wstrzymać się z kodowaniem do czasu zrobienia “porządków”. Pisanie programu nie polega na przerabianiu go tak, by kompilator przestał wywalać błędy, a potem by podczas jego pracy błędy nie występowały. Sugeruję, byś przygotował małą dokumentację swojego programu (brzmi groźnie), tj. żebyś opisał kluczowe zmienne do czego mają w programie służyć (np. jako komentarze obok ich definicji), żebyś opisał co ma robić każda z funkcji (i procedur), tj. co ma robić, na jakich danych operuje, co zmienia, itp. (to możesz też zrobić w formie komentarzy przed każdą funkcją/procedurą). To spowoduje, że uporządkujesz myślenie i będziesz mógł zająć się poprawą poszczególnych funkcji a potem będziesz w stanie złożyć z nich cały program.
EDIT: co do Twojego kodu i upartej walki z operacjami wejścia/wyjścia (I/O), to zajrzyj na tę stronę http://www.freepascal.org/docs-html/rtl/system/ioresult.html i zobacz, jak się poprawnie sprawdza, czy plik istnieje - kluczową sprawą jest w tym wypadku wyłączenie sprawdzania błędów I/O dyrektywą {$i-} a następnie jej włączenie {$i+} i sprawdzenie czy nie ma błędu.
Ok jestem coraz bliżej rozwiązania sprawy, więc może pojedynczo będę prosił o poprawienie procedur. A więc mam taki problem jak poniżej - czy da się coś zrobić, by w miejsce break’a wstawić coś, co przeskakiwałoby do końca tej procedury poza case’y (instrukcja goto też mi nie chciała działać, bo nie może jej być w tym miejscu)?
procedure sprawdz_wolne;
begin
clrscr;
writeln ('Podaj dzien rezerwacji:');
readln (dzien);
writeln ('Podaj miesiac rezerwacji:');
readln (miesiac);
writeln ('Podaj dlugosc trwania rezerwacji:');
readln (ilosc_dni);
CASE miesiac of
1: data:=dzien;
2: data:=31+dzien;
3: data:=31+28+dzien;
4: data:=2*31+28+dzien;
5: data:=2*31+30+28+dzien;
6: data:=3*31+30+28+dzien;
7: data:=3*31+2*30+28+dzien;
8: data:=4*31+2*30+28+dzien;
9: data:=5*31+2*30+28+dzien;
10: data:=5*31+3*30+28+dzien;
11: data:=6*31+3*30+28+dzien;
12: data:=6*31+4*30+28+dzien;
end;
writeln ('Podaj ilosc osob');
readln (ilosc_osob);
CASE ilosc_osob of
1: begin
assign(pokoj1, 'pokoj1.dat');
reset(pokoj1);
for i:=1 to ilosc_dni do
begin
if (kalendarz_pokoj1[data]=1) then
break
else
data:=data+1;
end;
data:=data-ilosc_dni;
for i:=1 to ilosc_dni do
begin
kalendarz_pokoj1[data]:=1;
write(pokoj1, kalendarz_pokoj1[data]);
data:=data+1;
end;
close(pokoj1);
decyzja;
end;
2: begin
assign(pokoj2, 'pokoj2.dat');
reset(pokoj2);
for i:=1 to ilosc_dni do
begin
if (kalendarz_pokoj2[data]=1) then
break
else data:=data+1;
end;
data:=data-ilosc_dni;
for i:=1 to ilosc_dni do
begin
kalendarz_pokoj2[data]:=1;
write(pokoj2, kalendarz_pokoj2[data]);
data:=data+1;
end;
close(pokoj2);
decyzja;
end;
3: begin
assign(pokoj3, 'pokoj3.dat');
reset(pokoj3);
for i:=1 to ilosc_dni do
begin
if (kalendarz_pokoj3[data]=1) then
break
else data:=data+1;
end;
data:=data-ilosc_dni;
for i:=1 to ilosc_dni do
begin
kalendarz_pokoj1[data]:=1;
write(pokoj3, kalendarz_pokoj3[data]);
data:=data+1;
end;
close(pokoj3);
decyzja;
end;
4: begin
assign(pokoj4, 'pokoj4.dat');
reset(pokoj4);
for i:=1 to ilosc_dni do
begin
if (kalendarz_pokoj4[data]=1) then
break
else data:=data+1;
end;
data:=data-ilosc_dni;
for i:=1 to ilosc_dni do
begin
kalendarz_pokoj1[data]:=1;
write(pokoj4, kalendarz_pokoj4[data]);
data:=data+1;
end;
close(pokoj4);
decyzja;
end;
end;
writeln('Brak wolnych miejsc/odrzucono propozycje rezerwacji');
readln;
end;
Co do powyższego - nie wziąłeś pod uwagę roku 2016 - jest to rok przestępny (luty ma 29 dni) - a także lat następnych - takie błędy wyjdą za kilka lat, kiedy program się rozrośnie i będzie ■■■■. http://pl.wikipedia.org/wiki/Rok_przest%C4%99pny
Jak się tak popatrzy na Twój kod, to widać w nim powielone te same instrukcje, a to można ładnie ogarnąć jak się zastosuje np. tablice:
zarówno dla nazw plików:
const plik.pokoje: array[1…4] of string=(‘pokoj1.dat’,‘pokoj2.dat’,‘pokoj3.dat’,‘pokoj4.dat’);
lub nawet jako użycie konstrukcji ‘pokoj’+ilosc_osob+’.dat’ i potem możesz użyć np. assign(pokoj,plik.pokoje[ilosc_osob]); - jak i kalendarza:
var kalendarz_pokoj[1..4][1..366] of boolean/byte;
i używanie konstrukcji
if (kalendarz_pokoj[ilosc_osob][data]=1) then
Co Ci skróci 4-krotnie cały kod i zrobi go czytelniejszym oraz bardziej odpornym na błędy (bo jak będziesz coś zmieniał w jednej części (case), to musisz to teraz robić w pozostałych trzech. A kiedy będziesz chciał rozszerzyć program do obsługi pokoi 5-osobowych, wtedy wystarczy zmienić stałe w deklaracjach tablic (przy okazji warto zdefiniować sobie stałą
const MAX_LICZBA_OSOB = 4;
i używać jej w programie i definicjach zakresu tablic, a kod pisać tak, jakby chodziło o pokój n-osobowy, gdzie n jest od 1 do MAX_LICZBA_OSOB, przez co obsłużysz wszystkie możliwości za jednym zamachem.
P.S. I pisz tak, żeby nie trzeba było korzystać z instrukcji goto!
Dzięki Pablo, już wszystko ogarnąłem tylko jeszcze jednej rzeczy nie zawarłem w swoim projekcie (typów proceduralnych), o których napiszę w następnym temacie :x