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