Karakterláncok és mutatók

Karakterláncok és mutatók

Az alábbi kódokkal a mutatók használatának alapfokú alkalmazási lehetőségeit kívánom bemutatni. Ebben az esetben a mutatók a karakterláncok (karakterek egydimenziós tömbje) karakterpozícióinak (memóriacímének) megtalálására korlátozódnak. Ezzel a megoldással ellenőrizhetünk például fájlneveket vagy manipulálhatunk karakterláncokat, de a fájlok méretét is a mutatópozíciók alapján tudhatjuk meg.

 

Karakterláncok manipulálása

Az első példakódban egy karakterláncot forgatunk el oly módon, hogy a forgatás mértékét és gyakoriságát is megadjuk. A forgat függvény egy elforgatott karakterlánccal tér vissza, argumentumként pedig az elforgatandó karakterláncot és az elforgatás mértékét kéri be. Jelen esetben ez utóbbi 3-ra definiált (#define F 3), ami azt jelenti, hogy a mutató az elforgatandó karakterlánc végére, egész pontosan a végétől számítva a harmadik karakter címére mutat. Ez a gyakorlatban azt jelenti, hogy az elforgatáshoz a karakterlánc végéről három karaktert leválaszt [*p >> strcpy(res,p)], majd az eléjéhez fűzi [strcat(res,s)]. Mivel itt több példányon keresztül, közvetett műveletekkel valósul meg a forgatás, a strcpy karakterlánc másoló függvényre többször is szükség van. A forgatás gyakoriságáról egy for ciklus gondoskodik a main függvényben, ennek száma példánkban szintén 3-ra definiált (#define N 3).

 

#include <stdio.h>
#include <locale.h>
#include <windows.h>

#define F 3
#define N 3 

//karakterláncot elforgat
char *forgat(char s[], int f) {
    
    int len = strlen(s);
    char *p = &s[len - f];
    char *res = (char*)malloc(len+1);
    strcpy(res,p);
    s[len - f] = '\0';
    strcat(res,s);
    strcpy(s, res); //átalakított legyen az eredeti helyén! <- globálisan megváltoztatja
    
    return res;
}

int main() {

    setlocale(LC_ALL, "Hungarian_Hungary.1250");
    
    //karakterlánc elforgatása többször
    char s[] = "HelloWorld";
    printf("Elforgatandó szó: %s\nMennyivel: %d\nHányszor: %d\n\n", s,F,N);
    int i;
    for (i = 0; i < N; i++) {
        char *forg = forgat(s, F);
        printf("%d. Elforgatás: %s\n", i+1,forg);
        free(forg);
    }
    
    return 0;
}

A fenti kódban megfigyelhető, hogy a forgat függvény visszatérése előtt az s karakterlánc felülírásra kerül [strcpy(s,res)], ezért a következő elforgatásnál a felülírt s fog rendelkezésre állni. Az is látható, hogy forgat függvény visszatérési értékének (res) memóriafoglalása a függvényen belűl történik, míg a felszabadítás a main függvényben. Ez utóbbit olyan függvények esetében alkalmazhatjuk, amelyek a visszatérési érték számára dinamikusan foglalják le a memóriát, pl. a malloc függvénnyel.

Az alábbi képen a program kimenete látható. A HelloWorld szót forgattuk el, három karakterrel és három alkalommal. Az első elforgatásnál látható, hogy a szó utolsó három karaktere “rld” a szó elejére kerül, megalkotva az “rldHelloWo” szót. Mivel az elforgatás összesen háromszor történik meg, ezért az eredetileg megadott szóból végül “elloWorldH” lesz.

 

A program kimenete

 
Karakterláncok validálása

A mutatók a C nyelvben nem csak karakterláncok manipulálására hanem validálására is alkalmasak. Az alábbi fval függvény ellenőrzi, hogy egy txt kiterjesztesű szöveges fájl neve megfelel-e az alapvető formai elvárásoknak. Ehhez csak arra van szükség, hogy igaz legyen: a fájlnév/karakterlánc utolsó három karaktere azonos a “txt” karakterlánccal. A *ptr mutató a strchr függvény segítségével a karakterlánc ‘.’ utáni pozícióját (valójában a memóriacímét) veszi fel, majd az itt elhelyezkedő “karakterlánc-töredéket” hasonlítja össze a megadott kiterjesztéssel, esetünkben a “txt”-vel. Az összehasonlításhoz a strcmp függvényt hívja meg.

 

#include <stdio.h>
#include <locale.h>
#include <windows.h>

//fájlnév érvényesség
int fval(char *s, char *kit) {
    
    char *ptr = strchr(s, '.') + 1;
    if (strcmp(ptr, kit) != 0)
        return 1;
    
    return 0;
}

int main() {
    
    //magyar nyelvű konzol
    setlocale(LC_ALL, "hun");
    
    char *fnev = "pelda.txt", *kit = "txt";
    printf("Ellenőrzi, hogy a fájlnév %s kiterjesztésű-e?\n", kit);
    if (fval(fnev, kit) == 0)
        printf("A %s: Helyes fájlnév!\n", fnev);
    else
        printf("A %s: Helytelen fájlnév\n", fnev);
    
    return 0;
}

Az alább látható konzol képeken egy helyes illetve egy hibás bemenet kiértékelése látható.

 

A kimenet helyes input megadásakor

A kimenet helytelen input megadásakor

A fájlmutató

A mutatóknak a fájlok olvasása, írása esetén is szerepe van. Amikor C-ben megnyitunk egy fájlt, akkor egy úgynevezett fájlmutatót definiálunk. Ez látható az alábbi kódrészletben.

FILE *fp;

fp = fopen("teszt.txt","r");
if(!fp){
 perror("");
 return fp;
}

/* Műveletek fájlokkal */

fclose(fp);

Az alábbi példa egy fájl méretet meghatározó C függvény, amely a mutatót fájl végére pozícionálja és visszatér ezzel az értékkel (res). A függvény a visszatérés előtt visszaállítja a fájlmutató eredeti pozícióját (pos), így a program a továbbiakban innen folytathatja a fájlon végzendő műveleteket. A res egy lebegőpontos érték, ami a fájl bájtokban vett mérete. Példánkban azonban a definiált váltószám 1024, tehát a függvény visszatérési értéke kilobájtban értendő.

#define VALTO 1024

//fájlméret
float fmeret(FILE *fp) {
 float res;
 int pos = ftell(fp);
 fseek(fp, 0L, SEEK_END);
 res = (float)ftell(fp);
 fseek(fp, pos, SEEK_SET);
 return res /VALTO;
}