Fizikus C labor

1. óra: ismerkedés a fejlesztőkörnyezettel2. óra: ciklusok3. óra: számelméleti feladatok
4. óra: számítás valós számokkal5. óra: sok adat beolvasása, tömbök6. óra: iteráció, könyvtári sztringkezelő függvények
7. óra: függvények és sztringek8. óra: cím szerinti és tömb paraméterek, struktúrák, dinamikus tömbök9. óra: rendezés, fájlkezelés, parancssori paraméterek
10. óra: állapotgép, szabványos I/O átirányítása11. óra: rekurzió, gyakorlás12. óra: láncolt listák, fák
13. óra: NHF beadás

Rajzoljunk a konzol ablakba Windowson

8. alkalom: függvények és sztringek

Az alábbi feladatokban mindig készíts main függvényt, amelyből meghívod, kipróbálod a feladatban szereplő függvényt!

0.

A scanf függvénnyel a következő szóközig a %s formátumjelzővel olvashatunk be: char st[100]; scanf("%s", st);. Ha a felhasználó 99 karakternél hosszabb szöveget ír be, akkor a scanf függvény az st tömb utáni memóriaterületre is megpróbál szöveget beírni, amit nem volna szabad. A scanf_s függvény célja, hogy ez elkerülhető legyen. A scanf_s-nél a %s, %[ és %c esetén meg kell adni a tároló méretét is (%c-nél ez 1 lesz). Pl. char st[100]; scanf_s("%s", st, 100);.Ha nem csak a következő szóközig szeretnénk olvasni, hanem a tejes sort, akkor használhatjuk a scanf(" %[^\n]", st); ill. scanf_s(" %[^\n]", st, 100); utasítást. A % előtti szóköz arra jó, hogy átugorja az előző beolvasás után esetleg megmaradt újsor karaktert, valamint a sor elején lévő whitespace karaktereket (szóköz, tabulátor). Utóbbi persze ritkán fordul elő, de az viszont nem, hogy ott marad az előző sor végén az enter, azt ugyanis a scanf nem olvassa be (kivéve, ha %c-t használunk), Az fgets(st, 100, stdin); ugyancsak teljes sor beolvasására jó, de ez a sorvégi entert is beteszi a sztringbe.

1. feladat

Írj függvényt, amely egy nevet kap sztringként, és eldönti, hogy az illető keresztneve Apor-e! A megoldáshoz használj könyvtári függvényeket! Az egyszerűség érdekében feltételezheted, hogy ha "Apor" szerepel a névben és nem az a vezetéknév, akkor az a keresztnév.

Tippek:

- Ha egy függvény eldönt valamit, az azt jelenti, hogy megvizsgálja, igez-e az állítás, és ennek megfelelően true vagy false visszatérési értéket ad.

- Ha a feladat nem írja, akkor tilos a függvényben a felhasználótól bekérni a bemenő adatot, hanem azt függvényparaméterként kell átadni. Ha a feladat nem írja, akkor tilos az eredményt kiírni, hanem azt vissza kell adni vagy returnnel, vagy cím szerinti paraméter segítségével.

- Az strstr könyvtári függvény két szting paramétert vár, és az első sztringben megkeresi a másodikat. Ha benne van, akkor a megtalált szövegrész első karakterének címét adja vissza, ha nincs benne, akkor pedig NULL pointert. Pl. char *nev="Gipsz Jakab", *hol=strstr(nev, "Jakab"); esetén a hol pointer a "Gipsz Jakab" szövegben lévő J betűre mutat.

- if(hol!=NULL)printf("Van a nevben Jakab"); Azonban elképzeljető, hogy a név pl.Jakab Anna, és ebben az esetben nem a keresztneve a Jakab, pedig a feladat az volt, hogy a keresztnevet vizsgáljuk. Ha if(hol!=NULL && hol!=nev)printf("Az illető keresztneve Jakab"); az utasításunk, akkor az már valóban jó kiírást ad. Ha a hol nem NULL, akkor benne van a névben, hogy Jakab. Mit jelent a hol!=Nev? Mindkettő egy pointer, tehát azt vizsgáljuk, hogy a két cím megegyezik-e. Ha az illető vezetékneve Jakab, akkor a hol ugyanúgy a név első betűjére mutat, mint ahogy a nev is, vagyis a hol!=Nev vizsgálat azt jelenti, hogy a név Jakabbal kezdődik-e.

- Az eddig bemutatott lépések nem megfelelőek, ha az illetőt Jakab Jakabnak hívják, mert az illető vezetékneve is Jakab. A feladatot megoldhatjuk a következőképpen: az strchr függvény egy karaktert keres egy sztringben. char *szokoz=strchr(nev,' '); módon szóközt keresünk. A szokoz tehát a vezetéknév és a keresztnév közötti szóköz címe lesz. Mivel egy sztring a C nyelvben azt a karaktersorozatot jelenti, ami a sztring első karakterére mutató pointer által mutatott karaktertől az első 0 értékű bájtig (vagy más néven a '\0' lezáró nulláig) tart a memóriában, ha a pointer a szóközre mutat, akkor az a szóköztől a lezáró nulláig tartó sztringet jelenti. vagyis egy char *hol=strstr(szokoz,"Jakab"); már csak a keresztnévben fog keresni.

2. feladat

Készítsd el az 1. feladat olyan változatát, ahol a függvény a keresett keresztnevet is paraméterként kapja!

3. feladat

Készíts programot, amely beolvassa egy ember nevét, és kiírja, hogy a keresztneve Apor-e! Használd a 2. feladatban készített függvényt!

Tipp:

- Mivel nem tudjuk előre, hogy az illetőnek hány keresztneve van, nem célszerű scanf-et használni %s-sel, ami csak szóközig olvas. A char nev[100]; fgets(nev, 100, stdin); utasítás egy teljes sornyi szöveget olvas be. Az fgets függvénynek megadjuk a tömb méretét is, így nem fordulhat elő, hogy ha a felhasználó túl hosszú nevet ad meg, akkor a program a tömb utáni memóriaterületre is beírjon. (Ebben az esetben 99 karaktert olvas be a program, plusz a lezáró nulla kerül a tömb végére, a szöveg többi része pedig a következő beolvasó utasításra vár, tehát pl. egy következő fgets olvassa majd be.)

4. feladat.

Készítsd el az strlen, strcpy, strcat, strchr, strstr függvényeket magad! A függvények pont úgy működjenek, mint a könyvtári függvények! Könyvtári függvényt természetesen nem használhatsz a megvalósításhoz.

5. feladat.

Készítsd el a 6. heti 2-3 feladatokat könyvtári sztringkezelő függvények használata nélkül! A 4. feladatban megírt függvényeket se használd, hanem mindegyiket egy darab függvénnyel valósítsd meg!

Az órai feladatok mintamegoldása

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

bool Apor_e_a_keresztneve(char nev[]) {
    char *szokoz = strchr(nev, ' ');
    if (szokoz == NULL)
        return false;
    return strstr(szokoz + 1, "Apor") != NULL;
}

bool ez_e_a_keresztneve(char nev[], char keresztnev[]) {
    char *szokoz = strchr(nev, ' ');
    if (szokoz == NULL)
        return false;
    return strstr(szokoz + 1, keresztnev) != NULL;
}

void my_strcpy(char cel[], char forras[]) {
    int i;
    for (i = 0; forras[i] != '\0'; i++)
        cel[i] = forras[i];
    cel[i] = '\0';
}

char * my_strstr(char hol[], char mit[]) {
    int i;
    for (i = 0; hol[i] != '\0'; i++) {
        if (hol[i] == mit[0]) {
            int j;
            for (j = 0; hol[i + j] == mit[j] && mit[j] != '\0'; j++)
                ; // szándékosan üres
            if (mit[j]=='\0')
                return hol + i;
        }
    }
    return NULL;
}

bool Apor_e_a_keresztneve_4(char nev[]) {
    char *szokoz = strchr(nev, ' ');
    if (szokoz == NULL)
        return false;
    return strstr(szokoz + 1, "Apor") != NULL;
}

void vez_ker_szetvalaszt_5(char nev[], char vez[], char ker[]) {
    int i, j = 0;
    for (i = 0; nev[i] != ' ' && nev[i] != '\0'; i++)
        vez[i] = nev[i];
    if (nev[i] == ' ')
        for (j = 0; nev[i + j + 1] != '\0'; j++)
            ker[j] = nev[i + j + 1]; // +1: átugorjuk a szóközt
    vez[i] = ker[j] = '\0';
}

int main() {

    if (Apor_e_a_keresztneve("Apor Vilmos"))
        printf("Apor Vilmos keresztneve Apor\n");
    else
        printf("Apor Vilmos keresztneve nem Apor\n");
    
    if (Apor_e_a_keresztneve("Kovács Apor"))
        printf("Kovács Apor keresztneve Apor\n");
    else
        printf("Kovács Apor keresztneve nem Apor\n");

    if (ez_e_a_keresztneve("Gipsz Jakab", "Jakab"))
        printf("Gipsz Jakab keresztneve Jakab\n");
    else
        printf("Gipsz Jakab keresztneve nem Jakab\n");

    char nev[100];

    fgets(nev, 100, stdin); // A sor végi ENTER-t is a név végére teszi. Mit lehet tenni ezzel?
    if (ez_e_a_keresztneve(nev, "Apor"))
        printf("%s keresztneve Apor\n", nev);
    else
        printf("%s keresztneve nem Apor\n", nev);

    char *enter;
    if ((enter = strchr(nev, '\n')) != NULL)
        *enter = '\0';

    char vez[100], ker[100];
    vez_ker_szetvalaszt_5(nev, vez, ker);
    printf("Vezeteknev: %s, keresztnev: %s\n", vez, ker);

    printf("%s\n", my_strstr("trallala", "all"));

    return 0;
}