[Pascal] Program nie kompiluje się


(Clank) #1

Witam,

Mam problem z bazą danych napisaną w Pascalu, mianowicie nie chce się po prostu skompilować i nie mam pomysłu, dlaczego. Błędy występują na linii zaczynającej procedurę.

baza_danych_hotel.pas<143.1> Error: Illegal expression

baza_danych_hotel.pas<143.11> Error: Constant expression expected

baza_danych_hotel.pas<143.11> Fatal: Syntax error, ":" expected but "identifier" found

baza_danych_hotel.pas<0> Fatal: Compilation aborted

Proszę o pomoc i z góry dzięki :slight_smile:


([alex]) #2

Ano brak formatowania ci doskwiera. Sformatuj kod po ludzku to sam zauważysz ten błąd.


(Pablo_Wawa) #3

Masz nie zamkniętą (brakuje END) procedurę sprawdz_wolne - przed procedurą z linii 143.


([alex]) #4

Pablo_Wawa , będziesz każdy taki błąd dla Clank'a szukać? Jak się nauczy formatować to sam sobie będzie takie błędy nie tyle wyłapywać ile przestanie popełniać.


(Clank) #5

Ok poprawiłem ale nic to nie dało:


(Pablo_Wawa) #6

Oj, to taki prezent na święta (po świętach) z ludzkiego odruchu serca.

Ale masz rację - poprawne formatowanie to podstawa i od tego należy zacząć.

-- Dodane 29.12.2012 (So) 15:20 --

Póki ładnie nie sformatujesz kodu, to już Ci nie pomogę. :stuck_out_tongue:

Przyjrzyj się linii 77 i 78 - tam masz jakiś begin i potem CASE, który należy zakończyć Iw Turbo Pascalu, tutaj nie mam pewności) również END - a Ty tego nie masz - masz tylko jeden END - może wywal ten begin przed CASE? (EDIT: to może być mylny trop - przez brak poprawnych wcięć = formatowania).


(adami) #7

I co z tego że się kompiluje jak to coś nie działa prawidłowo i nie będzie, są to jakieś fragmenty kodu czy co ?

Np w rezerwuj skąd ktoś ma wiedzieć żeby podać "ilosc_osob" itd.

http://mm.pl/~adamp74/66

Dygresja jeśli to twój kompilator to można go zaktualizować.


(Clank) #8

adami bo mam już w innej procedurze, żeby się pytało o te wartości (procedura 'sprawdz_wolne') i żeby dwa razy nie pytać o to samo, chyba w taki sposób zrobić nie można? Teraz mam inny problem. Program wysypuje się po przejściu w procedure "rezerwuj", kod błędu 201:

procedure rezerwuj;


        begin

                begin

                clrscr;

                assign (baza,'rezerwacje.dat');

                reset(baza);

                if ioresult<>0 then rewrite(baza);

                Seek(baza, FileSize(baza));

                writeln ('Podaj Nazwisko rezerwujacego: ');

                readln(rezerwacje[m].nazwisko);

                writeln ('Podaj ilosc dzieci: ');

                readln(rezerwacje[m].dzieci);

                readln(rezerwacje[m].ilosc_osob);

                readln(rezerwacje[m].ilosc_dni);

                readln(rezerwacje[m].miesiac);

                readln(rezerwacje[m].dzien);

                i:=i+1;

                write (baza,rezerwacje[m]);

                close(baza);

                end;

        end;

Nie wiem, czy to przez to, że plik 'rezerwacje' jest pusty i przez to wskaźnik nie może się ustawić na końcu tego pliku? Jeśli tak, to prosiłbym o dalsze wskazówki, jak to zastąpić. :slight_smile:


(Pablo_Wawa) #9

Plik rezerwacje.dat jest pusty, czy go nie ma i dopiero chcesz go założyć? Bo wtedy jak go nie ma, to program się wysypie w wierszu

reset(baza);

Poza tym masz błąd w tym wierszu - jak się korzysta z pliku z rekordami (file of ...), to należy używać konstrukcji

reset(baza,1);

Poza tym używasz do indeksowania tablicy rezerwacje zmiennej m , a w kodzie zwiększasz zmienną i.


(Clank) #10

Znowu trochę pozmieniałem i oto mój kod:

Mam problem z tą zmienną z rekordu, bo ogólnie inaczej nie umiem jej pobrać z pliku, a potrzebna mi jest do zapisywania jako wskaźnik a problem mam także z przeniesieniem jej do procedury (tak, aby po wyjściu z niej wartość bliczba.indeks była zwiększona o 1). Pablo_Wawa googl'ałem ale nic nie znalazłem podobnego do Twojego zapisu, chyba że źle szukam.


(Pablo_Wawa) #11

Z tym reset(baza,1) to coś mi się z czymś innym pomyliło - przepraszam.

Co to Twojego kodu, to:

  1. Dlaczego w wierszu

    procedure rezerwuj (var bliczba.indeks : real);

zmienna jest typu real , a nie integer? Przecież tablica rezerwacje jest indeksowana liczbami całkowitymi? 2. W procedurze decyzja masz wiersz

if a='tak' then rezerwuj;

ale przecież procedura rezerwuj wymaga podania zmiennej! Tak samo masz w głównym programie. 3. W procedurze odczytaj w wierszu

for i:=0 to bliczba.indeks do

używasz zmiennej bliczba.indeks , której nigdzie nie zadeklarowałeś lub nie przekazałeś jako parametr do procedury (zmiennej tej zresztą również używasz w głównym programie - a nie jest ona nigdzie zadeklarowana).

Może zmienną bliczba.indeks zadeklaruj globalnie?


(Clank) #12

No właśnie ta zmienna bliczba.indeks to rekord, pochodzi z pliku i na początku programu odczytuję ją, a jak chcę np. przypisać jakieś zmiennej a:=bliczba.indeks to też wyskakuje błąd, może dlatego że to plik txt, a ja chcę uzyskać zmienną typu int?

EDIT: Krótko mówiąc chodzi mi o to, żeby w jakikolwiek sposób móc odczytać tą wartość z rekordu z pliku 'liczba.txt'i przekazać ją do procedury


(Pablo_Wawa) #13

Sam masz deklarację

plik: file of bliczba;

gdzie bliczba to rekord, więc nie możesz na tym pliku (plik) wykonywać operacji tak jak na pliku tekstowym. Jaka to różnica? Plik tekstowy zawiera liczbę w postaci tekstowej, czyli takiej jak ją się pisze, a plik z rekordem typu byte czy integer zawiera wartość binarną takiej liczby (czyli wartość 0 - liczba zero - będzie w nim reprezentowana jako znak o kodzie 0 (albo dwa znaki, jeśli mowa o integer).

Operacje na plikach tekstowych robisz za pomocą funkcji read(ln) i write(ln), zaś na plikach z rekordami (file of ) poprzez funkcje BlockRead i BlockWrite.

Dane wczytujesz do programu jako tekstowe przez ReadLn, ale zapisujesz do pliku z rekordami poprzez BlockWrite.

http://haker.com.pl/threads/21463-Kurs-Pascal-VI-Rekordy-i-operacje-na-plikach


(Clank) #14

Ok więc zamieniłem po prostu na file of integer i wywala błąd (kod 100) przy próbie uruchomienia:

program hotel;

uses crt;


type rezerwacja = record

nazwisko:string[35];

ilosc_osob:integer;

dzieci:integer;

ilosc_dni:integer;

termin:string[30];

miesiac:integer;

dzien:integer;

end;


var rezerwacje:array[1..1000] of rezerwacja;

kalendarz_pokoj1:array[1..365] of integer;

kalendarz_pokoj2:array[1..365] of integer;

kalendarz_pokoj3:array[1..365] of integer;

kalendarz_pokoj4:array[1..365] of integer;

kalendarz_pokoj5:array[1..365] of integer;

ilosc_osob, miesiac, ilosc_dni, data, dzien:integer;

a:string[3];

szukaj:string[30];

opcja:string[1];

i,b,n,c,g:integer; m:byte;

plik: file of integer;

liczba:integer;

label wyjdz;

var baza: file of rezerwacja;



begin

clrscr;

        assign(plik,'liczba.dat');

        begin

        {$I-}

                reset(plik);

        {$I+}

        end;


                i:=0;

                reset(plik);

                seek(plik,i);

                read(plik,liczba);

                g:=liczba;

        repeat

        writeln('Witaj w programie zarzadzania rezerwacjami w hotelu. Wybierz jedna z dostepnych opcji.');

        writeln ('Dostepne opcje: rezerwuj (r), sprawdz czy sa wolne miejsca (s), odczytaj baze rezerwacji (o), zamknij program (x)');

        opcja:=readkey;

        case opcja of

        'r': rezerwuj (g);

        's': sprawdz_wolne;

        'o': odczytaj;

        end;

        until (opcja='x');

        assign(plik,'liczba.dat');

        i:=0;

        reset(plik);

        rewrite(plik);

        seek(plik,i);

        write(plik,g);

        close(plik);

end.

(Pablo_Wawa) #15

Po co masz pod koniec programu, po reset(plik), wywołanie rewrite(plik)? Przecież to kasuje wszystkie dane (zeruje go)?


(Clank) #16

Po to, aby kasował i zapisał do niego nową wartość (g). Wiem, że przekombinowane, ale inaczej nie umiem, póki co. :slight_smile:


(Pablo_Wawa) #17

Ale to można uzyskać prościej. Zamiast kodu

assign(plik,'liczba.dat');

        i:=0;

        reset(plik);

        rewrite(plik);

        seek(plik,i);

        write(plik,g);

        close(plik);

użyj tego:

assign(plik,'liczba.dat');

        rewrite(plik);

        write(plik,g);

        close(plik);

Reset otwiera plik do odczytu (i zapisu), a rewrite tylko do zapisu, jednocześnie kasując jego obecną zawartość.

EDIT: uwaga dotycząca BlockRead i BlockWrite dotyczy się plików nieokreślonego typu, a Ty masz rekordowe, więc używasz read i write.


(Clank) #18

Ale sam wspomniałeś, że procedura rewrite kasuje zawartość pliku, a ja chcę odczytać tą wartość, zapisać do zmiennej g i zamknąć ten plik, a później po zakończeniu edycji bazy zapisać zmienną g do tego pliku.

Tego pliku 'liczba.dat' nie mam już rekordowego tylko file of integer.


(Pablo_Wawa) #19

No dobrze, ale sam odczyt (na początku programu) robisz tak:

assign(plik,'liczba.dat');

reset(plik);

read(plik,g);

close(plik);

a zapis (na końcu programu) jak już Ci wyżej pokazałem (i reset oraz seek jest wtedy zbędny).

Poza tym Seek() używa się do przechodzenia po rekordach, a Ty w tym pliku chcesz trzymać tylko jedną wartość, po Reset() oraz ReWrite() wskaźnik pliku jest na początku i można użyć funkcji Read() lub Write() bez Seek().

No tak, ale to i tak oznacza, że w pliku są rekordy, a każdy zawiera 1 liczbę integer. Oczywiście możesz mieć w pliku 1 rekord i nic więcej. Rekordy w pliku to paczki tych samych danych, w Pascalu record definiuje typ/zmienną złożoną, która może (ale nie musi) być zapisana w pliku (z rekordami) - takie dwa znaczenia tego słowa.

-- Dodane 06.01.2013 (N) 22:43 --

Poza tym sugeruję używać w zmiennych (szczególnie globalnych) nazw bardziej określających ich zastosowanie w programie - np. u Ciebie zmienna g ma służyć do trzymania liczby pozycji (rekordów) w bazie (zgaduję), więc mógłbyś ją nazwać np. LiczbaRekordow i byłoby to czytelniejsze i dla Ciebie, i dla innych (program w ten sposób "sam się komentuje i opisuje").


(Pablo_Wawa) #20

@Description_1: akurat w tym przypadku to nie będzie miało żadnego znaczenia, bo ten program służy głównie do wprowadzania z klawiatury danych oraz ich zapisywania, odczytywania i przeglądania.