PDA

Zobacz pełną wersję : [Pascal] Błąd przy ponownym tworzeniu pliku



MacDada
20-08-07, 16:20
Witam!

Piszę wła¶nie program, którego ustawienia s± zapisywane do pliku i będzie możliwo¶ć wyboru jednego z nich.
Pliki tworzone s± na dwa sposoby:
1.) poprzez automat, który przekazuje nazwę do procedury tworz±cej plik: NewFile('JakasNazwaPliku');
2.) po podaniu nazwy przez użytkownika - wywołuje się: NewFile('!!spytaj o nazwe!!);

Kod mojej procedury wygl±da po czę¶ci tak:



PROCEDURE NewFile(nazwa:string);
var nowaNazwa :string;

Begin
If nazwa = '!!spytaj o nazwe!!' then
begin
ClrScr;
GoToXY(5,5); Write('Podaj nazwe pliku:');
GoToXY(25,5); Read(nowaNazwa);
end
Else nowaNazwa := nazwa;
End;

Gdzie tkwi problem?

Odpalam program i tworzę plik przy ręcznym podaniu nazwy. Wszystko gra. Jednak kiedy próbuję po raz drugi utworzyć plik to pojawia mi się bł±d:


Podaj nazwe pliku: Runtime error 5 at $000022D8
$000022D8 NEWFILE, line 186 of /Users/macdada/programowanie/EverydayToDos/EverydayToDos.pas
$000026A4 main, line 254 of /Users/macdada/programowanie/EverydayToDos/EverydayToDos.pas
$0000194C of EmptyPlaceHolderUnit.pas
$00001650 of EmptyPlaceHolderUnit.pas
Dodam, że używam FreePascalCompilera zintegrowanego z pakietem XCode na Mac OS X 10.4.10 (choć to chyba w tym przypadku nei ma znaczenia).

Linia 186:
Rewrite(nowyPlik);

Linia 254:
NewFile('spytaj o nazwe');

Pro¶ba o podanie nazwy pliku znajduje się w linii 178. Dowodzi to temu, że przy drugiej próbie utworzenia pliku jest ona pomijana i program od razu chce utworzyć plik ignoruj±c (?) sekcję If...

Ponowne uruchomienie programu pozwala nowy plik utworzyć lecz przy drugiej próbie znowu pojawia się bł±d.


DLACZEGO? CO MAM ZMIENIĆ, ŻEBY DZIAŁAŁO?
Bardzo proszę o pomoc - niestety nie znam nikogo "w realu" kto mógłby mi pomóc, choć pewnie wytłumaczyć o co chodzi byłoby łatwiej ;)

Pozdr.
Dawid, MacDada

stilgar
20-08-07, 20:31
wystarczyło wpisać w google "runtime error 5" aby sie dowiedzieć, że to oznacza, że taki plik/katalog już istnieje i nie można go utworzyć.

a ten if jest w ogóle brzydki, bo po pierwsze porównywanie stringów ma złożono¶ć liniow± (czyli chwilę trwa, tym dłużej im dłuższy string) a po drugie, może się zdarzyć, że dwa pozornie takie same stringi nie będ± takie same (zależy to od implementacji funkcji porównuj±cej, w niektórych językach programowania (np. w Javie) porównanie dwóch stringów da true, je¶li jeden i drugi string s± TYM SAMYM stringiem, więc raczej nie to, o co chodziło programi¶cie :)

dlatego ogólnie należy unikać porównań stringów, no, chyba, że piszesz parser, ale to już wyższa szkoła jazdy

imho lepiej jest ta funkcje napisac tak:



PROCEDURE NewFile(pytaj:boolean;var nazwa:string);

Begin
If pytaj then
begin
ClrScr;
GoToXY(5,5); Write('Podaj nazwe pliku:');
GoToXY(25,5); Read(nazwa);
end;
End;


wywołanie w stylu NewFile(true,jakisString)
dodatkowym plusem jest to, ze w jakisString zostanie zapisana nazwa jaka podal user (kluczem jest var w liscie parametrów)

RRybak
20-08-07, 21:09
Stilgar, ja wiem, że z Javą na początku trudno, gdy okazuje się, że porównuje na poziomie obiektów i klas, ale nie przesadzajmy - toż to zwykły Pascal :)

A teraz do MacDada. Rozwiązanie, które podał kolega powyżej jest o wiele bardziej profesjonalnym podejściem. To czy ma pytać o nazwę, gdy przekazujesz jakąś flagę, stan - najlepiej w takim przypadku za pomocą boolean (pytaj lub nie - i po kłopocie).
Po drugie - porĂłwnujesz napis z wykrzyknikami, a przekazujesz do procedury bez nich.
Po trzecie w Twoim rozwiązaniu nazwa pliku jest pamiętana tylko lokalnie wewnątrz procedury. Na zewnątrz - w programie - znika. I znowu - rozwiązanie Stiglara. Być może nie wiesz co to "referencja", a kolega nie napisał, więc śpieszę z wyjaśnieniem, że po kodzie:

nazwa_pliku:='; //tu sÄ… dwa apostrofy obok siebie
NewFile(true,nazwa_pliku);
w zmiennej "nazwa_pliku" będziesz miał nazwę, którą wprowadził użytkownik.

Cztery. Inna sprawa, że obie Wasze procedury są ździebko wyrwane z kontekstu i trochę bez sensu. W momencie gdy użytkownik nie poda nazwy, lub program ma się NIE zapytać:
a) w twojej wersji - nie stanie siÄ™ nic
b) w wersji Stiglara - pozostanie ta sama nazwa, która była - pod warunkiem, że jest ona (nazwa_pliku)zmienną globalną (a nie w procedurze).

Po piąte. Jeśli Cię nie pyta za drugim razem, to właśnie dlatego, że tracisz zawartość śmiesznej zmiennej pod tytułem "spytaj o nazwe" (o tym w punkcie wyżej) :)

To tyle wyjaśnień. Rozwiązanie masz w postach po części Stilgara i z wyjaśnieniem w moim. Spróbuj dalej sam :)