KZH-k régebbről – megoldásokkal

Régebben kiadott KZH feladatok és megoldásaik, vegyesen a gyakorlati kis zh-kból és a laboron szereplőkből.

1 Ciklusok

Add meg az algoritmus pszeudokódját, és készítsd el a programot C nyelven! A program kötelezően a pszeudokódot valósítsa meg!

1.

Egy program bekér a felhasználótól két pozitív egész számot, és kiírja a két szám közötti összes páratlan számot. A program akkor is helyesen működik, ha a felhasználó előbb a felső, aztán az alsó határt adja meg (és fordítva is).

Megoldás

Első és második szám bekérése
Ha első > második
    alsó = második, felső = első
Egyébként
    alsó = első, felső = második
A ciklusváltozó legyen alsó
Amíg a ciklusváltozó kisebb vagy egyenlő a felsővel
    Ha a ciklusváltozó páratlan
       Írd ki a ciklusváltozót
    Növeld a ciklusváltozót eggyel
#include <stdio.h>

int main() {
    int elso, masodik, also, felso, i;

    printf("Elso = ");       scanf("%d",&elso);
    printf("Masodik = ");    scanf("%d",&masodik);

    if (elso > masodik) { also = masodik; felso = elso; }
    else { also = elso; felso = masodik; }

    for (i = also; i <= felso; i = i + 1)
        if (i % 2 == 1) printf("%d ",i);

    return 0;
}

2.

Egy program bekér a felhasználótól két pozitív egész számot, és megszámolja, hogy a két szám között hány 3-mal osztható, de 5-tel nem osztható szám áll, végül kiírja a darabszámot. A program akkor is helyesen működik, ha a felhasználó előbb a felső, aztán az alsó határt adja meg (és fordítva is).

Megoldás

Első és második szám bekérése
Ha első > második
    alsó = második, felső = első
Egyébként
    alsó = első, felső = második
Darabszám = 0, ciklusváltozó = alsó
Amíg ciklusváltozó kisebb, mint felső
    Ha alsó osztható hárommal, de nem osztható öttel
        Darabszám növelése eggyel
    Alsó növelése eggyel
#include <stdio.h>

int main() {
    int elso, masodik, also, felso, darab,i;

    printf("Elso = ");       scanf("%d",&elso);
    printf("Masodik = ");    scanf("%d",&masodik);

    if (elso > masodik) { also = masodik; felso = elso; }
    else { also = elso; felso = masodik; }

    darab = 0;
    for (i = also; i <= felso; i = i + 1)
        if (i%3 == 0 && i%5 != 0)
            darab = darab + 1;

    printf("%d ", darab);

    return 0;
}

3.

Egy program bekér a felhasználótól két pozitív egész számot, és kiírja a két szám közötti összes 7-tel osztható páratlan számot. A program akkor is helyesen működik, ha a felhasználó előbb a felső, aztán az alsó határt adja meg (és fordítva is).

Megoldás

Első és második szám bekérése
Ha első > második
    alsó = második, felső = első
Egyébként
    alsó = első, felső = második
A ciklusváltozó legyen alsó
Amíg ciklusváltozó kisebb, mint felső
    Ha ciklusváltozó páratlan és osztható 7-tel
        írd ki ciklusváltozót
    növeld ciklusváltozó eggyel
#include <stdio.h>

int main() {
    int elso, masodik, also, felso, i;

    printf("Elso = ");       scanf("%d",&elso);
    printf("Masodik = ");    scanf("%d",&masodik);

    if (elso > masodik) { also = masodik; felso = elso; }
    else { also = elso; felso = masodik; }

    for (i = also; i < felso; i = i + 1)
        if (i % 2 == 1 && i % 7 == 0)  printf("%d ", i);

    return 0;
}

4.

Egy program bekér a felhasználótól két pozitív egész számot, és kiszámítja a két szám közötti összes 5-tel osztható páros szám összegét, majd ennyi * karaktert ír a képernyőre. A program akkor is helyesen működik, ha a felhasználó előbb a felső, aztán az alsó határt adja meg (és fordítva is).

Megoldás

Első és második szám bekérése
Ha első > második
    alsó = második, felső = első
Egyébként
    alsó = első, felső = második
Összeg = 0, ciklusváltozó = alsó
Amíg ciklusváltozó kisebb, mint felső
    Ha ciklusváltozó osztható 10-zel
        Összeget növeld ciklusváltozóval
    növeld ciklusváltozót eggyel
Ciklusváltozó = 0
Amíg ciklusváltozó < összeg
    írj ki egy csillagot
    ciklusváltozót növeld eggyel
#include <stdio.h>

int main() {
    int elso, masodik, also, felso, sum, i;

    printf("Elso = ");       scanf("%d",&elso);
    printf("Masodik = ");    scanf("%d",&masodik);

    if (elso > masodik) { also = masodik; felso = elso; }
    else { also = elso; felso = masodik; }

    sum = 0;
    for (i = also; i <= felso; i = i + 1)
        if (i % 10 == 0)  sum += i;

    for (i = 0; i<sum; i = i + 1) printf("*");

    return 0;
}

5.

Egy program megkérdezi a felhasználótól, hogy hány darab szám összegét kívánja kiszámolni, majd bekér ennyi darab egész számot. Utána kiírja a számok összegét úgy, hogy az összegben ne legyen benne a felhasználó által megadott legnagyobb szám. (Az összeg így éppen a maximummal kevesebb.) Pl. ha a felhasználó 4 számot ad: -1, 10, 5, 7, akkor a kiírt összeg 11 lesz, mert -1+5+7=11.

Megoldás

Darabszám bekérése
Összeg = 0
Ciklusváltozó = 0
Amíg ciklusváltozó kisebb, mint a darabszám
    Kérd be a következő számot
    Ha a ciklusváltozó 0, a maximum legyen egyenlő a számmal
    Egyébkén
        Ha a szám nagyobb a maximumnál
            A maximum legyen egyenlő a számmal
    Az összeghez add hozzá a számot
Írd ki az összeg és a maximum különbségét
#include <stdio.h>

int main() {
    int db, sum, max, akt, i;

    printf("Hany db szamot adsz ossze? ");
    scanf("%d", &db);

    sum = 0;

    for (i = 0; i < db; i = i + 1) {
        printf("A kovetkezo szam: ");
        scanf("%d",&akt);

        if (i == 0)  max = akt;
        else if (akt > max)  max = akt;

        sum += akt;
    }

    /* a trükk: a teljes összegből levonjuk a legnagyobbat. */
    /* így pont olyan lesz, mintha az kimaradt volna az összegből. */
    printf("Osszeg: %d\n", sum - max);

    return 0;
}

2 Rajzolgatás

1.

Írj C programot, amely kér a felhasználótól egy számot, és utána egy akkora, csúcsán álló egyenlőszárú háromszöget rajzol a képernyőre "o" betűkből, hogy annak éppen a megadott számú sora van! Például 3 esetén:

ooooo
 ooo
  o

Megoldás

#include <stdio.h>

int main() {
    int n,i,j;

    printf("Emelet=");
    scanf("%d",&n);

    for (i=0; i<n; i++) {
        for (j=0; j<i; j++)
            printf(" ");
        for (j=0; j<2*(n-i)-1; j++)
            printf("o");
        printf("\n");
    }
    return 0;
}

2.

Írj C programot, amely kér a felhasználótól egy számot, és utána egy akkora, csúcsán álló egyenlőszárú háromszöget rajzol a képernyőre "o" betűkből, hogy annak éppen a megadott számú sora van! Például 3 esetén:

  o
 oo
ooo
 oo
  o

Megoldás

#include <stdio.h>

int main() {
    int n,i,j;

    printf("Emelet=");
    scanf("%d",&n);

    for (i=0; i<n; i++) {
        for (j=0; j<n-i-1; j++) printf(" ");
        for (j=0; j<=i; j++) printf("o");
        printf("\n");
    }
    for (i=1; i<n; i++) {
        for (j=0; j<i; j++) printf(" ");
        for (j=0; j<n-i; j++) printf("o");
        printf("\n");
    }

    return 0;
}

3.

Írj C programot, amely kér a felhasználótól egy szélességet és egy magasságot, és utána egy akkora paralelogrammát rajzol a képernyőre "o" betűkből! Például x=7, y=3 esetén:

  ooooooo
 ooooooo
ooooooo

Megoldás

#include <stdio.h>

int main() {
    int x, y, i, j;

    printf("x="); scanf("%d", &x);
    printf("y="); scanf("%d", &y);

    for (i=0; i<y; i++) {
        for (j=0; j<y-i-1; j++) printf(" ");
        for (j=0; j<x; j++) printf("o");
        printf("\n");
    }

    return 0;
}

3 Számelméleti feladatok

1.

Írj C programot, amely kér a felhasználótól egy pozitív egész számot, és utána kiírja az összes, ennél a számnál kisebb olyan pozitív egész számot, amely nem prím!

Megoldás

#include <stdio.h>

int main() {
    int n, i;

    printf("Max=");
    scanf("%d",&n);

    printf("1\n");
    for (i=2; i<n; i++) {
        int prim = 1, j;
        for (j=2; j<i; j++)
            if (i%j == 0)
                prim = 0;
        if (prim == 0) printf("%d\n",i);
    }

    return 0;
}

2.

Írj C programot, amely kér a felhasználótól egy pozitív egész számot, és kiírja az összes, a megadott értéknél kisebb tökéletes számot! Tökéletes az a szám, amely megegyezik osztóinak összegével, pl.: 28=1+2+4+7+14.

Megoldás

#include <stdio.h>

int main() {
    int n,i;

    printf("Max=");
    scanf("%d",&n);

    printf("1\n");
    for (i=2; i<n; i++) {
        int sum=0, j;
        for (j=1; j<i; j++)
            if (i%j == 0)
                sum += j;
        if (sum==i) printf("%d\n",i);
    }

    return 0;
}

4 Statisztika készítése

Autópálya

Az M7 autópályán traffipax méri az autók sebességét. Minden mérésről három adatot ad: „óra perc sebesség”, szóközzel elválasztva. Pl. „9 39 125” jelentése az, hogy 9:39-kor egy autó 125 km/h-val ment. A 140 km/h feletti sebességért 30 000 Ft a bírság, a 180 km/h felettiért 100 000 Ft. Az adatsor több nap adatait tartalmazza, és a végét 0 0 0 zárja.

Olvassa be a C programod ezeket az adatokat, és írja ki, hogy a nap mely órájában mennyi az összes kirótt bírság! Példa kimenet:

12:00-12:59, 60000 Ft
13:00-13:59, 230000 Ft

Megoldás

#include <stdio.h>

int main() {
   int birsag[24]= {0};
   int ora, perc, seb;
   int i;

   scanf("%d %d %d", &ora, &perc, &seb);
   while (seb!=0) {
      if (seb>180)
         birsag[ora]+=100000;
      else if (seb>140)
         birsag[ora]+=30000;

      scanf("%d %d %d", &ora, &perc, &seb);
   }

   for (i=0; i<24; i+=1)
      printf("%2d:00-%02d:59, %d Ft\n", i, i, birsag[i]);

   return 0;
}

Bliccelés

Egy busztársaság szeretné tudni, a napok mely óráiban hány ellenőrt érdemes terepmunkára küldenie. Ehhez összesítik a bírságok adatait. Egy adat a következőkből áll: „óra perc típus összeg”, ahol a típusnál h a helyszíni bírság, c pedig a csekk. „9 45 c 6000” jelentése: egy utas 9:45-kor csekket kapott 6000 forintról. A helyszíni bírságokat az ellenőrök begyűjtik; a csekkes bírságoknak átlagosan 80%-át tudják behajtani. (Vagyis egy 6000-es csekk a társaság számára átlagosan csak 4800-at ér.) Az adatsor végén 0 0 x 0 szerepel.

Olvassa be a C programod ezeket az adatokat! Készítsen kimutatást arról, hogy mely napszakban mennyi a pótdíjakból a bevétel! Példa kimenet:

16:00-16:59, 14800 Ft
17:00-17:59, 12000 Ft

Megoldás

#include <stdio.h>

int main() {
   int birsag[24]= {0};
   int ora, perc, osszeg;
   char tipus;
   int i;

   scanf("%d %d %c %d", &ora, &perc, &tipus, &osszeg);
   while (tipus!='x') {
      if (tipus=='c')
         osszeg*=0.8;
      birsag[ora]+=osszeg;
      scanf("%d %d %c %d", &ora, &perc, &tipus, &osszeg);
   }

   for (i=0; i<24; i+=1)
      printf("%2d:00-%02d:59, %d Ft\n", i, i, birsag[i]);

   return 0;
}

ZH statisztika

Egy oktató statisztikát szeretne készíteni a megírt ZH-król. A ZH-ban három feladat van, ezek pontszáma nemnegatív egész szám, egyenként max. 10 pont, így az egész max. 30 pontos lehet.

Írj programot, mely a szabványos bemenetéről olvassa be soronként a ZH-k pontszámait. Az adatsort -1 -1 -1 zárja. Írja ki ezután a szabványos kimenetre, hány 0 pontos, hány 1 pontos, … és hány 30 pontos megoldás lett. Ha adott pontszámú dolgozat nem született, a sort ne írja ki.

Példa bemenet:

8 10 7
4 3 5
10 10 9
10 9 10
-1 -1 -1

Példa kimenet:

12 pontos: 1 db
25 pontos: 1 db
29 pontos: 2 db


Megoldás

#include <stdio.h>

int main() {
   int stat[31]= {0};
   int p1, p2, p3, x;

   scanf("%d %d %d", &p1, &p2, &p3);
   while (p1!=-1) {
      int szum=p1+p2+p3;
      ++stat[szum];
      scanf("%d %d %d", &p1, &p2, &p3);
   }

   for (x=0; x<=30; ++x)
      if (stat[x]!=0)
         printf("%2d pontos: %2d db\n", x, stat[x]);

   return 0;
}

Múzeum

Egy múzeumban gazdasági okok miatt heti egy szünnapot szeretnének tartani, ezért keresik a hét azon napját, amikor a legkevesebb a látogató.

Írj programot, mely a szabványos bemenetén fogadja a múzeum napi látogatási adatait úgy, hogy soronként a hét napjának sorszámát kapjuk 1-7 között, majd szóközzel elválasztva a látogatók számát. Az adatok rendezetlenül érkeznek, adott sorszámú naphoz több bejegyzés is tartozhat. A bemenet végét 0 0 jelzi.

Írja ki a program a szabványos kimenetre annak a napnak a sorszámát, amely a legkevesebb látogatót jelenti. Feltételezzük, hogy egy ilyen nap van.

Példa bemenet:

1 7
3 5
6 56
2 3
7 88
5 25
4 7
1 6
0 0

Példa kimenet:

2








Megoldás

#include <stdio.h>

int main() {
   int latogato[7]= {0};
   int nap, db, min, x;

   scanf("%d %d", &nap, &db);
   while (nap!=0) {
      latogato[nap-1]+=db;
      scanf("%d %d", &nap, &db);
   }

   min=0;
   for (x=1; x<7; ++x)
      if (latogato[x]<latogato[min])
         min=x;
   printf("%d\n", min+1);

   return 0;
}

5 Bitek

1.

Mennyi 27|13 ? Írd le mindkét számot, valamint az eredményt is kettes számrendszerben! Az eredményt tízes számrendszerben is add meg!

Megoldás

  27 = 11011
 |13 = 01101
------------
  31 = 11111

Írj függvényt, amely paraméterként kap egy pozitív egész számot, és logikai igazzal tér vissza, ha a szám páros számú 1-es bitet tartalmaz!

Megoldás

int paritas(int szam) {
    int db=0;
    for (; szam!=0; szam>>=1)
        db += szam & 1;
    return (db & 1) == 0;
}

2.

Mennyi 45&57 ? Írd le mindkét számot, valamint az eredményt is kettes számrendszerben! Az eredményt tízes számrendszerben is add meg!

Megoldás

 45 = 101101
&57 = 111001
------------
 41 = 101001

Írj függvényt, amely paraméterként kap egy előjel nélküli egész számot, melyről feltételezzük, hogy 32 bites. A függvény cserélje fel a szám összes szomszédos bitpárját (0. az 1.-vel, 2. a 3.-kal, … 30. a 31.-kel)! A függvény ezt az értéket adja vissza!

Megoldás

Egy egyszerű megoldás:

unsigned csere(unsigned miben) {
    int i;
    unsigned eredmeny = 0;
    for (i = 0; i < 32; i+=2) {
        if (miben & 1<<i)
            eredmeny |= 1<<(i+1);
        if (miben & 1<<(i+1))
            eredmeny |= 1<<i;
    }
    return eredmeny;
}

Egy nagyon trükkös megoldás:

unsigned csere(unsigned szam) {
    return ((szam & 0xaaaaaaaa)>>1) | ((szam & 0x55555555)<<1);
}

3.

Mennyi 27^13 ? Írd le mindkét számot, valamint az eredményt is kettes számrendszerben! Az eredményt tízes számrendszerben is add meg!

Megoldás

 27 = 11011
^13 = 01101
-----------
 22 = 10110

Írj függvényt, amely paraméterként kap egy előjel nélküli egész számot, melyről feltételezzük, hogy 32 bites, és visszatérési értékként adja, hogy a szám hány 0 értékű bitet tartalmaz!

Megoldás

int nullbit(unsigned szam) {
    int db=0, i;
    for (i=0; i<32; szam>>=1, i++)
        db += !(szam & 1);
    return db;
}

4.

Mennyi (~20) & 13 ? Írd le mindkét számot, valamint az eredményt is kettes számrendszerben! Az eredményt tízes számrendszerben is add meg!

Megoldás

 20  = 00010100
~20  = 11101011
&13  = 00001101
---------------
   9 = 00001001

Írj függvényt, amely paraméterként kap egy előjel nélküli egész számot, melyről feltételezzük, hogy 32 bites! A függvény számítsa ki és adja vissza, hogy hány olyan 1-es bit van a számban, amelyet mindkét oldalról 0 bit határol! (Értelemszerűen a legalsó és legfelső bit nem lehet ilyen.) Pl. ha a bemenő bitminta 1011101000010101011001010011111, akkor az eredmény 6.

Megoldás

int egyedulallo(unsigned szam) {
    int db=0, i;
    for (i=0; i<30; i++, szam>>=1)
        if (((szam&7)^2) == 0) db++;
    return db;
}

5.

Mennyi 0x2A | 0x82 ? Írd le mindkét számot, valamint az eredményt is kettes számrendszerben! Az eredményt tizenhatos számrendszerben is add meg!

Megoldás

 0x2A = 00101010
|0x82 = 10000010
----------------
 0xAA = 10101010

Írj függvényt, amely paraméterként kap egy előjel nélküli egész számot, melyről feltételezzük, hogy 16 bites. A függvény tükrözze a szám bitmintáját, az így kapott számot adja vissza! Pl. be: 0011000000000001, ki: 1000000000001100.

Megoldás

int tukroz(int szam) {
    int eredmeny;
    for (eredmeny=0; szam!=0; szam>>=1)
        eredmeny = (eredmeny<<1) + (szam&1);
    return eredmeny;
}

6 Saját sztringkezelő függvények

Összefűzés

Írj függvényt, amely paraméterként vesz át egy cél sztringet, továbbá két másik sztringet és egy elválasztó karaktert! Másolja be a cél sztringbe a másik két sztringet úgy, hogy közéjük az elválasztó karaktert teszi.

Írj főprogramot, amelyben egy példával bemutatod a függvény használatát! A string.h függvényei nem használhatóak!

Példa paraméterek: „alma” és „körte”, továbbá „;”

Példa eredmény: „alma;körte”

Megoldás

#include <stdio.h>

void osszefuz(char *ide, char *egyik, char *masik, char koze) {
   int pos, i;

   pos=0;
   for (i=0; egyik[i]!='\0'; ++i)
      ide[pos++]=egyik[i];
   ide[pos++]=koze;

   for (i=0; masik[i]!='\0'; ++i)
      ide[pos++]=masik[i];
   ide[pos++]='\0';
}

int main() {
   char kesz[20];

   osszefuz(kesz, "alma", "korte", ';');
   printf("%s\n", kesz);

   return 0;
}

Szétválasztás

Írj egy függvényt, amely paraméterként vesz át egy bemeneti sztringet és egy elválasztó karaktert! Legyen még két további paramétere, amelyekbe az eredményt írja. Vágja ketté a függvény a sztringet az első elválasztó karakternél: az eleje menjen az egyik eredmény sztringbe, másik pedig a másikba!

Írj főprogramot, amelyben egy példával bemutatod a függvény használatát! A string.h függvényei nem használhatóak.

Példa paraméterek: „alma;körte” és „;”

Példa eredmény: „alma” és „körte”

Megoldás

#include <stdio.h>

void szeletel(char *be, char elvalaszto, char *egyik, char *masik) {
   int x, pos;

   x=0;
   pos=0;
   while (be[x]!=elvalaszto)
      egyik[pos++]=be[x++];
   egyik[pos]=0;

   x++;
   pos=0;
   while (be[x]!='\0')
      masik[pos++]=be[x++];
   masik[pos]=0;
}

int main() {
   char bal[20], jobb[20];

   szeletel("alma;korte", ';', bal, jobb);
   printf("[%s] es [%s]\n", bal, jobb);

   return 0;
}

Karakterek törlése

Írj függvényt, amely átvesz paraméterként egy módosítandó sztringet és még egy karaktert. Alakítsa át úgy a sztringet úgy, hogy a megadott karaktert törölje a sztring elejéről és a végéről is! Mindkét oldalon lehet több is, vagy akár semennyi. A belsejében viszont tudjuk, hogy nincsen.

Írj főprogramot, amelyben egy példával bemutatod a függvény használatát! A string.h függvényei nem használhatóak.

Példa bemenet: „xxxHello hallo elektor kalandorxxxx” és az „x” karakter

Példa kimenet: „Hello hallo elektor kalandor”

Megoldás

#include <stdio.h>

void sztring_trim(char *str, char mit) {
   int eleje, pos, i;

   eleje=0;

   while (str[eleje]==mit)
      eleje++;
   pos=0;
   for (i=eleje; str[i]!=mit && str[i]!='\0'; i++)
      str[pos++]=str[i];
   str[pos]='\0';
}

int main() {
   char szoveg[]="xxxHello hallo elektor kalandorxxxx";

   sztring_trim(szoveg, 'x');
   printf("[%s]\n", szoveg);

   return 0;
}

Bevezető és lezáró karakterek

Írj függvényt, amely paraméterként átvesz egy cél sztringet, továbbá egy forrás sztringet, egy karaktert és egy darabszámot! Másolja át a cél sztringbe a forrást úgy, hogy elé és mögé a megadott karakterből a megadott darabszámút tegye. Ezen kívül a szóközöket is cserélje ki a megadott karakterre.

Írj főprogramot, amelyben egy példával bemutatod a függvény használatát! A string.h függvényei nem használhatóak.

Példa bemenet: „Hello hallo elektor kalandor”, továbbá az „x” karakter és 3

Példa kimenet: „xxxHelloxhalloxelektorxkalandorxxx”

Megoldás

#include <stdio.h>

void strelemoge(char *ide, char *mit, char kar, int db) {
   int pos, x;

   pos=0;
   for (x=0; x<db; ++x)
      ide[pos++]=kar;

   for (x=0; mit[x]!='\0'; ++x)
      ide[pos++] = mit[x]==' ' ? kar : mit[x];

   for (x=0; x<db; ++x)
      ide[pos++]=kar;

   ide[pos]='\0';
}

int main() {
   char novelt[30];

   strelemoge(novelt, "Hello hallo elektor kalandor", 'x', 3);
   printf("[%s]\n", novelt);

   return 0;
}

7 Állapotgépek

Szmájli számláló

Írj állapotgépes programot, amely a szabványos bemenetről olvasott szövegben megszámolja a szomorú :( és a vidám :) szmájlikat. A számlálás után kiírja, hogy a szöveg vidám, szomorú vagy közömbös, azaz több, kevesebb vagy ugyanannyi :) volt, mint :(.

Tervezd meg az állapotgépet állapot- és tevékenységtáblával, utána írd meg a programot! A programra csak akkor jár pont, ha állapotgépes és a leírt állapottáblát valósítja meg.

Megoldás

: ( ) többi
alap →kp - - -
kp - szom++, →alap vid++, →alap →alap
#include <stdio.h>

int main() {
   enum Allapot { alap, kp } all;
   int szom, vid, c;

   all=alap;
   szom=vid=0;

   while ((c=getchar())!=EOF) {
      switch (all) {
         case alap:
            if (c==':') all=kp;
            break;
         case kp:
            if (c==')')      vid++;
            else if (c=='(') szom++;
            if (c!=':') all=alap;
            break;
      }
   }

   if (vid>szom) printf("vidam");
   else if (szom<vid) printf("szomoru");
   else printf("kozombos");

   return 0;
}

Sz és zs számláló

Írj állapotgépes programot, amely a szabványos bemenetről olvasott szövegben megszámolja az „sz” és a „zs” betűket! (Hosszú ssz és zzs is egynek számítanak, azokkal külön nem kell foglalkozni.) A számlálás után írd ki a szabványos kimenetre mindkettő darabszámát!

Tervezd meg az állapotgépet állapot- és tevékenységtáblával, utána írd meg a programot! A programra csak akkor jár pont, ha állapotgépes és a leírt állapottáblát valósítja meg.

Megoldás

s z többi
alap →svolt →zvolt -
svolt - sz++, →alap →alap
zvolt zs++, →alap - →alap
#include <stdio.h>

int main() {
  enum Allapot { alap, svolt, zvolt } all;
  int c, sz, zs;

  all=alap;
  sz=zs=0;

  while ((c=getchar())!=EOF) {
    switch (all) {
      case alap:
        if (c=='s') all=svolt;
        else if (c=='z') all=zvolt;
        break;
      case svolt:
        if (c=='z') sz++;
        if (c!='s') all=alap;
        break;
      case zvolt:
        if (c=='s') zs++;
        if (c!='z') all=alap;
        break;
    }
  }

  printf("sz: %d, zs: %d\n", sz, zs);

  return 0;
}

Szmájli számláló

Írj állapotgépes programot, amely a szabványos bemenetről olvasott szövegben megszámolja a szomorú :( és a vidám :) szmájlikat. A számlálás után kiírja, hogy a szöveg vidám, szomorú vagy közömbös, azaz több, kevesebb vagy ugyanannyi :) volt, mint :(. A szmájlik zárójelenként egynek számítanak, vagyis :))) három vidámat, :(( két szomorút jelent.

Tervezd meg az állapotgépet állapot- és tevékenységtáblával, utána írd meg a programot! A programra csak akkor jár pont, ha állapotgépes és a leírt állapottáblát valósítja meg.

Megoldás

: ( ) többi
alap →kp - - -
kp - szom++ vid++ →alap
#include <stdio.h>

int main() {
  enum Allapot { alap, kp } all;
  int szom, vid, c;

  all=alap;
  szom=vid=0;

  while ((c=getchar())!=EOF) {
    switch (all) {
      case alap:
        if (c==':') all=kp;
        break;
      case kp:
        if (c==')')   vid++;
        else if (c=='(') szom++;
        else if (c!=':') all=alap;
        break;
    }
  }

  if (vid>szom) printf("vidam");
  else if (szom<vid) printf("szomoru");
  else printf("kozombos");

  return 0;
}

Dzs számláló

Írj állapotgépes programot, amely a szabványos bemenetről olvasott szövegben megszámolja a „dzs” betűket! (Hosszú ddzs egynek számít, nem kell külön foglalkozni vele.) A számlálás után írd ki a szabványos kimenetre a darabszámot!

Tervezd meg az állapotgépet állapot- és tevékenységtáblával, utána írd meg a programot! A programra csak akkor jár pont, ha állapotgépes és a leírt állapottáblát valósítja meg.

Megoldás

d z s többi
alap →dvolt - - -
dvolt - →dzvolt →alap →alap
dzvolt →dvolt →alap dzs++, →alap →alap
#include <stdio.h>

int main() {
  enum Allapot { alap, dvolt, dzvolt } all;
  int c, dzs;

  all=alap;
  dzs=0;

  while ((c=getchar())!=EOF) {
    switch (all) {
      case alap:
        if (c=='d') all=dvolt;
        break;
      case dvolt:
        if (c=='d') ;
        else if (c=='z') all=dzvolt;
        else all=alap;
        break;
      case dzvolt:
        if (c=='s') dzs++;
        if (c=='d') all=dvolt;
        else all=alap;
        break;
    }
  }

  printf("dzs: %d\n", dzs);

  return 0;
}

8 Tömbök, pointerek

1.

Írj függvényt, amely paraméterként vesz át egy egészekből álló tömböt, és visszaadja az első olyan tömbelem címét, amelyből legalább kettő található a tömbben! Ha nincs ilyen tömbelem, adjon vissza NULL pointert!

Megoldás

int *dupla(int *tomb, int n) {
    int i, j;
    for(i=0; i<n-1; i++)
        for(j=i+1; j<n; j++)
            if (tomb[i] == tomb[j] )
                return tomb+i;
    return NULL;
}

2.

Írj függvényt, amely paraméterként vesz át egy valós értékekből álló tömböt, melyről biztosan tudjuk, hogy elemei különbözőek! A függvény ellenőrizze, hogy a tömb rendezett-e (akár növekvő, akár csökkenő sorrendben; a feltételezett rendezettség iránya az első két tömbelem vizsgálatával eldönthető). Ha a tömb nem rendezett, a függvény adja vissza az első olyan tömbelem címét, amelyik elrontja a rendezettséget! Ha a tömb rendezett, adjon vissza NULL pointert! Pl. be: {-8.11, -5.3, 0.1, 2.5, 1.4, 6.9, 12.0, 5.7} , a visszaadott érték az 1.4-et tartalmazó tömbelem címe. Pl. be: {7, 1, 2, 3, 4, 5} , a visszaadott érték a 2-t tartalmazó tömbelem címe.

Megoldás

double *rendezette(double *tomb, int n) {
    int i, no;
    if (n<3)return NULL;
    no = tomb[0] < tomb[1];
    for(i=3; i<n; i++) {
        if (no && tomb[i-1] > tomb[i])return tomb+i;
        else if (!no && tomb[i-1] < tomb[i])return tomb+i;
    }
    return NULL;
}

3.

Írj függvényt, amely paraméterként vesz át egy sztringet, és visszaadja az első olyan karakter címét, amelyből legalább kettő található a sztringben! Ha nincs ilyen karakter, adjon vissza NULL pointert!

Megoldás

char *duplas(char *string) {
    int i, j;
    for(i=0; string[i]!='\0'; i++)
        for(j=i+1; string[j]!='\0'; j++)
            if (string[i] == string[j] )
                return string+i;
    return NULL;
}

4.

Írj függvényt, amely paraméterként vesz át egy egészekből álló tömböt! A függvény adja vissza paramétersoron (címével átvett változókban) a tömb legkisebb és legnagyobb elemének indexét! Ha több egyforma érték a legkisebb/legnagyobb, akkor ezek közül bármelyik indexét visszaadhatja.

Megoldás

void minmax(int *tomb, int n, int *min, int *max) {
    int i;
    *min = *max = 0;
    for(i = 1; i<n; i++) {
        if (tomb[i] < tomb[*min] ) *min = i;
        if (tomb[i] > tomb[*max] ) *max = i;
    }
}

5.

Írj függvényt, amely paraméterként kap egy sztringet! A sztring szöveget tartalmaz, melynek szavait szóközök választják el egymástól (minden szó, ami nem szóköz). A függvény adja vissza paramétersoron (címével átvett változókban) a sztring második szavának indexét, visszatérési értékként (return-nel) pedig a sztring utolsó szavának címét! A paraméterként kapott sztringről biztosan tudjuk, hogy legalább két szóból áll, a szavakat pontosan egy szóköz választja el egymástól, és a sztring első és utolsó karaktere nem szóköz.

Megoldás

char *szavak(char *sztring, int *masodik) {
    int i, utolso=0;
    *masodik=0;
    for (i=0; sztring[i]!='\0'; i++) {
        if (sztring[i]==' ') {
            utolso=i;
            if (*masodik==0)
                *masodik = i+1;
        }
    }
    return sztring + utolso;
}

9 Listák I.

Elejéről a végére

Írj függvényt, amely egy lista legelső elemét a lista végére helyezi át! (Például az 1,2,3,4,5 listából így 2,3,4,5,1 lesz.) A függvény a lista elejére mutató pointert cím szerint kapja. Ha kettőnél kevesebb elem van, akkor ne csináljon semmit.

Definiáld az egyszeresen láncolt lista adatszerkezetét úgy, hogy egész számokat tartalmazzon! Készíts rajzot, amely a listakezelést mutatja számozott lépésekkel! Írj programrészt, amely létrehoz két listaelemet, és meghívja a keletkező listára a függvényt.

Megoldás

typedef struct Lista {
   int szam;
   struct Lista *kov;
} Lista;

void elso_vegere(Lista **peleje) {
   Lista *iter, *elso;

   if (*peleje==NULL) return;
   if ((*peleje)->kov==NULL) return;

   for (iter=*peleje; iter->kov!=NULL; iter=iter->kov)
      ;

   elso=*peleje;

   iter->kov=elso;
   *peleje=elso->kov;
   elso->kov=NULL;
}

Lista *eleje;
eleje=(Lista*) malloc(sizeof(Lista));
eleje->szam=3;
eleje->kov=(Lista*) malloc(sizeof(Lista));
eleje->kov->szam=4;
eleje->kov->kov=NULL;

elso_vegere(&eleje);

Ötödik elem törlése

Írj függvényt, amely egy lista ötödik elemét törli! (A számozás 1-től indul.) Ha nincs ötödik elem, akkor ne történjen semmi. A függvénynek egy paramétere legyen csak, az a lista elejére mutató pointer.

Definiáld az egyszeresen láncolt lista adatszerkezetét úgy, hogy max. 30 karakter hosszúságú szavakat tároljon! Készíts rajzot, amely a listakezelést mutatja számozott lépésekkel! Írj rövid főprogramot, amelyben definiálsz egy listát. Feltételezve, hogy a lista fel van töltve, töröld ki a függvénnyel az 5. elemet!

Megoldás

typedef struct Lista {
   char szo[30+1];
   struct Lista *kov;
} Lista;

void lista_torol_5(Lista *lista) {
   Lista *iter, *negyedik, *otodik;
   int i;

   for (iter=lista, i=1; iter!=NULL && i<4; iter=iter->kov, ++i)
      ;

   negyedik=iter;
   if (negyedik==NULL) return;
   otodik=negyedik->kov;
   if (otodik==NULL) return;

   negyedik->kov=otodik->kov;

   free(otodik);
}

Lista *l=.....;

lista_torol_5(l);

Ötödik beszúrása

Írj függvényt, amely egy listába beszúr egy elemet úgy, hogy az az ötödik legyen! (A számozás 1-től indul.) Ha a lista rövidebb, akkor kerüljön a végére az új elem. A függvénynek paraméterei legyenek a lista elejére mutató pointer és a beszúrandó adat. Visszatérési értéke legyen a lista elejét mutató pointer.

Definiáld az egyszeresen láncolt lista adatszerkezetét úgy, hogy az max. 50 karakter hosszúságú neveket tároljon! Készíts rajzot, amely a listakezelést mutatja számozott lépésekkel! Írj rövid főprogramot, amelyben definiálsz egy listát. Feltételezve, hogy a lista fel van töltve, szúrd be az 5. helyre a Mézga Géza nevet!

Megoldás

typedef struct Lista {
   char nev[50+1];
   struct Lista *kov;
} Lista;

Lista* beszur_5(Lista *eleje, char *nev) {
   Lista *iter, *uj;
   int i;

   uj=(Lista*) malloc(sizeof(Lista));
   strcpy(uj->nev, nev);

   if (eleje==NULL) {
      uj->kov=NULL;
      return uj;
   }

   for (iter=eleje, i=1; iter->kov!=NULL && i<4; iter=iter->kov, i++)
      ;

   uj->kov=iter->kov;
   iter->kov=uj;
   return eleje;
}

Lista *l=.....;
l=beszur_5(l, "MezgaGeza");

Utolsó elem az elejére

Írj függvényt, amely egy lista utosó elemét a lista elejére helyezi át! (Például az 1,2,3,4,5 listából így 5,1,2,3,4 lesz.) A függvény a lista elejére mutató pointert cím szerint kapja. Ha kettőnél kevesebb elem van, akkor ne csináljon semmit.

Definiáld az egyszeresen láncolt lista adatszerkezetét úgy, hogy az valós számokat tartalmazzon! Készíts rajzot, amely a listakezelést mutatja számozott lépésekkel! Írj programrészt, amely létrehoz két listaelemet, és meghívja a keletkező listára a függvényt.

Megoldás

typedef struct Lista {
   double szam;
   struct Lista *kov;
} Lista;

void utolso_elore(Lista **peleje) {
   Lista *iter, *utolso;

   if (*peleje==NULL) return;
   if ((*peleje)->kov==NULL) return;

   for (iter=*peleje; iter->kov->kov!=NULL; iter=iter->kov)
      ;

   utolso=iter->kov;

   utolso->kov=*peleje;
   *peleje=utolso;
   iter->kov=NULL;
}

eleje=(Lista*) malloc(sizeof(Lista));
eleje->szam=3;
eleje->kov=(Lista*) malloc(sizeof(Lista));
eleje->kov->szam=4;
eleje->kov->kov=NULL;

utolso_elore(&eleje);

10 Listák II.

1.

Definiálj egy két irányban láncolt lista elemeinek tárolására alkalmas adatstruktúrát, a lista valós értékű adatokat tárol! Írj függvényt, amely paraméterként kapja egy ilyen elemekből felépülő, mindkét végén strázsával lezárt lista kezdőstrázsájának címét! A függvény töröljön a listából minden olyan elemet, amelynek adata negatív értékű!

Megoldás

typedef struct elem {
    double ertek;
    struct elem *prev, *next;
} elem;

void torol(elem *start) {
    for (start = start->next; start->next != NULL; start = start->next )
        if (start->ertek < 0.0) {
            elem *torlendo = start;
            start = start->prev;
            torlendo->prev->next = torlendo->next;
            torlendo->next->prev = torlendo->prev;
            free(torlendo);
        }
}

2.

Definiálj egy irányban láncolt lista elemeinek tárolására alkalmas adatstruktúrát, a lista 20 elemű int tömb adattaggal rendelkezik! Írj függvényt, amely paraméterként kapja egy ilyen elemekből felépülő lista címét! A függvény adja vissza a lista másolatát (a másolt lista kezdőelemének címét)! (Vagyis hozzon létre egy másik listát, amely ugyanazokat az adatokat tartalmazza ugyanolyan sorrendben, mint a paraméterként átvett!)

Megoldás

typedef struct elem {
    int adat[20];
    struct elem *next;
} elem;

elem *masol(elem *start) {
    elem *ujstart, *ujfuto;
    for (ujstart = ujfuto = NULL; start != NULL; start = start->next) {
        elem *p = (elem*)malloc(sizeof(elem));
        *p = *start;
        p->next = NULL;
        if (ujstart==NULL)
            ujstart = ujfuto = p;
        else {
            ujfuto->next = p;
            ujfuto = ujfuto->next;
        }
    }
    return ujstart;
}

3.

Definiálj két irányban láncolt lista elemeinek tárolására alkalmas adatstruktúrát, a lista pozitív egész számokat tárol! Írj függvényt, amely paraméterként kapja egy ilyen elemekből felépülő, mindkét végén strázsával lezárt lista címét! A függvény duplázzon meg minden olyan listaelemet, amely páratlan számot tartalmaz, vagyis hozzon létre és fűzzön be minden ilyen listaelem elé vagy mögé egy új listaelemet, melybe a páratlan értéket átmásolja!

Megoldás

typedef struct elem {
    int adat;
    struct elem *prev,*next;
} elem;

void duplaz(elem *start) {
    for (start = start->next; start->next != NULL; start = start->next) {
        if (start->adat % 2 == 1) {
            elem *p = (elem*)malloc(sizeof(elem));
            *p = *start;
            p->next = start;
            p->next->prev = p;
            p->prev->next = p;
        }
    }
}

4.

Definiálj két irányban láncolt lista elemeinek tárolására alkalmas adatstruktúrát, a lista 20 elemű int tömb adattaggal rendelkezik! Írj függvényt, amely paraméterként kapja egy ilyen elemekből felépülő lista címét! A függvény adja vissza a lista másolatát (a másolt lista kezdőelemének címét)! (Vagyis hozzon létre egy másik listát, amely ugyanazokat az adatokat tartalmazza ugyanolyan sorrendben, mint a paraméterként átvett!)

Megoldás

typedef struct elem {
    int adat[20];
    struct elem *prev,*next;
} elem;

elem *masol(elem *start) {
    elem *ujstart, *ujfuto;
    for (ujstart = ujfuto = NULL; start != NULL; start = start->next) {
        elem *p = (elem*)malloc(sizeof(elem));
        *p = *start;
        p->next = NULL;
        if (ujstart==NULL) {
            ujstart = ujfuto = p;
            p->prev = NULL;
        }
        else {
            ujfuto->next = p;
            p->prev = ujfuto;
            ujfuto = ujfuto->next;
        }
    }
    return ujstart;
}

5.

Definiálj egy irányban láncolt lista elemeinek tárolására alkalmas adatstruktúrát, a lista valós típusú adattaggal rendelkezik! Írj függvényt, amely paraméterként kapja két, ilyen elemekből felépülő lista címét! A függvény tegye át a két lista elemeit fordított sorrendben egy harmadik listába, és ennek a listának a kezdőcímét adja vissza! (Ne foglalj memóriát, hanem az eredeti listaelemek pointereinek átállításával oldd meg a feladatot!) Például ha a két bemenő lista elemei: {1.0, 3.0, 5.0} és {2.0, 4.0, 6.0}, akkor a kimenő lista {6.0, 4.0, 2.0, 5.0, 3.0, 1.0} legyen!

Megoldás

typedef struct elem {
    double adat;
    struct elem *next;
} elem;

elem *forditvafuz(elem *lista1, elem *lista2) {
    elem *cel = NULL;
    while (lista1 != NULL) {
        elem *temp = lista1->next;
        lista1->next = cel;
        cel = lista1;
        lista1 = temp;
    }
    while (lista2 != NULL) {
        elem *temp = lista2->next;
        lista2->next = cel;
        cel = lista2;
        lista2 = temp;
    }
    return cel;
}