Minta vizsgasorok

A 2011-es év alapján.

A vizsgákra ne a régi sorok megoldásainak olvasgatásával készülj! Annak hasznossága nem közelítőleg nulla, hanem pontosan nulla. Lásd itt.

1 Minta vizsga 2011

  1. Beugró
    1. Adott az alábbi definíció:
      int a[] = {3,29,26,31,16,27};
      Mi az értéke az &a[5]-a kifejezésnek?
    2. Definiálj olyan függvénypointerekből álló tömböt, melynek tagjai a könyvtári sin() függvényre is mutathatnak.
    3. Írj függvényt, amely visszaadja, hogy a paraméterében kapott sztring milyen hosszú! (Mint az strlen(). Könyvtári függvényt nem használhatsz.)
    4. Adott a következő típus:
      typedef struct pont3d { double x, y, z; } pont3d;
      Írj C függvényt, melynek felhasználásával a qsort() növekvő sorrendbe tud rendezni egy pont3d tömböt a benne tárolt, térben értelmezett pontok origótól vett távolsága szerint!
    5. Írj C függvényt, amely átvesz egy nemnegatív egészet, és visszaadja annak paritását, vagyis azt a logikai értéket, mely megmutatja, hogy a vizsgált szám páros számú 1-es bitet tartalmaz-e!
    6. Írj C programot, amely a parancssorán átvett tetszőleges számú egész szám összegét kiírja!
  2. Adott a következő definíció:
    typedef struct elem { int adat; struct elem *kov; } elem;
    Írj függvényt, mely elem elemekből álló, NULL-lal lezárt láncolt listát vesz át, és az utolsó elemét az elejére fűzi, pl. A→B→C→NULL listából C→A→B→NULL lesz. Visszatérési értékként az újonnan élre került elem címét adja vissza. Nem használhatsz tömböt, nem foglalhatsz új listaelemet; az eredeti elemekből kell, hogy álljon a lista!
    1. Írj soratlagok() nevű függvényt, amelyik paraméterként egy sorfolytonosan tárolt kétdimenziós double tömböt kap (egydimenziós tömbként tárolva, vagyis az első sor vége után a második sor eleje következik stb)! A függvény második paramétere a szélesség, harmadik pedig a magasság legyen. A függvény visszatérési értékében adjon vissza egy dinamikusan foglalt tömbre mutató pointert, amely tömb olyan magas, mint az eredeti tömb! Tárolja minden eleme az ugyanolyan indexű sor elemei átlagát a 2D tömbből!
    2. Írj programot, amelyik definiál egy 42 elemű tömböt, amelyben egy 6×7-es 2D tömböt tárol! Kérd be a felhasználótól a tömb összes elemét, és a függvény segítségével számold ki az átlagokat! Írd ki azokat a képernyőre!
  3. A nyári fesztiválok adatait egy szöveges fájlban az alábbi módon tároljuk:
    fesztiválnév kezdődátum végdátum város
    fesztiválnév kezdődátum végdátum város
    …
    

    Az adatok szóközzel vannak elválasztva, a fesztiválnévben és a városban szóköz nem lehet, ha mégis lenne, azok helyén '_' karakter áll. A nevek maximálisan 40 karaktert foglalnak el. A dátumok formátuma a következő: hónapszám nap.

    Írj programot, amely bekér a felhasználótól két dátumot, hogy mikor szeretne bulizni, valamint a feldolgozandó fájl nevét (max. 50 karakter), és kiírja a standard kimenetre azokat a fesztiválokat, amelyek időtartama legalább részben megadott intervallumon belül esik. A fájlt csak egyszer olvashatod végig, és abban tetszőleges számú fesztivál lehet, tetszőleges időrendben. Példa fájl:

    Sziget 08 07 08 13 Budapest
    Volt 07 04 07 07 Sopron
    Verébfeszt 08 17 08 19 Csorna
    
    Felhasználói bemenet:
    08 01 08 17
    
    Kimenet:
    Sziget 08 07 08 13 Budapest
    Verébfeszt 08 17 08 19 Csorna
    

2 Elővizsga 2011

    1. Definiálj egy pfv nevű pointert, amely a szabványos fopen() függvényre tud mutatni.
    2. Megoldás

      FILE* (*pfv)(char const *, char const *);
    3. Definiálj struktúrát típusdefinícióval, amely egy tetszőleges dimenzióbeli pont Descartes-koordinátáit tárolja: dimenziószám (nemnegatív egész), koordináták (dinamikusan foglalt valós tömb).

      Megoldás

      typedef struct PontND {
          unsigned dimenzioszam;
          double *koo;
      } PontND;
    4. Írj C programot, amely kiírja a parancssori paramétereinek számát!

      Megoldás

      int main(int argc, char *argv[]) {
          printf("%d", argc);
          return 0;
      }
    5. Írj programrészt, amely egy x előjel nélküli egész alulról 5. bitjét kiolvassa, és egy hasonló y számba beírja ugyanarra a helyiértékre.

      Megoldás

      unsigned x, y;
      if (x & 1<<5)
          y |= 1<<5;
      else
          y &= ~(1<<5);
    6. Adott a lenti, dinamikusan foglalt sztringeket tároló lista típus. Írj programrészt, amely felszabadít egy ilyen elemekből álló, strázsa nélküli listát, memóriaszivárgás nélkül! A lista elejére a p pointer mutat. (Definiáld a változókat!)
      typedef struct Szo {
          char *adat;
          struct Szo *kov;
      } Szo;

      Megoldás

      Szo *p=........;
      
      while (p!=NULL) {
          Szo *kov=p->kov;
          free(p->adat);
          free(p);
          p=kov;
      }
    7. Adott a lenti bináris fa típus. Írj függvényt, amely visszaadja a fában tárolt legnagyobb értéket (kihasználhatod, hogy ez legalább 0); üres fára 0-t!
    8. struct Fa {
          unsigned ertek;
          struct Fa *bal, *jobb;
      };

      Megoldás

      unsigned max(struct Fa *gyoker) {
          unsigned maxertek, temp;
          if (gyoker==NULL) return 0;
          maxertek=gyoker->ertek;
          temp=max(gyoker->bal);
          if (temp > maxertek) maxertek=temp;
          temp=max(gyoker->jobb);
          if (temp > maxertek) maxertek=temp;
          return maxertek;
      }
  1. Egy szöveges fájl egy bogár másodpercenként felvett, valós x, y koordinátáit tartalmazza méterben, szóközzel elválasztva, páronként új sorban. Írj ANSI C programot, amelyik paramétersoron átveszi a fájl nevét, és megadja, hány m-t tett meg összesen a bogár, és mi volt a legnagyobb sebessége (m/s) két regisztrált pont között. Felteheted, hogy a fájl létezik, és legalább két bejegyzést tartalmaz. Feltehetjük, hogy két regisztrált állapot között a bogár egyenesen halad. Két pont távolságát a Pitagorasz-tétellel számolhatjuk.
  2. Megoldás

    #include <stdio.h>
    #include <math.h>
    
    int main(int argc, char **argv) {
        double x, y, elozo_x, elozo_y;
        double szakasz, megtett_ut=0, max_seb=0;
        FILE *in;
    
        if (argc < 2 || (in=fopen(argv[1], "rt")) == NULL)
            return 0;
    
        fscanf(in, "%lf%lf ", &x, &y);
        elozo_x=x; elozo_y=y;
    
        while (fscanf(in, "%lf%lf ", &x, &y) == 2) {
            szakasz=sqrt((elozo_x-x)*(elozo_x-x)+(elozo_y-y)*(elozo_y-y));
            megtett_ut+=szakasz;
            if (max_seb<szakasz) max_seb=szakasz;
    
            elozo_x=x; elozo_y=y;
        }
    
        fclose(in);
    
        printf("Megtett ut: %lf, max sebesseg: %lf\n", megtett_ut, max_seb);
    
        return 0;
    }
  3. Írj ANSI C függvényt, amely paraméterként kap egy óra és egy perc értéket, és visszatér ennek negyedóra pontosságúra kerekített, szöveges változatával. 24 órás formátumot is tudjon feldolgozni, de az eredményt 12 órás változatban generálja. A sztringet éppen megfelelő méretűre foglalja dinamikusan, és a címét adja vissza. Egészítsd ki a kódot teljes programmá, amelyben meghívod a függvényt, és kiírod az eredményt.
    Pl: 3:39->"háromnegyed négy" 0:12->"negyed egy", 14:27->"fél három"
  4. Megoldás

    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    char *ora_szoveg(int ora, int perc) {
        char *szam[] = {
            "tizenketto", "egy", "ketto", "harom",
            "negy", "ot", "hat", "het", "nyolc",
            "kilenc", "tiz", "tizenegy"
        };
        char *negyed[] = {
            "", "negyed ", "fel ", "haromnegyed "
        };
        int normora, normperc;
        char *idoszoveg;
    
        normperc=((perc+7)/15)%4;
        if (perc>7) ++ora;
        normora=ora%12;
    
        idoszoveg=(char*) malloc(strlen(szam[normora])+strlen(negyed[normperc])+1);
        strcpy(idoszoveg, negyed[normperc]);
        strcat(idoszoveg, szam[normora]);
    
        return idoszoveg;
    }
    
    int main() {
        char *sz_ido=ora_szoveg(23, 16);
        printf("%s\n", sz_ido);
        free(sz_ido);
    
        return 0;
    }
  5. Írj szabványos ANSI C programot, amely a szabványos bemenetről kétféle parancsot fogad:
    • I karakter után bevesz egy szót a bemenetről, és elteszi egy várakozási lista végére,
    • O karakter hatására kiadja a lista elején álló szót a standard kimenetre.
    Feltételezheted, hogy egy szó maximum 30 betűből áll, a bemeneten nincs értelmezhetetlen parancs, és nem próbálunk meg üres listából olvasni. Ha a futás végén a lista nem üres, akkor jelezze a tényt a szabványos kimenetre adott figyelmeztetésben, de ne engedjen memóriaszivárgást. Javasoljuk, hogy írj segédfüggvényeket!
  6. Megoldás

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct listaelem {
        char ertek[31];
        struct listaelem *kov;
    } listaelem;
    
    int vegerol(listaelem **elso, char *visszaertek) {
        listaelem *futo;
    
        if (*elso == NULL)
            return 0;
    
        if ((*elso)->kov == NULL) {
            strcpy(visszaertek, (*elso)->ertek);
            free(*elso);
            *elso=NULL;
            return 1;
        }
    
        for (futo=*elso; futo->kov->kov!=NULL; futo=futo->kov)
            ;
        strcpy(visszaertek, futo->kov->ertek);
        free(futo->kov);
        futo->kov=NULL;
        return 1;
    }
    
    void elejere(listaelem **elso, char *ertek) {
        listaelem *uj=(listaelem*)malloc(sizeof(listaelem));
        strcpy(uj->ertek, ertek);
        uj->kov=*elso;
        *elso=uj;
        return;
    }
    
    int main() {
        listaelem *elso=NULL;
        int parancs;
        char ertek[31];
        while ((parancs=getchar()) != EOF) {
            switch(parancs) {
                case 'I':
                    scanf("%s ", ertek);
                    elejere(&elso, ertek);
                    break;
                case 'O':
                    if (vegerol(&elso, ertek)) /* sikeres kiolvasás */
                        printf("%s ", ertek);
                    break;
            }
        }
    
        if (elso!=NULL) { /* esetleges maradék ürítése */
            printf("takaritsunk");
            do {
                printf(".");
                vegerol(&elso, ertek);
            } while (elso!=NULL);
        }
    
        return 0;
    }

3 Vizsga – 2011. december 20.

    1. Add meg egy függvény prototípusát, amely paraméterként át tudja venni a könyvtári sqrt függvény címét!

      Megoldás

      void fv(double (*p)(double));
    2. Adj meg egy kódrészletet, amely bekér a felhasználótól egy karaktert, és kiírja, hogy a felhasználó „I” vagy „N” betűt adott-e meg, esetleg egyiket sem! Nem használhatsz if utasítást!

      Megoldás

      char ch;
      scanf("%c", &ch);
      switch(ch) {
          case 'I':
          case 'N': printf("%c-t irt\n",ch); break;
          default:  printf("Egyiket sem.\n");
      }
      (Egyéb lehetőségek: ?: operátor, while–break, stb.)
    3. Definiálj felsorolt típust típusdefinícióval, amely alkalmas a négy égtáj tárolására! Hozz létre egy ilyen típusú változót, és adj neki kezdőértéket!
    4. Megoldás

      typedef enum {eszak, del, kelet, nyugat} egtaj;
      egtaj e = eszak;
    5. Írj függvényt, amely az első paraméterként átvett sztring végére fűzi a második paraméterként kapott sztringet (my_strcat)! Más függvényt nem hívhatsz!

      Megoldás

      void my_strcat(char *cel, char *forras) {
          int i,j;
          for (i = 0; cel[i] != '\0'; i++)
              ;
          for (j = 0; forras[j] != '\0'; j++)
              cel[i+j] = forras[j];
          cel[i+j]='\0';
      }
    6. Definiálj típust egy valós számokat tároló egyszeresen láncolt lista létrehozásához! Írj függvényt, amely paraméterként veszi át egy ilyen elemekből álló lista első elemének címét, és visszaadja, hogy a listában hány negatív értékű szám található!

      Megoldás

      typedef struct elem {
          double szam;
          struct elem *next;
      } elem;
      
      int szamol(elem *lista) {
          int db;
          for (db = 0; lista!=NULL; lista = lista->next)
              if (lista->szam < 0.0)
                  db++;
          return db;
      }
    7. Írj rekurzív függvényt n faktoriálisának kiszámítására!

      Megoldás

      int fakt(int n) {
          if (n<2) return 1;
          return n*fakt(n-1);
      }
  1. Írj függvényt, amely meghatározza, és visszatérési értékként visszaadja, hogy mekkora az átvett előjel nélküli egészben a leghosszabb összefüggő 1-es bitsorozat! Tömböt nem használhatsz. Pl. 77 binárisan 000...0001001101, a visszatérési érték: 2. Írj rövid főprogramot, amelyben kérsz a felhasználótól egy számot, és kiszámolod ezt az értéket!

    Megoldás

    #include <stdio.h>
    
    int osszefuggo(unsigned be) {
        int max = 0, db = 0;
        while (be != 0) {
            if ((be & 1) == 1) {
                db++;
                if (db > max)
                    max = db;
            }
            else
                db=0;
    
            be >>= 1;
        }
        return max;
    }
    
    int main() {
        unsigned x;
        scanf("%u", &x);
        printf("%d", osszefuggo(x));
        return 0;
    }
  2. Írj programot, amely tömörített és darabokra vágott fájlokat egyesít a következők szerint! Parancssori paraméterként tetszőleges számú fájl nevét kapja. Az utolsó parancssori paraméter a kimeneti fájl, a többi a bemeneti fájlok neve. A bemeneti fájlokat bájtonként olvasva, ha 77-es értékű bájtot talál, az azt követő két bájt közül az első egy darabszám, a második pedig az a bájt, amelyiknek a darabszámát az első jelzi. A program írja a bemeneti fájlok tartalmát egymás után a kimeneti fájlba úgy, hogy a tömörített részeket kitömöríti! Pl. be … 153, 0, 77, 4, 8, 67, 254, …, ki: … 153, 0, 8, 8, 8, 8, 67, 254… (Tömörített bájthármas garantáltan nincs kettévágva más-más bemeneti fájlba. Ha kettőnél kevesebb fájlnevet kap a program, adjon hibajelzést és lépjen ki! A fájlokat bináris fájlként kezelje! A megoldáshoz nem szükséges állapotgép.)

    Megoldás

    #include <stdio.h>
    
    void masol(FILE *be, FILE *ki) {
        unsigned char byte, db, i;
        while (fread(&byte, 1, 1, be)==1) {
            if (byte == 77) {
                fread(&db, 1, 1, be);
                fread(&byte, 1, 1, be);
                for (i = 0; i < db; i++)
                    fwrite(&byte, 1, 1, ki);
            }
            else
                fwrite(&byte, 1, 1, ki);
        }
    }
    
    int main(int db, char **pars) {
        FILE *be, *ki;
        int i;
        if (db<3) {
            printf("Keves fajl\n");
            return 1;
        }
        ki=fopen(pars[db-1],"wb");
        if (ki==NULL)return 1;
        for (i = 1; i < db - 1; i++) {
            be = fopen(pars[i],"rb");
            if (be==NULL)
                return 1;
            masol(be,ki);
            fclose(be);
        }
        fclose(ki);
        return 0;
    }
  3. Írj függvényt, amely paraméterként vesz át egy egész számokból álló tömböt, és kiegyensúlyozott bináris rendezőfát épít belőlük a következők szerint. A paraméterként átvett tömböt megváltoztatni nem szabad, ezért másolatot kell róla készíteni, majd a másolatot nagyság szerint rendezni. A nagyság szerint rendezett tömb középső eleme kerüljön be a bináris fa gyökerébe, a két fél tömb középső eleme legyen a gyökér két gyermeke, stb. (Páros elemszám esetén a két középső elem egyike, bármelyik kerüljön a gyökérbe.) Ügyelj rá, hogy a bináris fába bekerüljön minden elem a tömbből! Segédfüggvény(ek) írása kifejezetten ajánlott. A függvény adja vissza a bináris fa gyökerének címét! Definiáld a szükséges típus(oka)t is!

    Megoldás

    typedef struct bifa {
        int adat;
        struct bifa *bal, *jobb;
    } bifa;
    
    int *masol(int tomb[], int n) {
        int *uj = (int*)malloc(n*sizeof(int)), i;
        for (i=0; i<n; i++)
            uj[i] = tomb[i];
        return uj;
    }
    
    void rendez(int tomb[], int n) {
        int i, j, mi, temp;
        for (i = 0; i < n - 1; i++) {
            mi = i;
            for (j = i + 1; j < n; j++)
                if (tomb[j] < tomb[mi])
                    mi = j;
            if (mi != i) {
                temp = tomb[i];
                tomb[i] = tomb[mi];
                tomb[mi] = temp;
            }
        }
    }
    
    bifa *betesz(bifa *gy, int tomb[], int also, int felso) {
        int kozep = (also + felso) / 2;
        bifa *uj;
        
        if (also > felso)
            return NULL;
        uj = (bifa*) malloc(sizeof(bifa));
        uj->adat = tomb[kozep];
        /* a bal es jobb reszfa egy ures fabol kiindulva epul */
        uj->bal = betesz(NULL, tomb, also, kozep - 1);
        uj->jobb = betesz(NULL, tomb, kozep + 1, felso);
    }
    
    bifa *epito(int tomb[], int n) {
        int *ujtomb = masol(tomb, n);
        bifa *fa;
    
        rendez(ujtomb, n);
        fa = betesz(NULL, ujtomb, 0, n - 1);
        free(ujtomb);
        return fa;
    }

4 Vizsga – 2012. január 3.

    1. Definiálj egy pfv nevű pointert, amely a szabványos strcpy() függvényre tud mutatni.

      Megoldás

      char *(*pfv)(char *, const char *);
    2. Definiálj struktúrát típusdefinícióval, amely egy játékban egy katona adatait tárolja: név (max. 26 betű), erőnlét (0..100), helyzet (x, y koordináta: 0..35).

      Megoldás

      typedef struct Katona {
          char nev[26+1];
          int eronlet;
          int x, y;
      } Katona;
    3. Definiálj egy x előjel nélküli egész számot. Írj programrészt, amely egy ilyen szám alulról 5. bitjét 1-be állítja.

      Megoldás

      unsigned x;
      x |= 1<<5;
    4. Írj C programot, amely kiírja két, parancssori paraméterként átvett egész szám összegét!

      Megoldás

      int main(int argc, char *argv[]) {
          printf("%d", atoi(argv[1])+atoi(argv[2]));
      }
    5. Definiálj valós számokat tároló lista típust! Írj programrészt, amely összegzi egy ilyen elemekből álló, strázsa nélküli listában a tárolt számokat! A lista elejére a p pointer mutat. (Definiáld a változókat!)

      Megoldás

      struct Szam {
          double sz;
          struct Szam *kov;
      };
      
      double osszeg=0;
      struct Szam *p=........, *iter;
      
      for (iter=p; iter!=NULL; iter=iter->kov)
          osszeg+=iter->sz;
    6. Definiálj bináris fa típust, amelynek elemei dinamikusan foglalt sztringeket tárolnak! Írj függvényt, amely felszabadít egy ilyen fát! Feltételezve, hogy adott egy p pointer (definiáld ezt is), mutass példát a függvény hívására!

      Megoldás

      struct Fa {
        char *str;
        struct Fa *bal, *jobb;
      };
      
      void fa_felszab(struct Fa *gyoker) {
        if (gyoker==NULL) return;
        fa_felszab(gyoker->bal);
        fa_felszab(gyoker->jobb);
        free(gyoker->str);
        free(gyoker);
      }
      
      Fa *p=...;
      fa_felszab(p);
  1. Írj függvényt, amely paraméterként vesz át egy nemnegatív egész számot, és a szám kettes számrendszerbeli alakját egy dinamikusan foglalt sztringben állítja elő! Ezt adja vissza egy cím szerint átvett paraméterben. A lefoglalt memóriaterület pontosan akkora legyen, amekkora szükséges, egy bájttal se nagyobb! A függvény működjön helyesen, akárhány bitből is áll a paraméterként kapott szám! Írj főprogramot, amely kér a felhasználótól egy számot, és a függvény meghívása után kiírja a kapott sztringet!

    Megoldás

    #include <stdio.h>
    #include <stdlib.h>
    
    void kettes(unsigned szam, char **pstr) {
        int bitek, i;
        char *str;
    
        for (bitek=0; szam>>bitek > 0; ++bitek)
            ;
        str=malloc((bitek+1)*sizeof(char));
    
        for (i=bitek-1; i>=0; --i)
            str[bitek-1-i]=(szam&(1<<i))!=0 ? '1':'0';
        str[bitek]='\0';
    
        *pstr = str;
    }
    
    int main() {
        char *s;
        unsigned mi;
    
        printf("Mit irjak kettesbe? ");
        scanf("%u", &mi);
    
        kettes(mi, &s);
        printf("%u(10) = %s(2)\n", mi, s);
        free(s);
    
        return 0;
    }
  2. Írj függvényt, amely paraméterként vesz át egy sztringet, és visszatér az abban tárolt római szám számértékével. (M=1000, D=500, C=100, L=50, X=10, V=5, I=1, növekvő helyiértékű pár kivonást jelent. Pl. MCMLXXXVIII=1988.) Írj programot, amely kér a felhasználótól egy római számot, és kiírja azt tízes számrendszerben! (Feltételezhetjük, hogy a beírt szám helyes. Az XXXXXXIIIIIIII is helyes, 68-at jelent!)

    Megoldás

    #include <stdio.h>
    
    int romaiertek(char c) {
        struct Romai {
            char betu;
            int ertek;
        } romai[] = {
            { 'I', 1 },
            { 'V', 5 },
            { 'X', 10 },
            { 'L', 50 },
            { 'C', 100 },
            { 'D', 500 },
            { 'M', 1000 },
            { 0, 0 }
        };
        int i;
        for (i=0; romai[i].ertek!=0; ++i)
            if (c==romai[i].betu)
                return romai[i].ertek;
        return 0;
    }
    
    int romai(char *str) {
        int i, romai;
    
        romai=0;
        for (i=0; str[i]!=0; ++i) {
            int ez=romaiertek(str[i]);
            /* lehet lezaro 0-t is nezi, de nem gond */
            int kovetkezo=romaiertek(str[i+1]);
    
            /* forditva? */
            if (kovetkezo>0 && ez<kovetkezo)
                romai-=ez;
            else
                romai+=ez;
        }
    
        return romai;
    }
    
    int main() {
        char beolv[20];
    
        printf("Kerem a szamot! ");
        scanf("%s", beolv);
    
        printf("Szerintem: %d\n", romai(beolv));
        return 0;
    }
  3. A Mátrában túráztunk. Utunk során pillanatnyi helyzetünket egy GPS egység percenként rögzítette. A Kékestető koordinátáit, és ezeket az adatokat kell feldolgoznia a programnak. A feladatai a következőek: a) Ki kell írnia, hogy a túra hányadik percében jártunk legközelebb a Kékestetőhöz, és mennyi ez a távolság, b) Ki kell írni az utunk két legtávolabbi pontjának távolságát, azaz az összes lehetséges pontpár távolságának maximumát. A „tura.txt” szöveges fájlban szerepelnek az adatok, x, y és z koordinátával adva, szóközzel elválasztva, soronként. Az első sorban a Kékestető koordinátája van (z=1014 méter), a továbbiak pedig a túrához tartozó koordináták. Ezekből nem tudjuk előre, mennyi lesz, hanem a fájl végéig tartanak – viszont legalább két adat mindenképp lesz. A fájlt csak egyszer szabad beolvasni.

    Megoldás

    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    typedef struct Koord {
       double x, y, z;
       struct Koord *kov;
    } Koord;
    
    Koord *beolvas(char *fnev, Koord *kekes) {
       Koord k, *lista=NULL, *vege;
       FILE *fp;
    
       fp=fopen(fnev, "rt");
       fscanf(fp, "%lf %lf %lf", &kekes->x, &kekes->y, &kekes->z);
       while (fscanf(fp, "%lf %lf %lf", &k.x, &k.y, &k.z)==3) {
          Koord *uj=(Koord*) malloc(sizeof(Koord));
          *uj=k;
          uj->kov=NULL;
          if (lista==NULL) {
             lista=uj;
             vege=uj;
          }
          else {
             vege->kov=uj;
             vege=uj;
          }
       }
       fclose(fp);
    
       return lista;
    }
    
    double tav(Koord k1, Koord k2) {
       return sqrt(pow(k1.x-k2.x,2)
                  +pow(k1.y-k2.y,2)
                  +pow(k1.z-k2.z,2));
    }
    
    void kekeshez_legkozelebb_kiir(Koord *koords, Koord kekes) {
       Koord *pmin, *iter;
       int percmin, i;
    
       pmin=koords;
       percmin=0;
       for (iter=koords->kov, i=1; iter!=NULL; iter=iter->kov, ++i)
          if (tav(*iter, kekes) < tav(*pmin, kekes)) {
             pmin=iter;
             percmin=i;
          }
       printf("Kekeshez legkozelebb: %d. perc, %g meter.\n", percmin, tav(*pmin, kekes));
    }
    
    void ket_legtavolabbi_kiir(Koord *koords) {
       Koord *iteri, *iterj, *mini, *minj;
    
       mini=koords; /* sajat maga - ennel ugyis lesz nagyobb */
       minj=koords;
       for (iteri=koords; iteri->kov!=NULL; iteri=iteri->kov)
          for (iterj=iteri->kov; iterj!=NULL; iterj=iterj->kov) {
             if (tav(*iteri, *iterj) > tav(*mini, *minj)) {
                mini=iteri;
                minj=iterj;
             }
          }
       printf("Legtavolabbi pontok tavolsaga: %g\n", tav(*mini, *minj));
    }
    
    int main() {
       Koord *koords, kekes;
    
       /* beolvas */
       koords=beolvas("tura.txt", &kekes);
    
       /* kekeshez legkozelebbi, ket legtavolabbi */
       kekeshez_legkozelebb_kiir(koords, kekes);
       ket_legtavolabbi_kiir(koords);
    
       /* felszabadit */
       while (koords!=NULL) {
          Koord *temp=koords->kov;
          free(koords);
          koords=temp;
       }
       return 0;
    }

5 Vizsga – 2012. január 10.

    1. Írj egy C kifejezést, amely egy három számjegyű szám (n) középső számjegyét adja meg! Pl. 123 középső számjegye 2.

      Megoldás

      n/10%10
      /* vagy */
      n%100/10
    2. Mennyi sizeof("hello\n\n")?
      8 = 5+2+1 (hello, a két enter és a lezáró nulla).
    3. int tomb[3, 2, 4, 3, 9]; Mennyi az értéke a tomb[*(tomb+2)] kifejezésnek?
      9, mert *(tomb+2) ugyanaz, mint tomb[2], ami 4. tomb[4] pedig 9.
    4. Írj függvényt, amely paraméterként kapja egy Prog1 vizsga pontszámát (0-60), és visszatér egy egész számmal, ami a jegy (1-5).

      Megoldás

      int prog1jegy(int pontszam) {
        if (pontszam<24) return 1;
        if (pontszam<33) return 2;
        if (pontszam<42) return 3;
        if (pontszam<51) return 4;
        return 5;
      }
    5. Írj függvényt, amely visszatér a paraméterként kapott, egészekből álló tömb elemeinek átlagával! Pl. ha a tömb { 1, 2, 3, 4 }, az átlaguk 2,5.

      Megoldás

      double atlag(int tomb[], int meret) {
        double szum;
        int i;
      
        szum=0;
        for (i=0; i<meret; ++i)
          szum+=tomb[i];
      
        return szum/meret;
      }
      /* El kell kerülni az egész osztást! */
      /* Vagy double-ben kell összegezni, vagy (double)szum/meret osztani. */
    6. A program.c nevű forrásfájl így néz ki:
      #include "program.h"
      int egesztomb[12];
      double negyzet(double x) { return x*x; }
      Írd meg az ehhez tartozó program.h fejlécfájlt, amely lehetővé teszi a tömb és a függvény elérését, és többször is beilleszthető egy forrásfájlba!

      Megoldás

      #ifndef PROGRAMH
      #define PROGRAMH
      
      extern int egesztomb[12];
      double negyzet(double x);
      
      #endif
      /* A tömb extern kell legyen, a méretét nem muszáj megadni
         (lehet egesztomb[] is). */
      /* A függvénynek csak a prototípusa kell ";" nem lehet definíció "{}". */
      /* A paraméter neve elmaradhat. */
  1. Készíts függvényt, amely két mátrixot ad össze! A függvény első két paramétere legyen a két összeadandó mátrixra mutató pointer, második kettő pedig a szélesség és a magasság. A mátrixok kétdimenziós, dinamikusan foglalt, double adatokból álló tömbök, amelyben az egyes sorok külön vannak foglalva, és az ezekre mutató pointerek tömbje is dinamikusan foglalt. A visszatérési érték legyen egy ugyanilyen mátrixra mutató pointer, amelyet a függvény foglalt le! Bármilyen memóriakezelési hiba esetén térjen vissza a függvény NULL pointerrel!

    Megoldás

    double **osszead(double **a, double **b, int szel, int mag) {
        double **uj;
        int x, y;
    
        /* pointertomb */
        uj=(double**) malloc(sizeof(double*)*mag);
        if (uj==NULL)
            return NULL;
    
        /* sorok tombjei */
        for (y=0; y<mag; ++y) {
            int yy;
    
            uj[y]=(double*) malloc(sizeof(double)*szel);
            if (uj[y]==NULL) {
                for (yy=0; yy<y; ++yy)
                    free(uj[yy]);
                free(uj);
                return NULL;
            }
        }
    
        for (y=0; y<mag; ++y)
            for (x=0; x<szel; ++x)
                uj[y][x]=a[y][x]+b[y][x];
    
        return uj;
    }
  2. Írj függvényt, amely létrehoz egy listát, amely a paraméterként kapott bináris fa elemeit tartalmazza! A bináris fa eredendően egy keresőfa, rendezett elemekkel (bal részfában kisebbek, jobban nagyobbak). Egész számokat tartalmaz. Erre mutató pointert kell átvennie a függvénynek, továbbá át kell vennie egy listapointert cím szerint is, ahová a keletkező lista kerül. A listába növekvő sorrendben kerüljenek a számok! Definiáld a szükséges típusokat is! Segédfüggvények írása ajánlott. Definiálj mutatókat, amelyek egy fára és a keletkező listára mutatnak, és mutass példát a függvény hívására!

    Megoldás

    typedef struct Lista {
      int adat;
      struct Lista *kov;
    } Lista;
    
    typedef struct Fa {
      int adat;
      struct Fa *bal, *jobb;
    } Fa;
    
    void listaba(Fa *gy, Lista **plist) {
      Lista *uj;
      if (gy==NULL) return;
      listaba(gy->jobb, plist);
      uj=malloc(sizeof(Lista));
      uj->adat=gy->adat;
      uj->kov=*plist;  /* lista elejere szur */
      *plist=uj;
      listaba(gy->bal, plist);
    }
    
    void fabol_lista(Fa *gy, Lista **plist) {
      *plist=NULL;
      listaba(gy, plist);
    }
    
    Fa *binfa = valahonnan_egy_fa();
    Lista *lista;
    fabol_lista(binfa, &lista);
    
    /* Ha jobb-gyökér-bal sorrendben járjuk be a fát, akkor csökkenő sorrendben
       kapjuk az elemeket. Viszont ha ezeket mindig a lista elejére szúrjuk be,
       akkor újra megfordítjuk őket - vagyis növekvő sorrendet kapjuk. Így a
       feladat O(n) időben elvégezhető. Aki így oldotta meg, +4 pontot kapott. */
    /* A feladat megoldható O(n) időben úgy is, ha bal-gyökér-jobb sorrendben
       járjuk be a fát, de van egy valahol nyilvántartott pointer, amivel
       a lista vége mindig elérhető. Aki ilyet csinált, vagy bármi más módon
       megoldotta, hogy O(n) időben fusson a programja, az is kapott +4 pontot. */
  3. Írj programot, amely egy bináris fájlból állít elő C programba illeszthető forráskód részletet! A kódrészletben legyen egy inicializált tömb, amely a fájl bájtjait tartalmazza. Például ha az „adat.dat” bináris fájl bájtjai 12, 87, 255, 75, 0, 212, akkor a keletkező „adat.c” szövegfájl legyen ilyen:

    Megoldás

    unsigned char adattomb[] = {
      12, 87, 255, 75, 0, 212
    };
    A program a bemenő fájl nevét (adat.dat), a kimenő fájl nevét (adat.c) és a tömb nevét (adattomb) parancssori paraméterként vegye át. (Ha nincs ennyi paraméter, adjon hibajelzést! Ha nem nyitható meg valamelyik fájl, akkor is!) Az előállított forráskód legyen „szép”: a számokat tartalmazó sorok maximum 80, de minimum 75 karakterből álljanak (az utolsó lehet rövidebb), a sorok elején legyen két szóköznyi behúzás és az utolsó szám után már ne legyen vessző!

    Megoldás

    #include <stdio.h>
    
    /* a megoldas viszonylag egyszeru, ha valaki emlekszik, hogy a printf
     * visszaadja a kiirt karakterek szamat. ha nem, akkor ugy is lehet
     * szep megoldast csinalni, hogy egy sztringben epitgetunk egy sort,
     * es ha mar nagyon tele van (strlen(sor)>75), akkor kiirjuk a fajlba,
     * es ures sztringgel folytatjuk. */
    int main(int argc, char *argv[]) {
        FILE *fbe, *fki;
        unsigned char c;
        int kiirt, elso;
    
        if (argc<4) {
            fprintf(stderr, "Hasznalat: %s infile outfile tombnev\n", argv[0]);
            return 1;
        }
    
        fbe=fopen(argv[1], "rb");
        if (fbe==NULL) {
            fprintf(stderr, "%s nem nyithato\n", argv[1]);
            return 2;
        }
        fki=fopen(argv[2], "wt");
        if (fki==NULL) {
            fprintf(stderr, "%s nem nyithato\n", argv[2]);
            return 3;
        }
    
        fprintf(fki, "unsigned char %s[] = {\n", argv[3]);
    
        fprintf(fki, "  ");
        kiirt=2;
        elso=1;
        while (fread(&c, 1, 1, fbe)>0) {
            if (!elso)
                kiirt+=fprintf(fki, ", ");
            if (kiirt>75) {
                fprintf(fki, "\n  ");
                kiirt=2;
            }
            kiirt+=fprintf(fki, "%u", (unsigned int) c);
            elso=0;
        }
    
        fprintf(fki, "\n};\n");
        fclose(fbe);
        fclose(fki);
        return 0;
    }

6 Vizsga – 2012. január 12.

    1. Definiálj egy előjel nélküli x egész számot. Írj programrészt, amely 0-ba állítja az 5. bitjét (alulról, 0.-tól számítva), a többit pedig változatlanul hagyja. (A bit helyiértékét ne magad számold ki, hanem a C kóddal oldd meg ezt!)

      Megoldás

      unsigned x;
      x &= ~(1<<5);
    2. Foglalj 101 elemű, valósakból álló tömböt dinamikusan! Töltsd fel úgy, hogy minden eleme a pi értékét tárolja! Szabadítsd fel!

      Megoldás

      int i;
      double *din = (double*) malloc(sizeof(double)*101);
      
      for (i=0; i<101; ++i)
        din[i]=3.14;
      free(din);
    3. Írj C függvényt, amely paraméterként egy egész számot vesz át cím szerint, amelyet ellentettjére változtat!

      Megoldás

      void ellentett(int *pi) {
        *pi = *pi * -1;   /* vagy *pi = -*pi; */
      }
    4. Definiálj felsorolt típust a négy évszakhoz: tavasz, nyár, ősz, tél. Írj függvényt, amely paraméterként egy hónap sorszámot kap (1…12), és visszatér azzal, hogy milyen évszakhoz tartozik az. (Pl. 6=nyár.)

      Megoldás

      enum evszak { tavasz, nyar, osz, tel };
      
      enum evszak melyikevszak(int honap) {
        if (honap>=3 && honap<=5) return tavasz;
        if (honap>=6 && honap<=8) return nyar;
        if (honap>=9 && honap<=11) return osz;
        return tel;
      }
    5. Definiálj lista struktúrát, amely maximum 30 betűs szavakat tárol. Írj függvényt, amely paraméterként átvesz egy ilyen listát, és megadja, hogy mennyi a benne tárolt szavak összegzett hossza! (Pl. alma, retek, dinnye összesen 15 betű.)

      Megoldás

      typedef struct Lista {
        char szo[30+1];
        struct Lista *kov;
      };
      
      int osszhossz(Lista *eleje) {
        int sum=0;
        Lista *iter;
        for (iter=eleje; iter!=NULL; iter=iter->kov)
          sum+=strlen(iter->szo);
        return sum;
      }
    6. Írj egy programot, amely 1-től 100-ig kiírja a számokat, mindegyiket külön sorba. 3 többszörösei helyett fizz, 5 többszörösei helyett buzz legyen kiírva. Ha egy szám mindkettőnek többszöröse, akkor fizzbuzz.

      Megoldás

      #include <stdio.h>
      
      int main() {
          int i;
          for (i=1; i<=100; ++i) {
              if (i%3==0) printf("fizz");
              if (i%5==0) printf("buzz");
              if (i%3!=0 && i%5!=0) printf("%d", i);
              printf("\n");
          }
          return 0;
      }
    1. Definiálj struktúrát bináris fához, amely valós számokat tárol!
    2. Írj függvényt, amely felszabadít egy ilyen fát!
    3. Írj függvényt, amely paraméterként veszi át egy ilyen fa gyökerét, és visszatér egy számmal, amely azt mutatja, hogy hányadik szintig van teljesen betöltve a fa!

    Megoldás

    typedef struct BiFa {
       double szam;
       struct BiFa *bal, *jobb;
    } BiFa;
    
    void felszabadit(BiFa *gyoker) {
       if (gyoker==NULL) return;
       felszabadit(gyoker->bal);
       felszabadit(gyoker->jobb);
       free(gyoker);
    }
    
    int betoltott(BiFa *gyoker) {
       int b, j;
       /* ures fa - 0 betoltott szint */
       if (gyoker==NULL)
          return 0;
    
       /* ha ez betoltott, akkor annyira van az egesz fa betoltve, amennyire
        * a reszfak kozul az alacsonyabb teljesen betoltott.
        * plusz egy, mert ahol most allunk, az is egy szint. */
       b=betoltott(gyoker->bal);
       j=betoltott(gyoker->jobb);
       if (b<j)
          return b+1;
       else
          return j+1;
    
    }
    A betöltöttséghez: az üres részfa betöltöttsége 0. Amúgy pedig a kevésbé betöltött részfa betöltöttsége +1 (ez a szint). Ha valamelyik részfa null pointer, akkor az arra meghívott függvény visszatér nullával, ami biztosan kisebb lesz a másik részfára meghívott függvény visszatérési értékénél (vagy esetleg az is nulla), így ez abban az esetben is jó.
  1. Írj programot, amely parancssori paraméterként kap egy fájlnevet, továbbá egy sor- és egy karakterszámot. Írja ki a szövegfájlból a megadott sor megadott sorszámú karakterét! Pl. a szoveg.txt nevű fájl 3. sorának 5. karakterét. A sorszámozások 1-től indulnak. Ha nem három parancssori paraméter van, vagy a fájl nem létezik, vagy nincs annyi sora, vagy a megadott sor nem olyan hosszú, mint kellene, akkor adjon a program hibaüzenetet.

    Megoldás

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char *argv[]) {
       int sor, oszlop;
       FILE *fp;
       int c, y, hamarvege;
    
       if (argc-1!=3) {
          printf("Harom parameter kell!\n");
          return 1;
       }
       sor=atoi(argv[2]);
       oszlop=atoi(argv[3]);
    
       fp=fopen(argv[1], "rt");
       if (fp==NULL) {
          printf("Nincs ilyen fajl!");
          return 1;
       }
    
       hamarvege=0;
       for (y=1; y<sor && !hamarvege; ++y) {
          do
             c=fgetc(fp);
          while (c!=EOF && c!='\n')
          if (c==EOF)
             hamarvege=1;
       }
    
       if (!hamarvege)
          for (y=1; y<=oszlop && !hamarvege; ++y) {
             c=fgetc(fp);
             if (c==EOF || c=='\n')
                hamarvege=1;
          }
    
       if (!hamarvege)
          printf("A karakter: '%c'\n", c);
       else
          printf("Nincs ilyen karakter.\n");
    
       return 0;
    }
  2. Írj programot, amely a szabványos bemenetén érkező szöveget tördel sorokra! A beérkező szövegben nagyon hosszú sorok vannak, amelyek a szöveg bekezdései. Ezek szóközzel elválasztott szavakat tartalmaznak. Olvassa be ezeket a program, és építsen belőlük láncolt listát! A láncolt lista elemei a sorok, amelyek a lehető leghosszabbak, de maximum 79 karakteresek lehetnek. A beolvasás végeztével írd ki a tördelt szöveget! A szöveg szavai nem hosszabbak egy sornál. A bekezdések bármilyen hosszúak lehetnek. A szavakat elválasztani nem kell. Új bekezdésnél azonban, az addig elkezdett sor legyen akármilyen rövidre sikerült, mindig új sort kell kezdeni. (Érdemes a szavak utáni írásjeleket (vessző, pont stb.) a szavakkal együtt beolvasni, amúgy sincsen előttük szóköz.)

    Megoldás

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    #define SORHOSSZ 79
    
    typedef struct Sor {
        char szoveg[SORHOSSZ+1];
        struct Sor *kov;
    } Sor;
    
    /* ez foglal egy új sort, és visszatér a pointerével,
     * amit a megadott helyre is betesz. azt a pointert kell
     * adni neki paraméterként (cím szerint), ahova a következő
     * sor lista láncszem kerül. */
    Sor *ujsor(Sor **ideptr) {
        Sor *uj = (Sor*) malloc(sizeof(Sor));
        strcpy(uj->szoveg, "");
        uj->kov=NULL;
        *ideptr = uj;
        return uj;
    }
    
    int main() {
        Sor *lista=NULL, *iter, *aktualis;
        int tornikell;
        char szo[SORHOSSZ+1], elvalaszto;
    
        /* szo es utana levo karakter beolvasasa */
        while (scanf("%s%c", szo, &elvalaszto)>=1) {
            /* ha nincs meg semmi, tuti kell egy sornak helyet foglalni */
            if (lista==NULL)
                aktualis = ujsor(&lista);
            /* ha az uj szo nem fer a sor vegere, torni kell */
            tornikell=strlen(aktualis->szoveg)+strlen(szo)+1>SORHOSSZ;
            /* ha torni kell, kezdjunk uj sort */
            if (tornikell)
                aktualis = ujsor(&aktualis->kov);
            /* mire ide eljutunk, akarhogy is, de az aktualis vegehez fuzhetjuk a szot */
            strcat(aktualis->szoveg, szo);
    
            if (elvalaszto=='\n')
                /* ha a szo utan enter volt, kezdeni kell egy uj sort */
                aktualis = ujsor(&aktualis->kov);
            else
                /* amugy egy szokoz kell, hogy a kovetkezo szot ne irjuk egybe vele */
                strcat(aktualis->szoveg, " ");
        }
    
        /* kiiras */
        for (iter=lista; iter!=NULL; iter=iter->kov)
            printf("%s\n", iter->szoveg);
    
        /* felszabaditas */
        while (lista!=NULL) {
            Sor *temp=lista->kov;
            free(lista);
            lista=temp;
        }
    
        return 0;
    }

7 Vizsga – 2012. január 17.

    1. Írj egy C logikai kifejezést, amelynek az értéke igaz, ha a szam nevű egész változó értéke 20-szal osztható, de 30-cal nem!

      Megoldás

      (szam % 20 == 0) && (szam % 30 != 0)
    2. Írj C kifejezést, amely megadja az 5.75-ös érték címét az alábbi, konkrét tömbben!
      double t[] = {2.34, 8.23, 5.75, 4.29};

      Megoldás

      t+2 /∗ VAGY ∗/ &t[2]
    3. Tudjuk, hogy programunk első két parancssori paramétere egy-egy 0 és 9 közötti egész szám. Írj C kifejezést, ami egy egész változóban elmenti a két paraméter szorzatát!

      Megoldás

      int i = (argv[1][0] - '0') * (argv[2][0] - '0');
    4. Egészítsd ki az alábbi C függvényt úgy, hogy a paraméterként kapott, egyváltozós f matematikai függvénynek keresse meg a lokális minimumát az [a, b] intervallumban dx lépésközzel!

      Megoldás

      double min(double (*f)(double), double a, double b, double dx) {
      
          double x, min = f(a);
      
          for (x = a + dx; x <= b; x += dx) {
              if (min > f(x)) min = f(x);
          }
      
          return min;
      }
    5. Írj C függvényt, amely átveszi paraméterként egy olyan megnyitott szövegfájl FILE pointerét, amely soronként egy IP címet tartalmaz a következő formában: 152.66.72.26 – négy, előjel nélküli, egybájtos érték pontokkal elválasztva. A függvény írja ki az összes olyan IP címet a fájlból, amelynek első két bájtja: 152, 66 (ebben a sorrendben) és a harmadik bájt 0 és 127 közötti értékű! Például a 152.66.115.224 sort írja ki, de a 152.66.252.25 sort ne!

      Megoldás

      void ip_kiir(FILE *cimek) {
          unsigned elso, masodik, harmadik, negyedik;
      
          while (EOF != fscanf(cimek, "%u.%u.%u.%u",
                  &elso, &masodik, &harmadik, &negyedik)) {
      
              if (elso==52 && masodik==66 && harmadik<=127) {
                  printf("%u.%u.%u.%u\n", elso, masodik, harmadik,
                          negyedik);
              }
          }
      }
    6. Definiálj listát, amely neveket tárol 50 karakteren! Írj C függvényt, amely átveszi a lista elejének a címét és kiír minden második nevet a listában! Az első kiírt név a lista második eleme legyen!

      Megoldás

      typedef struct lista {
          char nev[51];
          struct lista *kov;
      } lista;
      
      void minden_masodik(lista *eleje) {
          int paros = 0;
          lista *mozgo;
      
          for (mozgo=eleje; mozgo != NULL; mozgo=mozgo->kov) {
              if (paros) printf("%s\n", mozgo->nev);
              paros = !paros;
          }
      }
  1. Definiálj bináris rendező fa struktúrát, amely szavak egy fájlban való előfordulási gyakoriságát tárolja! Legyen képes eltárolni maximum 25 karakteres szavakat és egy egész számot! A fa a szavak abc-beli sorrendje szerint rendezett.
    Írj függvényt, ami átveszi egy ilyen fa gyökerének a címét, és megkeresi azt a szót, amely a legtöbbször fordult elő. Írj kódrészletet, amely kiírja a függvény által megkeresett szót, majd felszabadítja a fát!

    Megoldás

    typedef struct fa {
        char szo[26];
        int db;
        struct fa *bal, *jobb;
    } fa;
    
    fa *legtobbszor(fa *gyoker) {
        if (gyoker == NULL) return NULL;
        else {
            fa *bal = legtobbszor(gyoker->bal);
            fa *jobb = legtobbszor(gyoker->jobb);
            fa *max;
    
            if (bal == NULL) max = jobb;
            else if (jobb == NULL) max = bal;
            else {
                max = (bal->db > jobb->db) ? bal : jobb;
            }
    
            if(max == NULL || gyoker->db > max->db) {
                max = gyoker;
            }
    
            return max;
        }
    }
    
    void fa_torol(fa *gyoker) {
        if (gyoker != NULL) {
            fa_torol(gyoker->bal);
            fa_torol(gyoker->jobb);
            free(gyoker);
        }
    }
    
    int main() {
        fa *statisztika = ......., *legtobb;
    
        legtobb = legtobbszor(statisztika);
        printf("%s", legtobb->szo);
    
        fa_torol(statisztika);
        return 0;
    }
  2. Írj C programot, amely egy HTML fájl nevét kapja parancssori argumentumként! A program írja ki az összes olyan kódrészletet, amely kövér betűkkel jelenítendő meg! HTML-ben a kövér betűs részeket a HTML így jelöli: <b>szöveg</b>. Vigyázat: a <b> és </b> jelölők között tetszőleges egyéb HTML elem (pl. <em>, <span>, stb.) is szerepelhet!
    A feladatot állapotgéppel oldd meg! Add meg az állapottáblát és írd meg a nyitó elemhez (<b>) tartozó állapotok programkódját! A program többi részét (parancssori argumentumok átvétele, fájlkezelés, stb.) is ki kell dolgozni!

    Megoldás

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char *argv[]) {
        FILE *html;
        enum allapot {
            ALAP,     NYITO_KM, NYITO_B,
            KOVERBEN, ZARO_KM,  ZARO_PER,
            ZARO_B
        } allapot = ALAP;
        char c;
    
        if (argc != 2) {
            printf("Helyes hívás: %s html_fajl\n", argv[0]);
            return 1;
        }
    
        html = fopen(argv[1], "rt");
    
        while (EOF != (c = fgetc(html))) {
            switch (allapot) {
                case ALAP:
                    if (c == '<') allapot = NYITO_KM;
                    break;
                case NYITO_KM:
                    if (c == 'b') allapot = NYITO_B;
                    else allapot = ALAP;
                    break;
                case NYITO_B:
                    if (c == '>') allapot = KOVERBEN;
                    else allapot = ALAP;
                    break;
        /********** eddig kellett az állapotgép **********/
    
                case KOVERBEN:
                    if (c == '<') allapot = ZARO_KM;
                    else putchar(c);
                    break;
                case ZARO_KM:
                    if (c == '/') allapot = ZARO_PER;
                    else {
                        printf("<%c", c);
                        allapot = KOVERBEN;
                    }
                    break;
                case ZARO_PER:
                    if (c == 'b') allapot = ZARO_B;
                    else {
                        printf("</%c", c);
                        allapot = KOVERBEN;
                    }
                    break;
                case ZARO_B:
                    if (c == '>') allapot = ALAP;
                    else {
                        printf("</b%c", c);
                        allapot = KOVERBEN;
                    }
                    break;
            }
        }
    
        fclose(html);
        puts("");
    
        return 0;
    }
  3. Valósítsd meg egy mobiltelefon számlista alkalmazását! A telefonszámok az ismerősök nevei szerint vannak rendezve és végig lehet rajtuk lépdelni úgy, hogy az utolsó után megint az elsőre ugorjunk, valamint amikor hívást fogadunk, a szám alapján ki lehet keresni a hívó nevét.
    Definiálj adatszerkezetet, amellyel láncolt listában tárolhatjuk el az ismerősöket (egy max. 25 karakteres név és egy max. 15 karakteres telefonszám formájában). A telefonszám kezdődhet 0-val és ’+’-szal, ezért tároljuk karakteresen. Írd meg az elore és hatra függvényeket, amelyekkel a megadott irányba tudunk lépdelni a listában! Ezek átveszik a listában az aktuális pozícióra mutató pointert és visszatérnek az adott irányban soronkövetkező pozíción található elem címével. Ügyelj arra, hogy a függvényeknek a lépdelésnél körbe kell tudni érni a listán! Írd meg a keres_nev függvényt, amely átveszi a listát és egy számot, és visszatér a hozzátartozó nevet tároló sztring címével! A függvény NULL pointert adjon vissza, ha a szám nem szerepel a listában!
    Írj C programot, amely egy „ismerosok.txt” nevű szövegfájlból feltölti a listát. A fájl szerkezete a következő: minden páratlan sorban egy név áll, minden párosban egy telefonszám.

    Megoldás

    typedef struct ismeros {
        char nev[26];
        char szam[16];
        struct ismeros *elozo, *kov;
    } ismeros;
    
    typedef struct szamlista {
        ismeros elso;
        ismeros utolso;
    } szamlista;
    
    
    ismeros *elore(szamlista *lista, ismeros *aktualis) {
        if (aktualis->kov == &(lista->utolso)) {
            return lista->elso.kov;
        }
        else return aktualis->kov;
    }
    
    ismeros *hatra(szamlista *lista, ismeros *aktualis) {
        if (aktualis->elozo = &(lista->elso)) {
            return lista->utolso.elozo;
        }
        else return aktualis->elozo;
    }
    
    char *keres_nev(szamlista *lista, const char *szam) {
        ismeros *mozgo;
        for (mozgo = lista->elso.kov; mozgo != &(lista->utolso)
          && 0 != strcmp(mozgo->szam, szam); mozgo = mozgo->kov);
        if (mozgo == &(lista->utolso)) return NULL;
        else return mozgo->nev;
    }
    
    int main() {
        szamlista lista = {{"", "", NULL, NULL},
                           {"", "", NULL, NULL}};
        FILE *ismerosok;
        char sor[27];
        int paratlan = 1;
    
        lista.elso.kov = &(lista.utolso);
        lista.utolso.elozo = &(lista.elso);
    
        ismerosok = fopen("ismerosok.txt", "rt");
    
        while (NULL != fgets(sor, 26, ismerosok)) {
            ismeros *uj_ismeros;
            sor[strlen(sor) - 1] = '';
    
            /*
            Feltételezhetjük, hogy a fájl helyes --
            nem kell ennyire alapos hibakezelés     */
            if (paratlan) {
                ismeros *mozgo;
                paratlan = !paratlan;
    
                uj_ismeros = (ismeros *)(malloc(sizeof(ismeros)));
                strcpy(uj_ismeros->nev, sor);
    
                for (mozgo = lista.elso.kov; mozgo != &(lista.utolso)
                  && 0 < strcmp(sor, mozgo->nev); mozgo = mozgo->kov);
    
                mozgo->elozo->kov = uj_ismeros;
                uj_ismeros->elozo = mozgo->elozo;
                uj_ismeros->kov = mozgo;
                mozgo->elozo = uj_ismeros;
            }
            else {
                paratlan = !paratlan;
                strncpy(uj_ismeros->szam, sor, 15);
            }
        }
    
        fclose(ismerosok);
    
        return 0;
    }