5. labor: Tömbök

1 Legkisebb

Írj programot, amely tartalmaz egy tíz elemű tömböt, az általad megadott kezdeti értékekkel! Írd ki ezt a tömböt!

Írj programrészt, amely megmondja, melyik a legkisebb szám a tömbből! Írd ki ezt a számot! (Próbáld ki a programod úgy is, hogy a legkisebb szám a tömb legelején és legvégén van!) Írj programrészt, amely megkeresi a legkisebb elemet – és utána úgy írja ki a tömböt, hogy a legkisebb elem mellé tesz egy jelzést!

A tömb: 25 69 54 8 77 6 29 10 3 98

A legkisebb: 3
Jelölve: 25 69 54 8 77 6 29 10 3[MIN] 98

Megoldás

#include <stdio.h>

int main()
{
    int tomb[10] = { 25, 69, 54, 8, 77, 6, 29, 10, 3, 98 };
    int i, min;

    /* Kiírás */
    printf("A tömb:");
    for (i=0; i<10; ++i)
        printf(" %d", tomb[i]);
    printf("\n\n");

    /* Keresés */
    min = 0;
    for (i=1; i<10; ++i)
        if (tomb[i] < tomb[min])
            min = i;

    /* Kiírás */
    printf("A legkisebb: %d\n", tomb[min]);
    printf("Jelölve:");
    for (i=0; i<10; ++i) {
        printf(" %d", tomb[i]);
        if (i==min)
            printf("[MIN]");
    }
    printf("\n");

    return 0;
}

2 A folyó

Egy folyó sodrásirányára merőlegesen 2 m-enként megmértük a meder mélységét, és egy valós tömbben sorfolytonosan eltároltuk. Így az alábbi 18 számot kaptuk:

0.1, 1, 1.5, 1.7, 2, 2.3, 2.8, 4.5, 9.8, 12, 14.1, 13, 11.9, 8.7, 6.1, 3.5, 1, 0.5

Készíts programot, mely meghatározza, hogy hol a legmeredekebb a mederfal, és hány a százalékos meredeksége! (A százalékos lejtés azt mutatja, hogy egységnyi táv alatt mennyit változott a magasság: 10 m távon 5 m különbség 50%-os lejtőt jelent.)

Tipp: melyik programozási tétel kell itt? A meredekségnek mijét kell meghatározni? Vigyázz, a lejtő és az emelkedő ugyanaz, ha másik irányból nézzük, és vigyázz, ne indexeld túl a tömböt!

Megoldás

#include <stdio.h>
#include <math.h>

int main()
{
    double folyo[18] = { 0.1, 1, 1.5, 1.7, 2, 2.3, 2.8, 4.5, 9.8,
                         12, 14.1, 13, 11.9, 8.7, 6.1, 3.5, 1, 0.5 };
    int i, max;

    /* Keresés */
    max = 0;
    for (i=1; i<18-1; ++i)  /* i+1 indexelés miatt! */
        if (fabs(folyo[i+1]-folyo[i]) > fabs(folyo[max+1]-folyo[max]))
            max = i;

    /* Kiírás */
    printf("A legmeredekebb: max=%d-%d méter között\n", max*2, (max+1)*2);
    printf("A meredekség: %f %%-os\n", fabs(folyo[max+1]-folyo[max])/2*100);

    return 0;
}

3 Túlindexelés

Mi történik a következő program futtatásakor?

#include <stdio.h>

int main()
{
   int tomb[10], i;

   for (i=0; i<10; i+=1)
      tomb[i]=i;
   i=0;
   while (1) {
      printf("%d. elem: %d\n", i, tomb[i]);
      i+=1;
   }

   return 0;
}

4 Tömb léptetése

25 69 54  8 77  6 29 10  3 98
69 54  8 77  6 29 10  3 98 25
54  8 77  6 29 10  3 98 25 69
 8 77  6 29 10  3 98 25 69 54
77  6 29 10  3 98 25 69 54  8
 6 29 10  3 98 25 69 54  8 77
29 10  3 98 25 69 54  8 77  6

Írj egy programot, amely tartalmaz egy általad megadott értékekkel feltöltött, tíz elemű tömböt! Írja ki a program ezt a tömböt a képernyőre!

Léptesd egy tömb összes elemét eggyel az eleje felé. A tömb egyik végén kilépő elem jöjjön be a túlsó végén. Ismételd meg ezt a műveletet tízszer, közben mindig írd ki a tömböt! Az eredmény a jobb oldalon láthatóhoz hasonló kell legyen.

Tipp: segédtömbre ehhez nincs szükség! Az első felülírható a másodikkal, a második a harmadikkal… Kérdés, az utolsó helyre ilyenkor mi kerül. Rajzold le, és gondold végig úgy, minek kell történnie!

Megoldás

#include <stdio.h>

int main()
{
    int tomb[10] = { 25, 69, 54, 8, 77, 6, 29, 10, 3, 98 };
    int i, j, tmp; /* Ideiglenes változó */

    /* Kiírás és elemek léptetése 10szer */
    for(j=0; j<10; j++) {
        /* Kiírás */
        for(i=0;i<10;i++)
            printf("%2d ",tomb[i]);
        printf("\n");

        /* Léptetés */
        tmp=tomb[0]; /* Az első elemet kell félretenni */
        for(i=0;i<9;i++)
            tomb[i]=tomb[i+1]; /* Léptetés */
        tomb[9] = tmp; /* Az utolsó elem a régi első lesz */
    }

    return 0;
}

5 Az utolsó öt szám… átlaga

Írj C programot, amely a felhasználótól számokat kér be. A bevitel addig tartson, amíg a felhasználó 0-t nem ad meg. Amikor ez megtörtént, a program írja ki az utoljára bevitt öt szám átlagát! (Tegyük fel, hogy volt legalább ennyi.)

Tipp: a gondolat, hogy „csinálok egy egymillió elemű tömböt, abba biztos belefér majd az összes szám”, elvi hibás. Gondold végig, hogy a feladat megoldásához hány számot kell mindenképpen eltárolni! Szükség van-e ehhez egyáltalán tömbre? Ha igen, akkor mekkorára? Kell-e úgy tologatni az elemeket a tömbön belül, mint az előző feladatban?

Megoldás

#include <stdio.h>

int main()
{
   double szamok[5], beolv, szum;
   int i;

   printf("Szám vagy 0? ");      /* első */
   scanf("%lf", &beolv);
   i=0;
   while (beolv!=0) {
      szamok[i]=beolv;
      i=(i+1) % 5;               /* 4 után megint 0 */

      printf("Szám vagy 0? ");   /* következő */
      scanf("%lf", &beolv);
   }

   szum=0;
   for (i=0; i<5; i+=1)
      szum+=szamok[i];

   printf("Utolsó 5 átlaga: %f\n", szum/5);

   return 0;
}

6 További feladatok

Tömb kiírása – szépen

Írj programrészt, amely kiírja egy tömb elemeit a képernyőre, vesszővel elválasztva. A kiírás legyen szép: ne legyen se az elején, se a végén felesleges vessző. A kód is legyen szép: mindez megoldható egyetlen ciklussal, nem kell hozzá if() feltétel!

A tömb: 25, 69, 54, 8, 77, 6, 29, 10, 3, 98.

Megoldás

#include <stdio.h>

int main()
{
    int tomb[10] = { 25, 69, 54, 8, 77, 6, 29, 10, 3, 98 };
    int i;

    /* Kiírás */
    printf("A tömb:");
    /* első elem */
    printf(" %d", tomb[0]);
    /* többi elem */
    for (i=1; i<10; ++i)
        printf(", %d", tomb[i]);
    printf(".\n");

    return 0;
}

Szigmon

Készíts egy olyan C programot, amely létrehoz és a programba beépített kezdeti értékekkel feltölt egy int típusú elemeket tartalmazó tömböt! Írja ki, hogy a tömb elemei szigorúan monoton növekvőek, csökkenőek, vagy egyik sem!

Tipp: melyik programozási tételt kell alkalmazni ennek megoldásához? Másképp feltéve a kérdést, mit kell találni a tömbben ahhoz, hogy tudjuk, nem szigmon növekvő?

Teszteld a programot, hogy mind a három eredményt előállítsd vele! Próbáld ki úgy is, hogy a csökkenő vagy növekvő monotonitást a tömb első kettő vagy utolsó kettő elemével rontod el, hogy lásd, a számsor széleit is helyesen kezeled-e!

Megoldás

#include <stdio.h>

int main()
{
    /* Változók */
    int tomb[10] = {1,3,6,9,13,16,19,21,45,56};
    int nov, csokk, i;

    /* Tegyük fel hogy szig.mon.növ. és csökk. */
    nov=csokk=1;
    /* Ellenőrzés */
    for (i=0; i<10-1; i++){
        if (!(tomb[i]<tomb[i+1]))
            nov=0; /* Nem teljesül a szig.mon.csökk. */
        if (!(tomb[i]>tomb[i+1]))
            csokk=0; /* Nem teljesül a szig.mon.növ. */
    }

    /* Eredmény */
    if (nov==1)
        printf("szigmon novekvo");
    else
        if (csokk==1)
            printf("szigmon csokkeno");
        else
            printf("nem szigmon");

    return 0;
}

Master Mind

A Master Mind játékban egyik játékos kitalál egy feladványt, amely 4 tüskéből áll. A tüskék 6-féle színűek lehetnek. Lehetséges az is, hogy két vagy több tüske ugyanolyan színű, pl. piros, piros, zöld, kék. A másik játékos ezután megtippeli, mire gondolhatott az első. Az előbbi minden körben aképpen segít kitalálni a feladványt, hogy elárulja, a tippben hány olyan tüske van, amely a megfelelő színű és a megfelelő helyen is van (ezt feketékkel jelöli); és hány olyan, amely az előbbieken kívül még jó színű, de rossz helyen van (ezt pedig fehérekkel).

Pl. feladvány: oooo, tipp: oooo, segítség: ooo (a második piros, illetve a zöld és a sárga miatt).

Írj programot, amely feladványt ad a felhasználónak, és a leírt szabályok alapján segít neki kitalálni azt! A hat színt jelöld a programban az a…f betűkkel.

Sorbarakó játék

    1    2    3    4    5    6
  145   12    5   77  100   44

1. felcserelendo = 3
2. felcserelendo = 1
    1    2    3    4    5    6
    5   12  145   77  100   44

Írj C programot, amely a felhasználótól bekért egész számokkal feltölt egy hatelemű tömböt! A program ezután keverje össze véletlenszerűen a számokat, majd írja ki ezeket az oldalt látható módon.

    1    2    3    4    5    6
    5   12   44   77  100  145

Gratulalok, nyertel!

A program ezután kérjen a felhasználótól két 1 és 6 közötti sorszámot, majd a program cserélje fel az ezekhez a sorszámokhoz tartozó értékeket, és írja ki ismét a számokat.

A program mindaddig ismételje a sorszámok bekérését és a cserét, míg a felhasználó nem rakta növekvő sorrendbe a számokat. Ha a felhasználó nem 1 és 6 közötti értékeket ad meg, adjon hibaüzenetet!

Tipp: a tömb megkeveréséhez minden elemet cserélj meg egy véletlenedikkel! for(…tömbelemek…) – valahogy így. Vajon hogyan lehet két változó értékét megcserélni? A véletlenszámok generálásáról lentebb találsz egy útmutatót.

Megoldás

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
    /* Változók */
    int tomb[6],i,csere,rnd;
    int sorban,cs1,cs2;

    srand(time(0));  /* Véletlengenerátor inicializálása */

    /* 6 szám bekérése a tömbbe */
    for (i=0; i<6; i++){
        printf("%d. szam: ",i+1);
        scanf("%d",&tomb[i]);
    }

    /* Elemek véletlen rendezése */
    for (i=0; i<6; i++){
        rnd=rand()%6;  /* Generálunk egy véletlenszámot */
        /* Csere 3 lépésben */
        csere=tomb[i];  /* i. elem elmentése */
        tomb[i]=tomb[rnd];  /* i. elem felülírása */
        tomb[rnd]=csere;  /* rnd. elem helyére az elmentett elem */
    }

    /* Tömb kiírása */
    for (i=0; i<6; i++) printf("%4d ",i+1);
    printf("\n");
    for (i=0; i<6; i++) printf("%4d ",tomb[i]);
    printf("\n");

    /* Rendezetség ellenőrzése */
    sorban=1;  /* Tegyük fel hogy sorba van rendezve */
    /* Ha van két elem ami rossz sorrendben van akkor már nincs rendezve */
    for (i=0; i<5; i++)
        if (tomb[i]>tomb[i+1])
            sorban=0;

    /* Ciklus amíg rossz a sorrend */
    while (sorban==0) {
        /* Bekérünk két indexet */
        printf("1. cserelendo: "); scanf("%d",&cs1);
        printf("2. cserelendo: "); scanf("%d",&cs2);
        /* Ellenőrizzük a határokat */
        if (cs1!=cs2 && cs1>=1 && cs2>=1 && cs1<=6 && cs2<=6){
            /* 3 lépéses csere */
            /* Az indexekből 1-et ki kell vonni: 1..6 -> 0..5 */
            csere=tomb[cs1-1];
            tomb[cs1-1]=tomb[cs2-1];
            tomb[cs2-1]=csere;
        }
        else
            printf("Hibas indexek!\n");

        /* Tömb kiírása */
        for (i=0; i<6; i++)
            printf("%4d ",i+1);
        printf("\n");
        for (i=0; i<6; i++)
            printf("%4d ",tomb[i]);
        printf("\n");

        /* Rendezettség ellenőrzése */
        sorban=1;
        for (i=0; i<5; i++)
            if (tomb[i]>tomb[i+1])
                sorban=0;
    }

    /* Ha vége a ciklusnak akkor győzelem */
    printf("Gratulalok, nyertel!");

    return 0;
}

7 Segédlet - véletlenszámok generálása

A C nyelv rand() függvénye lehetővé teszi véletlenszámok előállítását. A függvény használatához az stdlib.h fejlécfájl beépítése szükséges. A rand() egy 0 és RAND_MAX közötti egész számot ad vissza. A RAND_MAX az stdlib.h-ban definiált konstans.

Adott tartományban lévő számot legegyszerűbben egy osztás maradékával állíthatunk elő. Például kockadobást így lehet csinálni:

int kockaval_dob()
{
   return rand()%6 + 1;
}

A lenti program pedig 10 db 0–99 közötti véletlen értéket ír ki. A rand() függvény egy ún. pszeudovéletlenszám-generátor. Ez azt jelenti, hogy egy bonyolult matematikai műveletsorozat eredményét adja, amely véletlenszámnak tűnik. Valójában azonban nem az. Ha kihagyjuk az srand() sort, akkor mindig ugyanazokat a számokat kapjuk. A generátort ezért inicializálni kell, vagyis kezdeti értékként kell adni neki egy számot, amelyből kiindulhat. A számítógép óráját a time() függvénnyel lekérdezve biztosíthatjuk azt, hogy mindig különféle számokkal inicializálunk. Ezt a program futásának elején egyszer kell csak megtenni. A time() működéséről és az ott lévő 0 szerepéről később lesz szó.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
   int i;

   /* inicializalas, csak a program elejen egyszer */
   srand(time(0));

   for (i=0; i<10; i+=1)
       printf("%d\n", rand() % 100);

   return 0;
}