Megoldások



"Némelyik böngészőből másolva, a CB hibát ír ki a példára - ez a másolás közben keletkezik - ilyenkor kézzel kell átgépelni a programokat. Az átgépeléskor célszerű a Space nyomkodása helyett, a Tab billentyűt használni - erre a CB direkt fel van készítve." - A legelső C program elkészítése c. fejezetből

  1. Bevezetés
    1. A legelső C program elkészítése
    2. A számítógép alkatrészei
  2. A programozás alapjai
    1. Adattárolás kettes számrendszerben
    2. Műveletek kettes számrendszerben
    3. A program mint adathalmaz
  3. Előrehaladottabb programozás
    1. Egyedi típusok definiálása
    2. A program részekre bontása
    3. Egyszerű dinamikus adatszerkezetek
    4. Karakterláncokkal végzett műveletek
    5. Egyszerű rendezési algoritmusok
  4. Az egyszerű C/C++ programok rejtelmei
    1. A program fő függvénye, és a rendszer közötti kapcsolat
    2. Hibakeresési módszerek
    3. Összetett dinamikus adatszerkezetek
    4. Fájlkezelés, adattárolás
    5. Egyszerű síkbeli grafikai alkalmazás

Ia, A legelső C program elkészítése

  1. pl. Borland C++, Code::Blocks, C++ Builder
  2. link
  3. Győződjünk meg hogy az IDE megbízható helyről lett-e letöltve, és ha igen - akkor ki kell kapcsolni a vírusirtót. A riasztás azért lehet téves, mert sok esetben a vírusok is előállíthatnak más programokat.
  4. pl. A változó segítségével a program adatokat jegyezhet meg. Elemei a típus, a név, és az érték.
  5. Csak az angol ABC betűiből, aláhúzás jelekből, és számokból állhat - de a szám nem állhat az elején. pl. teto, szam2, _2pac
  6. pl. int szam;
  7. pl. float valos = 3.14;
  8. pl. char ca = 'a', cb = 'b', cc = 'c';
  9. Nem kivitelezhető, mert a változó neve rossz. (szándékosan)
  10. #include <stdio.h>

    int main()
    {
       printf("Az alma kek.");
       return
    0;
    }
  11. Nincs benne hiba, de hányadék a rendezése. (szándékosan)
  12. stio.h helyett stdio.h
    a prinf helyett printf
    a prinf sorának a végén hiányzik a pontosvessző
  13. link
  14. link
  15. %s jellel
  16. Ez egy
    szépen tagolt
    'szöveg'.
  17. Ez egy \\\ szépen    tagolt
    'szöveg'.
  18. Ez egy   
        "szépen" tagolt 'szöveg'.
  19. Ez egy
    \
        "szépen" tagolt
    'szöveg'.
  20. Hangjelzést/sípolást ad ki a gép a hatására.
  21. pl. int i; scanf("%d", &i);
  22. link
  23. link
  24. link
  25. link
  26. link
  27. link
  28. link
  29. link

Ib, A számítógép alkatrészei

  1. A számítógép agya, programokat futtat, utasításokat hajt végre, számol.
  2. Azt a frekvenciát ami megadja hogy másodpercenként hány utasítást képes végrehajtani.
  3. Azt hogy hány teljes értékű alprocesszorra osztható.
  4. Azt hogy hány bittel képes egyidejűleg, egy műveletben számolni.
  5. Az a nagyon gyors memória, amelyben ideiglenesen a műveletekhez megjegyzi a processzor az adatokat.
  6. Egy alprocesszor számolási, matematikai része.
  7. Egy alprocesszor utasításvégrehajtó, vezérlő része.
  8. Az a gyors memória, amelyben ideiglenesen a műveletekhez megjegyzi a processzor az egyéb segédadatokat, illetve azokat amikre később szükség lesz.
  9. Nagy mennyiségű adat ideiglenes tárolására.
  10. Az a folyamat, melynek során a processzor, a fizikai memória minden egyes byteját egy-egy sorszámmal látja el.
  11. Egy olyan sorszám ami a címzés során kioszt a processzor, általa lehet "navigálni" a memóriában.
  12. Partíciós tábla > Partíció > Fájlrendszer > Mappák > Fájlok
  13. Az a név, amelynek során a fájlrendszerből kikereshető egy adott fájl.
  14. A teljes elérési út mindig tartalmazza a mappát, és a meghajtót is - míg a fájlnév nem.
  15. Olyan fájlnév, melynek a név része 8 karakterből, kiterjesztése 3 karakterből állhat (pl. AUTOEXEC.BAT).
  16. Hogy ne maradjon nyitva a fájlhoz tartozó hozzáférési kulcs - ennek hiányában a következő program nem fog tudni hozzáférni a fájlhoz.
  17. Egy olyan saját memóriával rendelkező processzor, ami kifejezetten grafikai számításokat tud végezni, és előállítja a képet a monitor számára.
  18. memória, sávszélesség, magok száma, órajel
  19. DirectX, OpenGL
  20. Ellenőrzi a gép alapvető hardvereit a bekapcsolás során, majd megpróbálja betölteni az operációs rendszer. Segítségével szabályozhatóak az órajelek, a hardveres erőforrások, és az egyes villamos feszültségek is.

IIa, Adattárolás kettes számrendszerben

  1. Mert a 32 bit, több variációt állíthat elő, mint a 8.
  2. 1101101101011010, 155532, 0xDB5A
  3. 2 391
  4. 163
  5. 207
  6. pl.:
    • unsigned short short int
    • short short int
    • unsigned short int
    • short int
    • unsigned long int
    • long int
    • unsigned short int
    • unsigned long int
  7. 1, 1, 2, 2, 4, 4, 2, 4 byte-ot
  8. Igen, de korlátozott pontossággal.
  9. Az első hamist, a többi mind igaz.
  10. Nem.
  11. Mert hivatkozhatunk olyan címre, amihez nincs hozzáférésünk (vagy a NULL címre), amitől összeomlik a program.
  12. Egy szándékosan érvénytelen memóriacím, ami a nulla címet jelképezni.
  13. ANSI, ASCII, Unicode, stb...
  14. 852-es kódlappal
  15. ASCII vagy ANSI
  16. 852-es kódlap vagy ANSI
  17. Unicode
  18. (12+1)*1 = 13 byte, (12+1)*1 = 13 byte, (12+1)*2 = 26 byte
  19. 59 betűs
  20. Az eltelt másodperceket jelöli, 1970 január 1.-je, 0:00 óta.
  21. pl.:
    • short short int _8beesz = -2;
    • long int x4eesz;
    • char x1k;
    • unsigned long long int _64benesz = 15;
    • short int logikai1 = 1;
    • float _furik =  3.14f;
    • a névben nem lehet ékezetes betű
    • unsigned long long int _5abc;
    • long int logikai;
    • double __8_f;
    • a név nem kezdődhet számmal
    • wchat_t 2byxx[58];
    • long double atompontos;
  22. ANSI
  23. link

IIb, Műveletek kettes számrendszerben

  1. Igaz.
  2. Igaz.
  3. Mert az && jelnek nagyobb a műveleti sorrendje (precedenciája) mint a || jelnek.
  4. pl.:
    • -2
    • - 1
    • -5.00f
    • nullával nem lehet osztani
  5. pl.:
    1. A=3, B=1 C=-1 D=5.00f
    2. A=3, B=-4, C=-1 D=5.00f
    3. A=-8 B=-1 C=0 D=5.00f
    4. A=1 B=0 C=0 D=-5.00f
  6.  pl.:
    1. igaz
    2. igaz
    3. igaz
    4. igaz
    5. hamis
    6. hamis
  7. pl.:
    1. 8
    2. 0
    3. 3
    4. 0
    5. 2
    6. 253
  8. pl.
    1. 6.00f
    2. 1.00f
    3. -1
  9. pl.
    1. eredmény=4, A=2, B=1, C=-1, D=5.00f
  10. int A = 1, B = 2, C = 3;

    C += A++, B += ++A, C - A * B;
  11. link, link
  12. link, link
  13. link, link
  14. link, link
  15. link, link
  16. link, link
  17. link, link
  18. link, link
  19. link, link
  20. link, link, link
  21. link, link, link

IIc, A program mint adathalmaz

  1. Assembly
  2. A gépi kód a processzor számára érthető, az alacsony szintű programnyelv már nekünk is - de gépközeli, emiatt csak egy vason fut el - a magas szintű pedig gépfüggetlen programot állít elő, és kis angoltudással folyékonyan olvasható.
  3. Az operációs rendszer védi az erőforrásokat, és próbálja egyenletesen elosztani a programok között.
  4. Mert a védett mód nem engedi hogy arra a területre írjon a program - megvédi a gépet a memóriahibáktól.
  5. GCC, LD, GDB
  6. GCC
  7. saját készítésű
  8. int i, j;

    scanf("%d", &i);

    if (i > 6)
        j = i;
  9. int i, j;

    scanf("%d", &i);

    if (i > 6)
        j = i;
    else
        j = -i;

  10. int i, j;

    scanf("%d", &i);

    if (i > 0)
        j = 1;
    else if (i == 0)
        j = 0;
    else
        j = -1;
  11. int i, j;

    scanf("%d", &i);

    switch(i)
    {
      case 1:
      case 2:
            j = i + 2;
            break;
      case 4:
      case -4:
            k = i - 2;
            break;
    }
  12. int i, j;

    scanf("%d", &i);

    j = i > 0 ? i : -i;
  13. Azt adja meg, mi legyen akkor ha egyik eset sem teljesül.
  14. Olyan ismétlődő utasítássorozatot, amely addig fut le, amíg egy adott feltétel fennáll.
  15. link
  16. link
  17. link
  18. Megszakítja az adott ciklust.
  19. Kihagyja az adott utasítássorozat hátralévő részét, és ugrik a következő ciklusszakaszra.
  20. link, link
  21. link, link, link
  22. link, link, link
  23. link, link, link, link, link, link, link, link, link, link, link
  24. link
  25. link
  26. link, link, link, link, link
  27. link

IIIa, Egyedi típusok definiálása

  1. Sok adott típusból álló változó egy név alatt, amelyben indexeléssel (sorszámozással) érhető el a kívánt elem.
  2. Azt hogy a tömb változói egymás után helyezkednek el a memóriában - ennek következménye, hogy egy tetszőleges elem címe előállítható egy szorzással, és egy összeadással ha a kezdőcím adott - a tömb ekvivalens lesz a kezdőcímével - a C/C++ nyelvben a memóriacím és a tömb összekeverhető.
  3. int tomb[60];
    *(tomb + 11) = 14;
    tomb[11] = 14;
  4. Egy olyan adathalmazt, ahol az egyes elemek n sorba, és m oszlopba vannak rendezve - ezáltal egy téglalap alakú elrendezést kapunk.
  5. float matrix[5][3];
    matrix[4][2] = 12;

    5. sor, 3. oszlop
  6. Azt hogyha egyes irányokban nagyobb számot adunk meg, mint az abba az irányba vonatkozó korlát - ha a másik irányban lévő szám megfelelő, elérhetünk egy elemet a szabályostól eltérő módon is. Ezt az elérést hívjuk túlindexelésnek.
    float matrix[5][3];
    matrix[4][2] == matrix[3][5];
  7. char t[5][5][5] = {'\0'};
    t[15] == t[0][3][0];
  8. int t[1][2][3][4][5][6];
    1*2*3*4*5*6 = 6! = 720
  9. Egy teljesen új típusú változó felvételéhez, a programnyelvnek tudnia kell, hogyan tudja létrehozni azt. A típusdefiníció minden egyes típusra megadja, ezeket a létrehozáshoz szükséges információkat.
  10. typedef struct {
        int Field1, Field2;
        char Field3;
        unsigned int Field4;
        char Field5[20];
    } TMyStruct, *PMyStruct;
  11. A struktúra egy adott összetevőjét, ezek általában változók.
  12. Egy olyan mutató, aminek az alapja egy struktúra.
  13. Hagyományos struktúrák esetében a pont a mezők elérése használható, míg struktúramutató esetében erre a nyíl operátor használható.
    int i = strukt.mezo1;
    *(strukt_mutato).mezo1 == strukt_mutato->mezo1;
  14. pl. sizeof(TMyStruct), de megadható egy olyan változó is, aminek TMyStruct a típusa. Struktúramutató nem használható erre a célra.
  15. A tömb elemei mindig azonos típusúak - és számozottak, míg a másik két esetben különböznek - és névvel érhetőek el. A struktúra és a union egyik különbsége hogy az utóbbi sok különböző típusú mező esetén kevesebb memóriát fog foglalni mint elődje.
  16. link
  17. Az enumeráció egy egyedi sorszámozott típus, amely azért jobb mint egy halom konstans, mert így közvetlenül alkalmazhatóak rajta a sorszámozott típusra vonatkozó operátorok (pl. ++, --, stb.), és a lehetséges értékek egy helyen vannak.
  18. Igen.
    typedef int TMyArray[50];
    typedef float TRealMatrix[70][70];
  19. typedef unsigned short short int byte;
  20. typedef enum {
        meItem1 = 1,
        meItem2 = 2,
        meItem3 = 3
    } TMyEnum;

    typedef unsigned long int TMySet;

    TMySet a = 0;
    a = a | meItem1 & ~meItem2; //+meItem1, -meItem2
    if (a & meItem3) {...} //meItem3 in a
  21. link
  22. link
  23. link
  24. link
  25. link
  26. link
  27. link
  28. link, link
  29. link
  30. link
  31. link
  32. link
  33. link, link
  34. link
  35. link
  36. link    - a példa függvényt használ (későbbi rész)
  37. link
  38. link
  39. link    - a példa függvényt használ (későbbi rész)
  40. link

IIIb, A program részekre bontása

  1. Két kapcsos zárójel közötti kódszakasz, amely egyetlen utasítás helyett fut le. Megjegyzésképp, a blokkok egymásba ágyazhatóak.
  2. //{    Típusdefiníciók

        typedef char byte;

    //}
  3. Az a kódszakasz ameddig a változó elérhető - ez általában egy blokkra érvényes.
  4. A program nem lesz lefordítható.
  5. Amelyik a kódrészlethez közelebbi blokkban van - általában ez a belsőbbik lesz.
  6. A globális változó a program futása során végig elérhető, míg a lokális csak blokkszinten, ideiglenesen.
  7. Egy olyan névvel ellátott kódsorozatot, amely adatok egy bizonyos mennyiségéhez, egy másik adatcsoportot rendel - általában számítás által.
  8. Azt az adatcsoportot, amit a bekért adatmennyiséghez rendel - más néven helyettesítési érték, mivel ahol használva lesz a függvény ott a hívása helyett fog megjelenni ez az érték. Ez az érték a return parancs által jelölhető ki.
  9. float fv1 (int v1, int v2);
  10. char* fv2();
  11. float f(float x)
    {
        return x - x/2 + x/3 - x/4 + x/5;
    }
  12. A függvénynek van visszatérési értéke, az eljárásnak nincs.
  13. void fv3(int i1, int i2, char c3);
  14. Amikor a bekérésnél nem a változó értékét, hanem a memóriacímét adjuk meg - ezáltal visszaírás történhet.
  15. void f(float x, float* y)
    {
        if (y != NULL)
            (*y) = x - x/2 + x/3 - x/4 + x/5;
    }
  16. Nem, de cím szerint több érték is kivihető a függvényből.
  17. Az olyan függvények rekurzívak, amelyek összetett feladatokat végeznek el, önmaguk ismétlődő, de eltérő paraméterekkel történő meghívásával. A rekurzió fontos eleme, hogy legyen olyan pont, ahol megáll, és lesz visszatérési érték is.
  18. Egy függvény memóriacíme, amely által készíthető olyan kódrészlet ami bármilyen adott paraméterlistával bíró függvényt elfogad névtől függetlenül.
    typedef float (*TFuggveny)(float x);

    float sqr(float x){ return x*x };
    float cube(float x){ return x*x*x };

    TFuggveny fv = &sqr;
    float f = fv(3); //f = 9
    fv = &cube;
    f = fv(3); //f = 27
  19. A makró akkor jó, ha csak egy gyors kódrészlet ismétlődését kívánjuk megszüntetni. Sokkal gyorsabb mint a függvény, de nem tartalmazhat bonyolult típusokat, és számításokat.
  20. #define F(X) X - X/2 + X/3 - X/4 + X/5;
  21. #include <fájlnév>
  22. pl.:
        stdio.h, stdio.h, stdlib.h, time.h, stdlib.h, math.h, math.h, string.h, string.h, string.h
  23. #define, #include, #pragma, #ifdef, #else
  24. Egyszerű típusú konstans értékek definíálására
  25. pl.:
    1. A függvények összemásolása egy .C fájlba
    2. A függvények fejlécének összemásolása egy .H fájlba
    3. A típusdefiníciók, makrók áthelyezése a .H fájlba
    4. A .C és .H fájl összekapcsolása, az #include "<>.H" direktívával
    5. A .H fájl ellátása védelemmel
    6. A célprogramba kapcsolni a két fájlt az #include "<>.H" direktívával
  26. Egy olyan csoportosítási elem, ami több függvénytáron is átnyúlhat - csak C++ nyelvre jellemző.
  27. float osszead(float egyik, float masik)
    {
        return egyik + masik;
    }
  28. int osztoja_e(int egyik, int masik)
    {
        return !(egyik % masik);
    }
  29. float hatvany(float alap, int kitevo)
    {
        if (kitevo < 0)
        {
           kitevo *= -1;
           alap = 1 / alap; 
        }
       
        if (kitevo = 0)
            return 1;
        else 
            return alap * hatvany(alap, kitevo - 1);
    }
  30. #include <math.h>...

    float hossz(float* vektor, unsigned int length)
    {
        int i;
        float result = 0;

        for (i = 0; i < length; i++)
            result += vektor[i] * vektor[i];

        return sqrt(result);
    }
  31. float atlag(float* vektor, unsigned int length)
    {
        int i;
        float result = 0;

        for (i = 0; i < length; i++)
            result += vektor[i];

        if (length != 0) //nullával nem osztunk
            return result / length;
        else
            return 0;
    }

  32. #include <math.h>...

    float mert_koz(float* vektor, unsigned int length)
    {
        int i;
        float result = 1; //nullaszor bármi nulla lenne...

        for (i = 0; i < length; i++)
            result *= vektor[i];

        if (length != 0) //nullával nem osztunk
            return pow(result, 1 / length); //hatványozással érjük el az n-edik gyököt
        else
            return 0;
    }

  33. float mx_atlag(float** matrix, unsigned int mag, unsigned int szel)
    {
        int x, y, k;
        float result = 0;

        for (y = 0; y < mag; y++)
            for (x = 0; x < szel; x++)
                result += matrix[y][x];

        k = mag * szel;
        if (k != 0)
            return result / k;
        else
            return 0;
    }

  34. #include <math.h>...

    float mx_mert_koz(float** matrix, unsigned int mag, unsigned int szel)
    {
        int x, y, k;
        float result = 1;

        for (y = 0; y < mag; y++)
            for (x = 0; x < szel; x++)
                result *= matrix[y][x];

        k = mag * szel;
        if (k != 0)
            return pow(result, 1 / k);
        else
            return 0;
    }
  35. float ter_atlag(float*** ter, unsigned int sz, unsigned int sy, unsigned int sx)
    {
        int x, y, z, k;
        float result = 0;

        for (z = 0; z < sz; z++)
            for (y = 0; y < sy; y++)
                for (x = 0; x < sx; x++)
                    result += ter[z][y][x];

        k = sz * sy * sx;
        if (k != 0)
            return result / k;
        else
            return 0;
    }

  36. #include <math.h>...

    float ter_mert_koz(float*** ter, unsigned int sz, unsigned int sy, unsigned int sx)
    {
        int x, y, z, k;
        float result = 1;

        for (z = 0; z < sz; z++)
            for (y = 0; y < sy; y++)
                for (x = 0; x < sx; x++)
                    result *= ter[z][y][x];

        k = sz * sy * sx;
        if (k != 0)
            return pow(result, 1 / k);
        else
            return 0;
    }
  37. unsigned long int fibonacci(int x)
    {
        if (x == 0)
            return 0;
        else if (x == 1)
            return 1;
        else
            return fibonacci(x-1) + fibonacci(x-2);
    }

  38. unsigned long int faktorialis(int x)
    {
        if (x == 0)
            return 0;
        else if (x == 1)
            return 1;
        else
            return x * faktorialis(x - 1);
    }

  39. void kereszt_szorzat(float* a, float* b, float* eredmeny)
    {
       if (eredmeny != NULL)
       {
            eredmeny[0] = a[1] * b[2] - a[2] * b[1];
            eredmeny[1] = a[2] * b[0] - a[0] * b[2];
            eredmeny[2] = a[0] * b[1] - a[1] * b[0];
        }
    }

  40. #include <stdio.h>...

    void atlag_elj(float* vektor, unsigned int length)
    {
        int i;
        float result = 0;

        for (i = 0; i < length; i++)
            result += vektor[i];

        if (length != 0)
            printf("A vektor atlaga: %f", result / length);
        else
            return 0;
    }

  41. #include <stdio.h>...

    void szumma(float* vektor, unsigned int length)
    {
        int i;
        float result = 0;

        for (i = 0; i < length; i++)
            result += vektor[i];

        printf("A vektor szummazva: %f", result);
    }

  42. #include <stdio.h>...

    void alapmuv(float a, float b)
    {
        printf("A negy alapmuveletre %f es %f:\n\t+ :%f\n\t- :%f\n\t* :%f\n\t/ :", a, b, a+b, a-b, a*b);

        if (b != 0)
            printf("%f", a/b);
        else
            printf("NAN"); 
    }

  43. #include <stdio.h>...

    void beolvas_v(float* vektor, unsigned int length)
    {
        int i;
     
        for (i = 0; i < length; i++)
            printf("Kerem a %d. elemet: ", i + 1), scanf("%f", &vektor[i]);
    }

  44. #include <stdio.h>...

    void beolvas_m(float** matrix, unsigned int sy, unsigned int sx)
    {
        int y, x;
     
        for (y = 0; y < sy; y++)
            for (x = 0; x < sx; x++)
            {           
                printf("Kerem a %d. sor, %d. oszlop elemet: ", y + 1, x + 1);
                scanf("%f", &matrix[y][x]);
            }
    }

  45. #include <stdio.h>...

    void beolvas_t(float*** ter, unsigned int sz, unsigned int sy, unsigned int sx)
    {
        int z, y, x;
       
        for (z = 0; y < sz; z++)
            for (y = 0; y < sy; y++)
                for (x = 0; x < sx; x++)
                {           
                    printf("Kerem a %d. lap, %d. sor, %d. oszlop elemet: ", z + 1, y + 1, x + 1);
                    scanf("%f", &ter[z][y][x]);
                }
    }

  46. #include <stdlib.h>...

    void rand_v(float* vektor, unsigned int length)
    {
        int i;
     
        for (i = 0; i < length; i++)
            vektor[i] = rand();
    }

  47. #include <stdlib.h>...

    void rand_m(float** matrix, unsigned int sy, unsigned int sx)
    {
        int y, x;
     
        for (y = 0; y < sy; y++)
            for (x = 0; x < sx; x++)
                matrix[y][x] = rand();
    }

  48. #include <stdlib.h>...

    void rand_t(float*** ter, unsigned int sz, unsigned int sy, unsigned int sx)
    {
        int z, y, x;
       
        for (z = 0; y < sz; z++)
            for (y = 0; y < sy; y++)
                for (x = 0; x < sx; x++)
                    ter[z][y][x] = rand();
    }

  49. #include <stdio.h>...

    typedef struct
    {
        int szam;
        float valos;
    } TStruktura, *PStruktura;

    void beker_s(PStruktura adatok)
    {
        printf("Kerem a \"szam\"-ot: "); scanf("%d", &(adatok->szam));
        printf("Kerem a \"valos\"-t: "); scanf("%f", &(adatok->valos));
    }

  50. #define OSSZEG(X, Y) X+Y
  51. #define MAX(X, Y) X > Y ? X : Y
  52. #define OSZTO_E(X, Y) !(X % Y)
  53. #define ATLAG(X, Y) X+Y/2
  54. link (.C), link (.H)
    Megjegyzés: A továbbiakban ez a függvénytár jelentősen leegyszerűsíti az olyan dolgokat mint a mátrixok, stb. előállítása, képernyőről történő beolvasása, stb. - sőt az újabb utasításokkal, amik majd a többi fejezetben állnak elő igény szerint bővíthető. Sok esetben az esetleges beadandó feladatok is pár for ciklussá rövidülnek ennek a használatakor.
    Fontos: A CB esetében, hogy kapcsoljuk a saját .H fájlt, máshogy kell indulnia a programnak:
        1, New -> Project -> Console Application
        2, New -> Empty File (főprogram, MAIN.C)
        3, Az egész hókuszpókuszt elmented egy mappába, ide bemásolod ezt a két fájlt is
        4, oldalt a Workspace alatt jobbklikk a projektedre (színes négyzetek jelölik) - majd Add
    Files...
        5, betallózod a két fájlt, és már is használhatod - annyi hogy az #include "FUGGVENY.H" alakot használd, csak ehhez a fájlhoz

IIIc, Egyszerű dinamikus adatszerkezetek

  1. Egy olyan tömböt amelynek mérete futásidőben dől el.
  2. A statikusnak a memóriakezelését a programnyelv végzi, míg a dinamikusét mi magunk.
  3. Az hogy a memóriafolytonosságot úgy érjük el, hogy egy nagy összefüggő területet jelölünk ki neki.
  4. Mindig tételezzük fel a lehetőségét a sikertelen eseteknek, illetve sose felejtsük el felszabadítani, ha már nem használjuk.
  5. malloc, realloc, free, memset
  6. #include <stdio.h>...

    unsigned int pozitiv_egesz_szam;
    scanf("%d", &pozitiv_egesz_szam);
    float* ilyen_hosszu_tomb = (float*)malloc(pozitiv_egesz_szam * sizeof(float));
  7. int* tomb = (int*)malloc(60 * sizeof(int));
    *(tomb + 11) == tomb[11];
  8. Igaz.
  9. Igen, a realloc segítségével:
    int* tomb = (int*)malloc(60 * sizeof(int));
    tomb = (int*)realloc((void*)tomb, 65 * sizeof(int));
    tomb[64] = 0;
  10. Mert ezeknél fontos hogy a kezdőérték nulla legyen, pl. szummázás - és az alap kezdőérték nem nulla. Ilyenkor az átíráshoz, a for ciklusnál sokkal gyorsabb a memset.
  11. tomb[12].myItem1 = 4;
  12. Mert annak a létrehozásakor magunkra vállaltuk, hogy a program futása során, mi kezeljük a memóriáját - ezért nekünk kell kisöpörni is ha már nem kell.


  13. Mert ez már nem egy nagy lineáris tömb - megszűnik a memóriafolytonosság a sorok között - hiba történik túlindexeléskor.
  14. Míg az előbbi csak téglalapos lehet, a második lehet szabadalakú is.
  15. Mert a megvalósításának módja egy tömbben a tömb szerkezet lesz.
  16. link
  17. link
  18. Igen, de komplikáltabb mint egy dinamikus tömb esetében.
  19. Ha a létrehozás során, a sorvektorokat a memset segítségével kinullázzuk.
  20. link
  21. link, link
    Az egyik közelebb áll a tömbökhöz, míg a másik inkább a mátrixokhoz - a második kivitelezése emiatt összetettebb (hátrány), de nagy méretű struktúrák esetén is, sokkal több elemű lehet mint az első (előny).
  22. Igen, de még komplikáltabb, mint egy dinamikus mátrix esetén.
  23. Igen, de nagyon komplikált.
  24. Lefoglal egy n elemű tömböt egy adott típusból, a malloc utasítást helyettesíti - sokkal olvashatóbb.
  25. Felszabadít egy tömböt egy adott típusból, a free utasítást helyettesíti - sokkal olvashatóbb.
  26. Nem.
  27. Előny:
        - nem kell felszabadítani
        - igény szerint rugalmasan bővíthető, szerkeszthető, átméretezhető
        - a beépített utasítások rengeteg algoritmust válthatnak ki
    Hátrány:
        - az objektum jelleg kezdőknek nehézkes lehet
        - szükséges hozzá egy külön függvénytár
  28. beszúrás (insert), törlés (erase), hozzáadás (push_back)
  29. #include <vector>...

    std::vector<int> tomb(60);
    tomb[12] =  4;
  30. <new>, <vector>
  31. Alapvetően nem.
  32. Igen.

    #include <vector>...

    std::vector<std::vector<int>> matrix(7);
    int y;
    for (y = 0; y < 7; y++)
      matrix[y].resize(10);
    matrix[6][9] = 5;
  33. float** fmxalloc(unsigned int sy, unsigned int sx)
    {
        unsigned int y;
        float** array = (float**)malloc(sy * sizeof(float*));

        for (y = 0; y < sy; y++)
           array[y] = (float*)malloc(sx * sizeof(float));

        return array;
    }
  34. A realloc alapú kivitel elég összetett lenne, maradtam egy olyannál ami egy új mátrixba átmásol mindent inkább.

    float** fmxrealloc(float** src, unsigned int sy, unsigned int sx, unsigned int dy,
        unsigned int dx)
    {
        unsigned int y;
        float** array = fmxalloc(dy, dx); //34. kérdés

        for (y = 0; y < MIN(sy, dy); y++)
            memcpy(&array[y][0], &src[y][0], MIN(sx, dx) * sizeof(float));

        //a memcpyről később lesz szó - adatot másol A helyről B-re

        fmxfree(src); //36. kérdés

        return array;
    }
  35. void fmxfree(float** array, unsigned int sy)
    {  
        unsigned int y;

        for (y = 0; y < sy; y++)
            free((void*)array[y]);

        free((void*)array);
    }
  36. float*** ftalloc(unsigned int sz, unsigned int sy, unsigned int sx)
    {
        unsigned int y, z;
        float*** array = (float***)malloc(sz * sizeof(float**));

        for (z = 0; z < sz; z++)
       
    {
            array[z] = (float**)malloc(sy * sizeof(float*));
           
            for (y = 0; y < sy; y++)
              array[z][y] = (float*)malloc(sx * sizeof(float));
       
    }

        return array;
    }
  37. A realloc alapú kivitel elég összetett lenne, maradtam egy olyannál ami egy új térbe átmásol mindent inkább.

    #define MIN(A, B) A < B ? A : B

    float*** trealloc(float*** src, unsigned int sz, unsigned int sy, unsigned int sx, unsigned int dz, unsigned int dy, unsigned int dx)
    {
     
        unsigned int y, z;
        float*** array = ftalloc(dz, dy, dx); //37. kérdés

        for (z = 0; z < MIN(sz, dz); z++)
            for (y = 0; y < MIN(sy, dy); y++)
                memcpy(&array[z][y][0], &src[z][y][0], MIN(sx, dx) * sizeof(float));

        //a memcpyről később lesz szó - adatot másol A helyről B-re

        ftfree(src); //39. kérdés

        return array;
    }
  38. void ftfree(float*** array, unsigned int sz, unsigned int sy)
    {
        unsigned int y, z;

        for (z = 0; z < sz; z++)
       
    {
            for (y = 0; y < sy; y++)
                free((void*)array[z][y]);

            free((void*)array[z]);
       
    }

        free((void*)array);
    }
  39. void* mxalloc(unsigned int sy, unsigned int sx, const unsigned int element_size)
    {
        unsigned int y, j;
        void** array = (void**)malloc(sy * sizeof(void*));

        if (!array)
            for (y = 0; y < sy; y++)
                if (!(array[y] = malloc(sx * element_size)))
               
    {
                    for (j = 0; j < y; j++)
                        free((void*)array[j]);
                    free((void*)array);
                    return NULL;
               
    }

        return (void*)array;
    }
  40. A realloc alapú kivitel elég összetett lenne, maradtam egy olyannál ami egy új mátrixba átmásol mindent inkább.

    void* mxrealloc(void* ptr, unsigned int sy, unsigned int sx, unsigned int dy,
        unsigned int dx, const unsigned int element_size)
    {
        if (sx == 0 || sy == 0 || dx == 0 || dy == 0 || element_size == 0 || !ptr)
            return NULL;

        unsigned int y;
        void** array = mxalloc(dy, dx, element_size); //40. kérdés
        void** src = (void**)ptr;

        if (!array)
            return NULL;

        for (y = 0; y < MIN(sy, dy); y++)
            memcpy(&array[y][0], &src[y][0], MIN(sx, dx) * element_size);

        //a memcpyről később lesz szó - adatot másol A helyről B-re

        mxfree(ptr); //42. kérdés

        return (void*)array;
    }
  41. void mxfree(void* ptr, unsigned int sy)
    {  
        if (sy == 0 || !ptr)
            return NULL;
       
        unsigned int y;
        void** array = (void**)ptr;

        for (y = 0; y < sy; y++)
       
    {
            free((void*)array[y]);
       
    }

        free((void*)array);
    }
  42. void* talloc(unsigned int sz, unsigned int sy, unsigned int sx, const unsigned int element_size)
    {
        if (sx == 0 || sy == 0 || sz == 0 || element_size == 0)
            return NULL;

        unsigned int y, z, j, k;
        void*** array = (void***)malloc(sz * sizeof(void*));

        if (!array)
            for (z = 0; z < sz; z++)
           
    {
                if (!(array[z] = (void**)malloc(sy * sizeof(void*))))
               
    {
                    for (k = 0; k < z; k++)
                        mxfree((void*)array[k], sy); //42. példa
                    free((void*)array);
                    return NULL;
               
    }

                for (y = 0; y < sy; y++)
                    if (!(array[z][y] = malloc(sx * element_size)))
                   
    {
                        for (j = 0; j < y; j++)
                            free((void*)array[k][j]);
                        free((void*)array[k]);

                        for (k = 0; k < z; k++)
                            mxfree((void*)array[k], sy); //42. példa
                        free((void*)array);
                        return NULL;
                    }
           
    }

        return (void*)array;
    }
  43. A realloc alapú kivitel elég összetett lenne, maradtam egy olyannál ami egy új térbe átmásol mindent inkább.

    #define MIN(A, B) A < B ? A : B

    void* trealloc(void* ptr, unsigned int sz, unsigned int sy, unsigned int sx, unsigned int dz, unsigned int dy, unsigned int dx, const unsigned int element_size)
    {
        if (dx == 0 || dy == 0 || dz == 0 || sx == 0 || sy == 0 || sz == 0 || element_size == 0 || !ptr)
            return NULL;
     
        unsigned int y, z;
        void*** array = (void***)talloc(dz, dy, dx, element_size); //43. kérdés

        if (array == NULL)
            return NULL;

        for (z = 0; z < MIN(sz, dz); z++)
            for (y = 0; y < MIN(sy, dy); y++)
                memcpy(&array[z][y][0], &src[z][y][0], MIN(sx, dx) * element_size);

        //a memcpyről később lesz szó - adatot másol A helyről B-re

        tfree(ptr); //45. kérdés

        return (void*)array;
    }
  44. void tfree(void* ptr, unsigned int sz, unsigned int sy)
    {
        if (sz == 0 || sy == 0 || !ptr)
            return;
     
        unsigned int y, z;
        void*** array = (void***)ptr;

        for (z = 0; z < sz; z++)
       
    {
            for (y = 0; y < sy; y++)
           
    {
                free((void*)array[z][y]);
           
    }

            free((void*)array[z]);
       
    }

        free((void*)array);
    }
  45. link
  46. link
  47. link
  48. link
  49. link
  50. link
  51. link
  52. link
  53. link
  54. link
  55. link
  56. link
  57. link
  58. link
  59. link
  60. link
  61. link
  62. link
  63. link
  64. link
  65. link
  66. link
  67. direkt megoldás: link
    indirekt megoldás: link
  68. link
  69. link
  70. link
  71. link
  72. link
  73. link

IIId, Karakterláncokkal végzett műveletek

  1. pl.:
    • főként szövegekkel kommunikál
    • egy betűtípus, 16 előtér és háttérszín
    • a betűk rögzített szélességűek
    • a képernyőterület oszlop-sor méret által lesz meghatározva
  2. EGA/VGA: 80 oszlop, 25 sor, 16 szín
  3. A kurzor egy aláhúzás ("_") karakter ami villog - ez jelöli hogy éppen, ha most elkezdenénk írni a képernyőre, honnan kezdené. A kurzor elrejthető (pl. színes kezelőfelülettel bíró szöveges alkalmazásoknál szokták). Minden kiírás után a kurzor új helyre kerül, a kiírt szöveg végére.
  4. Teljes körű támogatást a Windows XP tartalmaz, de néhány MS-DOS alkalmazást a jelenlegi Windows-ok 32 bites kiadásai is képesek futtatni.
  5. Olyan csatornák amikor karaktereket (= byteokat) lehet átvinni írással/olvasással:
    • CON: standard be/ki/hibakimenet - képernyőről (billentyűzetről) olvas be/ír ki adatokat (utóbbi főként hibáknak van fenntartva - eltér a standard kimenettől)
    • NUL: null ki/bemenet - kimenetként elnyeli az adatokat, bemenetként mindig üres
    • AUX, COMx: soros ki/bemenet - a kiírt byteok a soros/kommunikációs portra kerülnek, illetve onnan lesznek beolvasva
    • PRN, LPTx: párhuzamos ki/bemenet - a kiírt byteok a párhuzamos/nyomtatóportra kerülnek, illetve onnan lesznek beolvasva
    • tetszőleges fájl - a kiírt byteok fájlból lesznek beolvasva, illetve oda lesznek kiírva
    • másik alkalmazás - a másik alkalmazás kimenete lesz ennek a bemenete, és fordítva
  6. Több módja van:
    • copy parancs által
    • átirányítással (pl. +type parancs)
    • összekapcsolással (pl. +echo parancs)
  7. copy CON: Teszt.txt
  8. copy Teszt.txt CON:
  9. echo I | format C:
  10. fgetc, getchar
  11. fputc, putchar
  12. Néha bennmaradhat karakter az adott csatorna pufferében, és az fflush ezt üríti ki - tipikusan ilyen hiba ha egy gets után a scanf látszlóag nem fut le - mivel kiolvassa pl. az <ENTER> billentyűt a pufferből és ennyi.
  13. Az MS-DOS alatt az <ENTER> két karakterből áll, az első az újsor (line feed), a második a "kocsi vissza" (carriage return) - ezek a nevükből adódóan is az írógéphez köthetőek [CR/LF sortörés].
    Unix alapú rendszerekben csak az első van jelen [LF sortörés], illetve a C/C++ a memóriában tárolt karakterláncokban is így tárolja, csak kiíráskor írja ki mindkettőt - ha kell.
  14. Nem mindig tudjuk előre, a felhasználó hány karaktert akar begépelni, és ha többet ír be, mint amennyinek mi helyet biztosítunk, akár hiba is történhet. Az fgets bekéri azt is, hogy mennyi helyünk van a tömbben - így ha hosszabb a szöveg, szabályosan vágja le.
  15. A puts, fputs segítségével. link
    fputs(stderr, "Az alma kek.");
  16. Segítségével a karaktertömbök nyugodtan átadhatóak mutatóként anélkül, hogy a hosszukat külön változókban tárolnánk. A '\0' segítségével (ha szabályos a szöveg, és rajta van) meg lehet keresni annak a végét, ami sok-sok utasításnál fontos. A zárókarakter hiányában számolhatunk arra hogy kilépünk a tömb határain (túlfutás), és a program összeomlik.
  17. Igen, ha hosszabb szöveget írunk be mint a tömb hossza - ilyenkor nem csak a zárókarakter lemaradásával kell számolni, hanem a túlfutással is.
  18. Megadja hogy a zárókarakter előtt hány karakter található a sztringben.
  19. Az strcmp megadja két szöveg egymáshoz képesti helyét - ha N1 > N2 akkor 1, ha N1 < N2 akkor -1, ha N1 == N2 akkor nulla a visszatérési értéke.
  20. Mivel az strcmp egy egyszerű összehasonlítási algoritmussal dolgozik, ami a kódlapra épít - a kódlapban pedig az angol ábécé betűi sorban vannak, de a speciális "külföldi" karakterek - mint a magyar ékezetes betűk is - hátrébb vannak mint az angol ábécé betűi.
  21. Mert a sztring, az egy karaktertömb ami mutatóként van kezelve - így ha az értékadással A=B alakban másoljuk, akkor csak a mutatót kétszereztük meg - két hivatkozás lesz ugyanarra a tömbre.
    Az strdup lemásolja a tömböt egy másik memóriaterületre, így az eredményéül adott mutató ténylegesen egy másolatra mutat.
  22. lásd 21.
  23. Erre az strcat szolgál - fontos hogy az összekapcsolt szöveg el kell férjen az első tagban.
  24. Mert a programnyelv nem értelmezi a szöveget, csak karakterenként összemásolja pl. "ab" + "ab" = "abab" alapon.
  25. pl.:
    • char* -> atoi() -> int
    • char* -> atof() -> float
    • char* -> atol() -> long int
  26. Mert a sztring, az egy karaktertömb ami mutatóként van kezelve - így a típuskonverzió során ezt a mutatót (ami egy memóriacím, kvázi egy szám) alakítanánk át, és nem a szöveg tartalmát - arra különböző algoritmusok vannak miként kell értelmeztetni és más típussá alakítani (lásd 25.)
  27. Az a sztring, ami utalásokat tartalmaz a printf/scanf utasítások számára, a különféle változók, különféle helyettesítésére/kiolvasására majd formázására vonatkozóan.
  28. pl.
    1. valós szám legrövidebb alakja (tizedestört/normálalak közül), kisbetűs, két tizedesjegy pontossággal, mindenféleképpen kiírt előjellel
    1. valós szám nagybetűs normálalakja, 10+ karakter hosszon kiírva, azon belül balra igazítva
    2. mutató (memóriacím)
    3. nemzetközi szöveg
    4. 64-bites (8 bájtos) előjel nélküli egész szám
    5.  8-bites (1 bájtos) előjel nélküli egész szám, 16-os számrendszerben, 8+ karakteren kiírva, szóköz helyett "0" előtéttel
    6.  négy tizedes pontossággal többszörösen pontos valós szám, menet közben megadott karakteren kiírva
  29. A vezérlőkarakterek, azok a karakterek, amelyeknek fontos szerepük van (pl. sortörés, tabulátor, ...), saját karakterkóddal rendelkeznek - de megjelenítendő képpel nem - általában az operációs rendszerre hatnak, ami hatásukra különböző feladatokat végezhet el (pl. program leállítása, fájl lezárása, stb...).
  30. pl.
    1. \b, törli az előtte lévő karaktert
    2. \e, segítségével escape-szekvenciák is kiadhatóak
    3. \f, törli a képernyőt - nyomtatásnál új lapot kezd
    4. \4, átvitel vége jel (EOT = Ctrl+D)
    5. \32, fájl vége jel (EOF = Ctrl+Z)
    6. \a, hangjelzést ad ki
    7. \n, sortörést csinál - a memóriában csak az LF tag van tárolva
    8. \t, vízszintes tabulátor
    9. \3, megszakítási jel (SIGINT = Ctrl+C)
  31. printf, fprintf, snprintf - ezek a képernyőre/fájlba/sztringbe írnak formázott szöveget
    scanf, fscanf, sscanf - ezek a képernyőről/fájlból/sztringből értelmeznek formázott szöveget
  32. typedef struct {
      int ev, honap, nap;
    } TDatum, *PDatum;

    TDatum d;
    scanf("%d.%d.%d", &d.ev, &d.honap, &d.nap);
  33. link
  34. pl.
    • dinamikus, de nem kell felszabadítani
    • beolvasásakor, nem számít az előre megadott hossz, igény szerint bővül
    • kompatibilis a char* megoldással is
    • nem kell a hosszára, és a zárókarakterre figyelni
    • a beépített utasításai leegyszerűsítik a kezelését
    • értékadással másolható
    • összeadható
    • a beépített utasítások olyat is tudnak, ami nagyon körülményes lenne, pl. beszúrás, szakasz törlése, stb.
  35. pl.
    • dinamikus, de nem kell felszabadítani
    • a beépített utasításai leegyszerűsítik a kezelését
    • a beépített utasítások olyat is tudnak, ami nagyon körülményes lenne, pl. beszúrás, szakasz törlése, stb.
  36. #include <iostream> ...

    std::cout << "Teszt szöveg.";
  37. #include <iostream> ...

    int i = 5;
    std::cout << "Egy kerek szám: " << i;
  38. #include <iostream> ...

    int i;
    std::cin >> i;
  39. link
  40. link
  41. Igen, ha az std::wcin csatornát használjuk, és az std::string helyett, az std::basic_string<wchar_t> típust használjuk.
  42. link
  43. #include <stdio.h>
    #include <string.h>

    int main()
    {
        char szoveg[200];
        printf("Kerek egy szoveget (max. 200 karakter): "); fgets(szoveg, 200, stdin);
        printf("\nA szoveg hossza: %d", strlen(szoveg));
        return 0;
    }
  44. #include <stdio.h>
    #include <string.h>

    int main()
    {
        char szoveg1[200], szoveg2[100];
        printf("Kerek egy szoveget (max. 100 karakter): "); fgets(szoveg1, 100, stdin);
        printf("Kerek meg egy szoveget (max. 100 karakter): "); fgets(szoveg2, 100, stdin);
        strcat(szoveg1, szoveg2);
        printf("\nA ket szoveg egyutt:", szoveg1);
        return 0;
    }
  45. #include <iostream>

    using namespace std;

    int main()
    {
       char c;
     
       do
       {
         cin >> c;
         cout << c;
       }
       while (c != EOF);
     
       return 0;
    }
  46. #include <iostream>
    #include <string>

    using namespace std;

    int main()
    {
       string
    sz;

       cout << "Kerek egy szoveget: "; getline(cin, sz);
       cout << endl << "A szoveg hossza: " << sz.length() << endl;

       return 0;
    }
  47. #include <iostream>
    #include <string>

    using namespace std;

    int main()
    {
       string
     sz1, sz2;

       cout << "Kerek egy szoveget: "; getline(cin, sz1);
       cout << "Kerek meg egy szoveget: "; getline(cin, sz2);
      
       string sz3 = sz1 + sz2;

       cout << endl << "A ket szoveg egyutt: " << sz3;

       return 0;
    }

IIIe, Egyszerű rendezési algoritmusok

  1. pl.:
    1. Tudjunk adathalmazt (pl. tömböt, adatbázist) felállítani a rendezni kívánt adatokból.
    2. Tudjuk eldönteni minden egyes elemre, hogy melyik van előrébb a sorban. Ehhez elégséges feltétel ha ezt bármelyik kettőről el tudjuk dönteni, hiszen akkor lényegében mindről el lehet.
    3. Keressünk egy vidám algoritmust, ami a páronkénti összehasonlítások alapján, a lehető legkevesebb cserével (és legkevesebb összehasonlítással) sorba rakja az elemeket.
  2. Alapvetően lesz két csoport, a közvetlenül és a közvetetten összehasonlítható adattípus - a közvetleneket egyszerűen lehet összehasonlítani - mivel a gép hardveresen képes erre (processzor logikai egysége) , míg a másikat csak összetettebb algoritmusok által tudjuk elvégezni (bonyolultabb számítást végezve, közvetlenül összehasonlítható értéket állítva elő).
  3. Az egyszerű véletlenszám generálás alapja az hogy fogunk egy algoritmust, amely egy adott számból, attól nagyon eltérő számot fog adni. Ahhoz, hogy minden indításkor más és más számokat kapjunk, szükséges egy kezdőérték megadása - ez lesz az, amivel minden alkalommal más és más számokat fog kidobni az algoritmus. A kezdőértéket szokás az időből származtatni, mert az mindig változik.

  4. Azonos kezdőértékek esetén, az algoritmus minden alkalommal ugyanazokat a számokat dobná ki, így már azok nem egészen lennének véletlenek.
  5. srand, rand
  6. float f = rand() / (float)RAND_MAX;
  7. int f = rand() % 10 + 1;
  8. #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>

    int main()
    {
        int n, i;
        srand(time(NULL));
        printf("Hany veletlenszam kell? "); scanf("%d", &n);
        for (i = 0; i < n; i++)
            printf("%d ", rand());
        return 0;
    }
  9. #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>

    int main()
    {
        int n, i;
        srand(time(NULL));
        printf("Hany veletlenszam kell? "); scanf("%d", &n);
        for (i = 0; i < n; i++)
            printf("%d ", rand() % 100 + 1);
        return 0;
    }
  10. #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>

    int main()
    {
        int n, i;
        srand(time(NULL));
        printf("Hany veletlenszam kell? "); scanf("%d", &n);
        for (i = 0; i < n; i++)
            printf("%.3f ", rand() / (float)RAND_MAX);
        return 0;
    }
  11. Egy külső i ciklussal végighaladunk az elemeken (az utolsót kivéve), és az így adott i. elemhez hasonlítjuk egy belső j ciklus által, az összes mögötte lévő elemet. Ha kisebb a j. elem mint az i.-dik, akkor cserélünk, és legközelebb a már kisebb i.-dik elemmel hasonlítjuk össze a többit.
    Az algoritmus során, biztosak lehetünk hogy az i. elem, előtt álló rész már ki van rendezve - hiszen mindig a legkisebb elem kerül oda (kvázi minimumkeresést végez a belső ciklus). A minimumkeresés optimalizálásával lényegesen gyorsítható az algoritmus, de összetettsége is lényegesen nőni fog.
  12. Minden lépésben [1]-től egyesével n-ig, kiemeljük a csökkenő sorozat szerinti első elemet, és beszúrjuk a megfelelő helyre.
  13. Ha a tömböt egy víztartályhoz hasonlítjuk, és a rendezendő tételeknek a buborékok súlyát feleltetjük meg, akkor minden lépés egy buborék felemelkedését eredményezi, a súlyának megfelelő szintre.
    Ennél előfordulhat, hogy már nincs szükség cserére, még sem áll le a rendezési művelet. Ez javítható ha jegyezzük hogy történt-e csere a menet alatt, és az első olyannál ahol nem, ott kilépünk az algoritmusból.
    Ha esetleg egy folyamatjelzőt (progressbar) is szeretnénk meghajtani, az utolsó csere indexe lehet a k, ahol a k alatti adatok már sorban vannak.

  14. Ennek az algoritmusnak akkor lehet előnye ha extrém mennyiségű adatot kell rendezni.
    A lényeg hogy felosztjuk a tömböt sok egyforma részre képzeletben, amiket sorba rendezünk (pl ne=2 esetén egyértelmű).
    A következő lépések abból állnak hogy ezeket a kisebb részeket összefésüljük, mindig páronként.

  15. Nagyjából annyi a teendő, hogy a relációs jelet kicseréljük az strcmp-re, az egyik szimpatikus algoritmusban.
  16. #include <stdlib.h>...,l

    void vel(float* tomb, unsigned int length)
    {
        int i;
        for (i = 0; i < length; i++)
            tomb[i] = rand() / (float)RAND_MAX;
    }
  17. #include <stdlib.h>...

    void mxvel(float** matrix, unsigned int sy, unsigned int sx)
    {
        int x, y;
        for (y = 0; y < sy; y++)   
            for (x = 0; x < sx; x++)
                matrix[y][x] = rand() / (float)RAND_MAX;
    }
  18. #include <stdlib.h>...

    void tvel(float*** ter, unsigned int sz, unsigned int sy, unsigned int sx)
    {
        int x, y, z;
        for (z = 0; z < sz; z++)   
            for (y = 0; y < sy; y++)   
                for (x = 0; x < sx; x++)
                    ter[z][y][x] = rand() / (float)RAND_MAX;
    }
  19. void rend_cs(float* f, const int count)
    {
      float p;
      int i, j;

      for (i = 0; i < count - 1; i++)
        for (j = i + 1; j < count; j++) 
          if (f[i] > f[j])
          {
             p = f[i];
             f[i] = f[j];
             f[j] = p;
          }
    }
  20. void mxrend_cs(float** f, const int sy, const int sx)

        int y;
        for (y = 0; y < sy; y++)   
            rend_cs(f[y], sx); //lásd 19.
    }
  21. void trend_cs(float*** f, const int sz, const int sy, const int sx)

        int z;
        for (z = 0; z < sz; z++)   
            mxrend_cs(f[z], sy, sx); //lásd 18.
    }
  22. void csrend_cs(float* f, const int count)
    {
      float p;
      int i, j;

      for (i = 0; i < count - 1; i++)
        for (j = i + 1; j < count; j++) 
          if (f[i] < f[j])
          {
             p = f[i];
             f[i] = f[j];
             f[j] = p;
          }
    }
  23. void mxcsrend_cs(float** f, const int sy, const int sx)

        int y;
        for (y = 0; y < sy; y++)   
            csrend_cs(f[y], sx); //lásd 22.
    }
  24. void tcsrend_cs(float*** f, const int sz, const int sy, const int sx)

        int z;
        for (z = 0; z < sz; z++)   
            mxcsrend_cs(f[z], sy, sx); //lásd 23.
    }
  25. void rend_b(float* f, const int count)
    {
      float p;
      int i, j;

      for (i = 1; i < count; i++)
      {
        p = f[i];
        j = i - 1;

        while (j > 0 && p < f[j])
          f[j + 1] = f[j--];

        f[j + 1] = p;
      }
    }
  26. void mxrend_b(float** f, const int sy, const int sx)

        int y;
        for (y = 0; y < sy; y++)   
            rend_b(f[y], sx); //lásd 25.
    }
  27. void trend_b(float*** f, const int sz, const int sy, const int sx)

        int z;
        for (z = 0; z < sz; z++)   
            mxrend_b(f[z], sy, sx); //lásd 26.
    }
  28. void csrend_b(float* f, const int count)
    {
      float p;
      int i, j;

      for (i = 1; i < count; i++)
      {
        p = f[i];
        j = i - 1;

        while (j > 0 && p > f[j])
          f[j + 1] = f[j--];

        f[j + 1] = p;
      }
    }
  29. void mxcsrend_b(float** f, const int sy, const int sx)

        int y;
        for (y = 0; y < sy; y++)   
            csrend_b(f[y], sx); //lásd 28.
    }
  30. void tcsrend_b(float*** f, const int sz, const int sy, const int sx)

        int z;
        for (z = 0; z < sz; z++)   
            mxcsrend_b(f[z], sy, sx); //lásd 29.
    }
  31. void rend_bub(float* f, const int count)
    {
      float p;
      int i, j;

      for (i = 1; i < count; i++)
        for (j = count - 1; j >= i; j--)
          if (f[j - 1] > f[j])
          {
             p = f[j - 1];
             f[j - 1] = f[j];
             f[j] = p;
          }
    }

  32. void mxrend_bub(float** f, const int sy, const int sx)

        int y;
        for (y = 0; y < sy; y++)   
            rend_bub(f[y], sx); //lásd 31.
    }
  33. void trend_bub(float*** f, const int sz, const int sy, const int sx)

        int z;
        for (z = 0; z < sz; z++)   
            mxrend_bub(f[z], sy, sx); //lásd 32.
    }
  34. void csrend_bub(float* f, const int count)
    {
      float p;
      int i, j;

      for (i = 1; i < count; i++)
        for (j = count - 1; j >= i; j--)
          if (f[j - 1] < f[j])
          {
             p = f[j - 1];
             f[j - 1] = f[j];
             f[j] = p;
          }
    }

  35. void mxcsrend_bub(float** f, const int sy, const int sx)

        int y;
        for (y = 0; y < sy; y++)   
            csrend_bub(f[y], sx); //lásd 34.
    }
  36. void tcsrend_bub(float*** f, const int sz, const int sy, const int sx)

        int z;
        for (z = 0; z < sz; z++)   
            mxcsrend_bub(f[z], sy, sx); //lásd 35.
    }
  37. void beturend(char** f, const int count)
    {
      char* p;
      int i, j;

      for (i = 0; i < count - 1; i++)
        for (j = i + 1; j < count; j++)
          if (strcmp(f[i], f[j]) == 1)
          {
            p = f[i];
            f[i] = f[j];
            f[j] = p;
          }
    }
  38. void beturend_forditott(char** f, const int count)
    {
      char* p;
      int i, j;

      for (i = 0; i < count - 1; i++)
        for (j = i + 1; j < count; j++)
          if (strcmp(f[i], f[j]) == -1)
          {
            p = f[i];
            f[i] = f[j];
            f[j] = p;
          }
    }