Wstęp do programowania/Pliki/Ćwiczenia: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Niech sie mury pna do gory!
Usuwanie komentarzy w Pascalu i zmiana kolejnosci
Linia 10: Linia 10:


==Zadanie 1==
==Zadanie 1==
Napisz funkcję sprawdzającą, czy dwa pliki tekstowe o podanych nazwach mają tę samą liczbę wierszy.
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Wskazówka 1'''
<div class="mw-collapsible-content" style="display:none">
Najprostsze rozwiązanie polega na policzeniu liczby linii w jednym pliku, w drugim pliku i potem porównanie tych liczb.
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Rozwiązanie 1'''
<div class="mw-collapsible-content" style="display:none">
'''function''' LiczLinie(f:Text):integer;
// f otwarty plik tekstowy
'''var''' c:character;
  l:integer;
'''begin'''
  l:=0;
  '''while''' '''not''' eof(f) '''do''' '''begin'''
    '''while''' '''not''' eoln(f) '''do'''
      read(f,c);
    readln(f);
    l:=l+1;
  '''end''';
  LiczLinie:=l;
'''end'''; // LiczLinie
'''function''' RownoLinijne(s1,s2:string):boolean;
'''var''' f1,f2:Text;
'''begin''' // RownoLinijne
  assign(f1,s1);
  assign(f2,s2);
  reset(f1);
  reset(f2);
  RownoLinijne:=LiczLinie(f1)=LiczLinie(f2);
  close(f1);
  close(f2);
'''end'''; // RownoLinijne
Zaletą tego rozwiązania jest możliwość powtórnego wykorzystania funkcji LiczLinie do innych celów, a wadą konieczność czytania obu plików, nawet gdy jeden jest bardzo mały, a drugi bardzo duży.
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Wskazówka 2'''
<div class="mw-collapsible-content" style="display:none">
Można też wczytywać po jednej linii z każdego pliku, aż któryś z nich się nie skończy.
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Rozwiązanie 2'''
<div class="mw-collapsible-content" style="display:none">
'''function''' RownoLinijne(s1,s2:string):boolean;
'''var''' f1,f2:Text;
  c:character;
'''begin'''
  assign(f1,s1);
  assign(f2,s2);
  reset(f1);
  reset(f2);
  '''while''' '''not''' (eof(f1) '''or''' eof(f2)) '''do''' '''begin'''
    '''while''' '''not''' eoln(f1) '''do'''
      read(f1,c);
    readln(f1);
    '''while''' '''not''' eoln(f2) '''do'''
      read(f2,c);
    readln(f2);
  '''end''';
  RownoLinijne:=eof(f1) '''and''' eof(f2);
  close(f1);
  close(f2);
'''end'''; // RownoLinijne
Czytamy po jednej linii z każdego pliku, aż co najmniej jeden z nich się skończy. Jeśli okazało się, że skończyły się oba naraz - mają tę samą liczbę linii. Jeśli skończył się tylko jeden - ten drugi musi być dłuższy.
</div>
</div>
==Zadanie 2==


Napisz procedurę, która skopiuje plik tekstowy f na g, modyfikując go w następujący sposób: bezpośrednio po każdym słowie należy wstawić koniec wiersza, a nowy wiersz rozpocząć od nowego słowa (spacje i puste wiersze należy pomijać).
Napisz procedurę, która skopiuje plik tekstowy f na g, modyfikując go w następujący sposób: bezpośrednio po każdym słowie należy wstawić koniec wiersza, a nowy wiersz rozpocząć od nowego słowa (spacje i puste wiersze należy pomijać).
Linia 69: Linia 149:
'''Rozwiązanie 2'''  
'''Rozwiązanie 2'''  
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
  procedure Kopiuj(var f,g:Text);
  '''procedure''' Kopiuj('''var''' f,g:Text);
  type pozycja=(odstep,slowo);
  '''type''' pozycja=(odstep,slowo);
  var stan:pozycja;
  '''var''' stan:pozycja;
   c:character;
   c:character;
  begin
  '''begin'''
   reset(f);
   reset(f);
   rewrite(g);
   rewrite(g);
   stan:=odstep;
   stan:=odstep;
   while not eof(f) do begin
   '''while''' '''not''' eof(f) '''do''' '''begin'''
     if eoln(f) then begin
     '''if''' eoln(f) '''then''' '''begin'''
       readln(f);
       readln(f);      
       if stan=slowo then begin
       '''if''' stan=slowo '''then''' '''begin'''
         writeln(g);
         writeln(g);
stan:=odstep;
        stan:=odstep;
       end;
       '''end''';
     end
     '''end'''
     else begin // not eoln(f)
     '''else''' '''begin''' // '''not''' eoln(f)
       read(f,c);
       read(f,c);
       if c=' ' then begin
       '''if''' c=' ' '''then''' '''begin'''
         if stan=slowo then begin
         '''if''' stan=slowo '''then''' '''begin'''
  writeln(g);
          writeln(g);
  stan:=odstep
          stan:=odstep
end
        '''end'''
       end
       '''end'''
       else begin // c<>' '
       '''else''' '''begin''' // c<>' '
         write(g,c);
         write(g,c);
         if stan=przerwa then  
         '''if''' stan=przerwa '''then'''
  stan:=slowo
          stan:=slowo
       end
       '''end'''
     end
     '''end'''
   end;
   '''end''';
   close(f);
   close(f);
   close(g);
   close(g);
  end; // Kopiuj
  '''end'''; // Kopiuj


W tym rozwiązaniu jest tylko jedna pętla while przetwarzająca poszczególne ''zdarzenia'' w pliku f. Zdarzeniem może być albo koniec linii, albo wczytanie znaku. Za każdym razem wykonywane są odpowiednie operacje na plikach i zmieniany jest stan.
W tym rozwiązaniu jest tylko jedna pętla while przetwarzająca poszczególne ''zdarzenia'' w pliku f. Zdarzeniem może być albo koniec linii, albo wczytanie znaku. Za każdym razem wykonywane są odpowiednie operacje na plikach i zmieniany jest stan.
Linia 108: Linia 188:
</div>
</div>


==Zadanie 2==
==Zadanie 3 (Usuwanie komentarzy)==
 
Napisz procedurę usuwającą komentarze z pliku tekstowego zawierającego program w Pascalu.


Napisz funkcję sprawdzającą, czy dwa pliki tekstowe o podanych nazwach mają tę samą liczbę wierszy.
Komentarze oznaczone są przez { ... } lub (* ... *). Należy przy tym uważać by nie usuwać komentarzy znajdujących się wewnątrz napisów (oznaczonych przez ' ... ')


<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Wskazówka 1'''  
'''Wskazówka 1'''  
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
Najprostsze rozwiązanie polega na policzeniu liczby linii w jednym pliku, w drugim pliku i potem porównanie tych liczb.
Tak jak w Zadaniu 2, procedura powinna być sterowana stanem, oznaczającym tę część wiedzy zdobytej podczas przetwarzania dotychczasowego fragmentu pliku, od której zależy reakcja na wczytanie poszczególnych znaków: czy jesteśmy wewnątrz komentarza, napisu, po przeczytaniu nawiasu oswierającego itp.
</div>
</div>
</div>
</div>
Linia 122: Linia 204:
'''Rozwiązanie 1'''  
'''Rozwiązanie 1'''  
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
  '''function''' LiczLinie(f:Text):integer;
  '''procedure''' Komentarze(wej,wyj:string);
  // f otwarty plik tekstowy
  '''type''' stany=(nic,kom1,naw_otw,kom2,kom2_gw,napis);
  '''var''' c:character;
  '''var''' f,g:Text;
   l:integer;
  stan:stany;
   c:character;
  '''begin'''
  '''begin'''
   l:=0;
   assign(f,wej);
  assign(g,wyj);
  reset(f);
  rewrite(g);
  stan:=nic;
   '''while''' '''not''' eof(f) '''do''' '''begin'''
   '''while''' '''not''' eof(f) '''do''' '''begin'''
     '''while''' '''not''' eoln(f) '''do'''
     '''if''' '''not''' eoln(f) '''then'''
       read(f,c);
       read(f,c);    
    readln(f);
      '''case''' stan '''of'''
    l:=l+1;
        nic:
  '''end''';
          '''case''' c '''of'''
  LiczLinie:=l;
            '(': stan:=naw_otw;
'''end'''; // LiczLinie
            '&#39;&#39;': '''begin''' stan:=napis; write(g,c) '''end''';
 
            '''else''' write(g,c);
'''function''' RownoLinijne(s1,s2:string):boolean;
          '''end'''
'''var''' f1,f2:Text;
        naw_otw: 
'''begin''' // RownoLinijne
          '''case''' c '''of'''
   assign(f1,s1);
            '*': stan:=kom2;
  assign(f2,s2);
            '&#39;&#39;': '''begin''' stan:=napis; write(g,'(&#39;&#39;'); '''end''';
  reset(f1);
            '{': '''begin''' stan:=kom1; write(g,'({'); '''end'''
  reset(f2);
            '''else''' '''begin''' stan:=nic; write(g,'(',c); '''end'''
  RownoLinijne:=LiczLinie(f1)=LiczLinie(f2);
          '''end'''
   close(f1);
        kom2:
   close(f2);
          '''case''' c '''of'''
  '''end'''; // RownoLinijne
            '*': stan:=kom2_gw;
 
          '''end'''   
Zaletą tego rozwiązania jest możliwość powtórnego wykorzystania funkcji LiczLinie do innych celów, a wadą konieczność czytania obu plików, nawet gdy jeden jest bardzo mały, a drugi bardzo duży.
        kom2_gw:
</div>
          '''case''' c '''of'''
</div>
            ')': stan:=nic;
            '*': stan:=kom2_gw;
            '''else''' stan:=kom2
          '''end'''  
        kom1:
          '''case''' c '''of'''
            '}': stan:=nic
          '''end'''    
        napis:
          '''case''' c '''of'''
            '&#39;&#39;': '''begin''' stan:=nic; write(g,c); '''end'''
            '''else''' write(g,c);
          '''end'''
      '''end'''
    '''end'''
    '''else''' '''begin''' // eoln(f)
      readln(f);
      '''case''' stan '''of'''
        nic: writeln(g);
        naw_otw: '''begin''' stan:=nic; writeln(g,'('); '''end''';
        kom2: // nic
        kom2_gw: stan:=kom2;
        kom1: // nic
        napis: writeln(g)
      '''end'''
    '''end'''
  '''end'''
   close(f);
   close(g);
  '''end'''


<div class="mw-collapsible mw-made=collapsible mw-collapsed">
Każdy obrót pętli while w powyższej procedurze przetwarza jedno ''zdarzenie'' (znak lub koniec wiersza) z pliku wejściowego. W zależności od stanu i znaku (zdarzenia) zmieniany jest odpowiednio stan i zapisywany odpowiedni napis do pliku wyjściowego.
'''Wskazówka 2'''
<div class="mw-collapsible-content" style="display:none">
Można też wczytywać po jednej linii z każdego pliku, aż któryś z nich się nie skończy.
</div>
</div>


<div class="mw-collapsible mw-made=collapsible mw-collapsed">
Można sobie wyobrazić zawartość pętli while w powyższej procedurze jako dwuwymiarową tabelkę, której kolumny indeksowane są stanami, wiersze - rodzajem zdarzenia wejściowego, a w każdej komórce jest informacja jaki ma być nowy stan i co wypisać do pliku g.
'''Rozwiązanie 2'''
<div class="mw-collapsible-content" style="display:none">
'''function''' RownoLinijne(s1,s2:string):boolean;
'''var''' f1,f2:Text;
  c:character;
'''begin'''
  assign(f1,s1);
  assign(f2,s2);
  reset(f1);
  reset(f2);
  '''while''' '''not''' (eof(f1) '''or''' eof(f2)) '''do''' '''begin'''
    '''while''' '''not''' eoln(f1) '''do'''
      read(f1,c);
    readln(f1);
    '''while''' '''not''' eoln(f2) '''do'''
      read(f2,c);
    readln(f2);
  '''end''';
  RownoLinijne:=eof(f1) '''and''' eof(f2);
  close(f1);
  close(f2);
'''end'''; // RownoLinijne
 
Czytamy po jednej linii z każdego pliku, co najmniej jeden z nich się skończy. Jeśli okazało się, że skończyły się oba naraz - mają tę samą liczbę linii. Jeśli skończył się tylko jeden - ten drugi musi być dłuższy.
</div>
</div>
 
==Zadanie 3 (Usuwanie komentarzy)==
 
Napisz procedurę usuwającą komentarze z pliku tekstowego zawierającego program w Pascalu.
 
Komentarze oznaczone są przez { ... } lub (* ... *). Należy przy tym uważać by nie usuwać komentarzy znajdujących się wewnątrz napisów (oznaczonych przez ' ... ')
 
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Wskazówka 1'''
<div class="mw-collapsible-content" style="display:none">
Tak jak w Zadaniu 1, procedura powinna być sterowana stanem oznaczającym całą przeszłą wiedzę, od której zależy reakcje na wczytanie poszczególnych znaków: czy jesteśmy wewnątrz komentarza, napisu, po przeczytaniu nawiasu oswierającego itp.
</div>
</div>
</div>
</div>

Wersja z 12:16, 20 lip 2006

To są zadania na pliki.

Pokaż rozwiązania __SHOWALL__
Ukryj rozwiązania __HIDEALL__

W poniższych zadaniach zakładamy, że eof(f) implikuje eoln(f).


Zadanie 1

Napisz funkcję sprawdzającą, czy dwa pliki tekstowe o podanych nazwach mają tę samą liczbę wierszy.

Wskazówka 1

Rozwiązanie 1

Wskazówka 2

Rozwiązanie 2

Zadanie 2

Napisz procedurę, która skopiuje plik tekstowy f na g, modyfikując go w następujący sposób: bezpośrednio po każdym słowie należy wstawić koniec wiersza, a nowy wiersz rozpocząć od nowego słowa (spacje i puste wiersze należy pomijać).

Słowem (w tym zadaniu) nazywamy dowolny maksymalny spójny ciąg znaków niezawierający spacji i znaków końca wiersza. Nie zakładamy niczego o długości słów.

Wskazówka 1

Rozwiązanie 1

Rozwiązanie 2

Zadanie 3 (Usuwanie komentarzy)

Napisz procedurę usuwającą komentarze z pliku tekstowego zawierającego program w Pascalu.

Komentarze oznaczone są przez { ... } lub (* ... *). Należy przy tym uważać by nie usuwać komentarzy znajdujących się wewnątrz napisów (oznaczonych przez ' ... ')

Wskazówka 1

Rozwiązanie 1