Základy práce se soubory
Zatřiďování souborů (merging)
 Tisk

Zatřiďování souborů (merging)


Dva soubory, seřazené podle stejného kritéria, se otevřou, z obou se přečte jedna komponenta. Ta z přečtených komponent, která má nižší hodnotu řadícího klíče, se zapisuje do pomocného výstupního souboru a ze souboru, ze kterého se četla, se přečte další komponenta. Pokud je jeden ze vstupních souborů prázdný, provede se kopírování zbytku druhého na výstupní, nakonec se provede přejmenování a zrušení.


Pro vytváření souboru se používají tyto standardní procedury a funkce:


assign, reset, rewrite, read, write, close, erase, rename.


Myšlenka zatřiďování je velmi jednoduchá. Předpokládejme, že máme dva vstupní vzestupně seřazené soubory, z nichž máme vytvořit jeden vzestupně seřazený soubor.

Evidentně chceme opakovaně provádět příkaz (zjednodušeně):


while not EOF(infile1) and not eof (infile2) do begin

    if element1.Key <= element2.Key then begin {pošli element1 na výstup }

        write(OutFile,element1);

        read (InFile1,element1)

    end

    else begin {pošli element2 na výstup }

        write(OutFile,element2);

        read (InFile2,element2)

    end;

end;


a to tak dlouho, dokud jeden vstupní soubor není vyčerpán. Pak kopírujeme druhý vstupní soubor na výstup až narazíme na jeho konec.


Vstupní soubory odpovídající animaci mají následující obsah:


03trojka *

04čtyřka *

08osmička *


a


05pětka   *

09devítka *


První dva znaky představují řadící klíč.


Výsledný soubor má tvar:


03trojka *

04čtyřka *

05pětka   *

08osmička *

09devítka *


Jako ukázka je uveden program, který provede sloučení obou souborů:


program merge;

{/**

*

* Projekt: PPVS     Autor: Kopeček     Datum: 20.4.2005

*

* Funkce: Slučování dvou souborů

*

*                       ***************

*        infile1.dat -->*             * --> outfile.dat

*                       * merge.exe *

*        infile2.dat -->*             *

*                       ***************

*

**/}

const

     KEY_LEN = 2;                // délka klíče

     USER_LEN = 8;                // délka uživatelské informace


     INFILE1 = 'INFILE1.DAT';    // 1. vstupní soubor

     INFILE2 = 'INFILE2.DAT';    // 2. vstupní soubor

     OUTFILE = 'OUTFILE.DAT';    // výstupní soubor


     DEBUG   = 1;                 // pro ladění a sledování běhu


type

     typ_stav = (NECTENO,PRECTENO,KONEC);

     typ_porov = (MENSI,ROVNO,VETSI);

     typ_klic = array[1..KEY_LEN] of char;

     typ_uziv = array[1..USER_LEN] of char;


     typ_soub = record

          klic : typ_klic;

          uziv : typ_uziv;

          znacik0: char;

             znacik1: char;

          znacik2: char;

     end;

var

   ind1,ind2:     typ_stav;

   rec1,rec2,

   strec1,strec2: typ_soub;


   isoub1,isoub2,osoub: file of typ_soub;


   // pomocné funkce a procedury


function porov(r,s:typ_klic): typ_porov;

begin

if r<s then porov := MENSI else

if r>s then porov := VETSI else

             porov := ROVNO;

end;


function ukazstav(s:typ_stav): string;

begin

case s of

NECTENO: ukazstav:= 'NECTENO';

PRECTENO: ukazstav:= 'PRECTENO';

KONEC:    ukazstav:= 'KONEC';

end;

end;


procedure tisksoub(s:typ_soub;var t:text);

var i:integer;

begin

     for i := 1 to KEY_LEN do write(t,s.klic[i]);

     for i := 1 to USER_LEN do write(t,s.uziv[i]);

     writeln(t);

end;


// Uvodni sekce - otevreni souboru


begin

assign(isoub1,INFILE1);

{$i-}

reset(isoub1);

{$i+}

if ioresult <> 0 then begin

    writeln('Nelze otevrit soubor ',INFILE1);

    exit;

end;


reset(isoub2,INFILE2);

{$i-}

reset(isoub2);

{$i+}

if ioresult <> 0 then begin

    writeln('Nelze otevrit soubor ',INFILE2);

    exit;

end;


assign(osoub,OUTFILE);

{$i-}

rewrite(osoub);

{$i+}

if ioresult <> 0 then begin

    writeln('Nelze otevrit soubor ',OUTFILE);

    exit;

end;


writeln;

writeln;

writeln('SLUCOVANI SOUBORU');

writeln;


ind1 := NECTENO;

ind2 := NECTENO;

strec1.klic := ' ';

strec2.klic := ' ';


// Hlavni cyklus - pokud nejsou oba vstupní soubory zpracovány


while (ind1 <> KONEC) or (ind2 <> KONEC) do begin


    if (DEBUG=1) then writeln('indikator ind1 = ', ukazstav(ind1),

                              ' indikator ind2 = ', ukazstav(ind2));


    if (ind1 = NECTENO) then begin       // načítání 1. souboru

        if eof(isoub1) then ind1 := KONEC

        else begin

             read(isoub1,rec1);

             ind1 := PRECTENO;

        end;

        if (ind1 = PRECTENO) and (DEBUG = 1) then begin

                writeln('Precten 1. soubor: ');

                tisksoub(rec1,output);

        end;

        if (ind1 = KONEC) and (DEBUG = 1) then

                writeln('Konec 1. souboru');


        if (ind1 = PRECTENO) and

              (porov(strec1.klic,rec1.klic) <> MENSI) then begin

                  writeln('Porusena posloupnost zaznamu v 1. souboru:');

            if (DEBUG = 1) then begin

                   tisksoub(strec1,output);

            end;

                  ind1 := KONEC;

        end;

        strec1 := rec1;

    end;

    if (ind2 = NECTENO) then begin       // načítání 2. souboru

        if eof(isoub2) then ind2 := KONEC

        else begin

             read(isoub2,rec2);

             ind2 := PRECTENO;

        end;

        if (ind2 = PRECTENO) and (DEBUG = 1) then begin

                writeln('Precten 2. soubor: ');

                tisksoub(rec2,output);

        end;

        if (ind2 = KONEC) and (DEBUG = 1) then

                writeln('Konec 2. souboru');


        if (ind2 = PRECTENO) and

              (porov(strec2.klic,rec2.klic) <> MENSI) then begin

                  writeln('Porusena posloupnost zaznamu v 2. souboru:');

               if (DEBUG = 1) then begin

                   tisksoub(strec2,output);

               end;

                  ind2 := KONEC;

        end;

        strec2 := rec2;

    end;


    // Ukončen 1. soubor - dokončí se zpracovaní 2. souboru - prosté kopírování


    if (ind1 = KONEC) and (ind2 <> KONEC) then begin

         if (DEBUG = 1) then

          writeln('Dokonceni zpracovani 2. souboru - klic: ',rec2.klic);

         write(osoub,rec2);

         ind2 := NECTENO;

    end;


    // Ukončen 2. soubor - dokončí se zpracovaní 1. souboru - prosté kopírování


    if (ind2 = KONEC) and (ind1 <> KONEC) then begin

         if (DEBUG = 1) then

           writeln('Dokonceni zpracovani 1. souboru - klic: ',rec1.klic);

         write(osoub,rec1);

         ind1 := NECTENO;

    end;



// Zpracovávají se oba soubory


    if (ind1 <> KONEC) and (ind2 <> KONEC) then begin

         if (DEBUG = 1) then begin

           writeln('Zpracovani obou souboru');

           writeln('Porovnava se 1. klic:', rec1.klic);

           writeln('Porovnava se 2. klic:', rec2.klic);

         end;

         case porov(rec1.klic,rec2.klic) of

              MENSI:begin

                    if (DEBUG = 1) then

                      writeln('Vlozeni z 1. souboru');

                      write(osoub,rec1);

                      ind1 := NECTENO;

                    end;

                ROVNO:begin

                      ind1 := NECTENO;

                      ind2 := NECTENO;

                      write(osoub,rec1);

                      write(osoub,rec2);

                      writeln('Zaznam se stejnym klicem');

                      tisksoub(rec1,output);

                    end;

                VETSI:begin

                    if (DEBUG = 1) then

                      writeln('Vlozeni z 2. souboru');

                      write(osoub,rec2);

                      ind2 := NECTENO;

                    end;

                end;


    end;      // Konec zpracování obou vstupních souborů

end;         // Konec hlavní smyčky


// Závěrečná sekce - uzavření všech souborů


close(isoub1);

close(isoub2);

close(osoub);

writeln;

writeln('KONEC SLUCOVANI SOUBORU');

end.



Průběh činnosti programu (ladící výstup) je následující:


SLUCOVANI SOUBORU


indikator ind1 = NECTENO indikator ind2 = NECTENO

Precten 1. soubor:

03trojka

Precten 2. soubor:

05pětka

Zpracovani obou souboru

Porovnava se 1. klic:03

Porovnava se 2. klic:05

Vlozeni z 1. souboru

indikator ind1 = NECTENO indikator ind2 = PRECTENO

Precten 1. soubor:

04čtyřka

Zpracovani obou souboru

Porovnava se 1. klic:04

Porovnava se 2. klic:05

Vlozeni z 1. souboru

indikator ind1 = NECTENO indikator ind2 = PRECTENO

Precten 1. soubor:

08osmička

Zpracovani obou souboru

Porovnava se 1. klic:08

Porovnava se 2. klic:05

Vlozeni z 2. souboru

indikator ind1 = PRECTENO indikator ind2 = NECTENO

Precten 2. soubor:

09devítka

Zpracovani obou souboru

Porovnava se 1. klic:08

Porovnava se 2. klic:09

Vlozeni z 1. souboru

indikator ind1 = NECTENO indikator ind2 = PRECTENO

Konec 1. souboru

Dokonceni zpracovani 2. souboru - klic: 09

indikator ind1 = KONEC indikator ind2 = NECTENO

Konec 2. souboru


KONEC SLUCOVANI SOUBORU