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

10. alkalom: rendezés, fájlkezelés, parancssori paraméter

1. feladat

Egy szöveges fájlban emberek adatai találhatók. A fájl első sora az emberek számát tartalmazza, majd ennyi ember adatait. Egy embert négy sornyi adat ír le: név, foglalkozás, magasság, testsúly. Pl.:

3
Gipsz Jakab
traumatológus
178
77
Pohl Lenke
allergológus
172
68
Kasza Blanka
sebész
163
48

a) Definiálj struktúrát egy ember adatainak tárolására! Feltételezheted, hogy a név max. 40 karakter, a foglalkozás max. 50 karakter. Mindkettőben lehet szóköz is.

b) Írj függvényt, amely paraméterként kapja a szöveges fájl nevét, és egy megfelelő méretű dinamikus struktúratömbben visszaadja a fájlból beolvasott adatokat. A függvény NULL pointert adjon vissza, ha a fájlt nem lehet megnyitni, vagy nincs elég memória a dinamikus tömb létrehozásához!

c) Írj függvényt, amely egy paraméterként kapott nevű bináris fájlba menti a struktúratömböt! A fájl első adata a tömb mérete, melyet a tömbelemek követnek. A függvény logikai értéket ad vissza, ami a mentés sikerességét mutatja.

d) Írj függvényt, amely egy paraméterként kapott nevű bináris fájlból beolvas egy struktúratömböt egy éppen megfelelő méretű dinamikus tömbbe! A fájl formátuma a c) feladatban megadott. A függvény NULL pointert adjon vissza, ha a fájlt nem lehet megnyitni, vagy nincs elég memória a dinamikus tömb létrehozásához!

e) Írj függvényt, amely névsorba rendezi a paraméterkét átvett struktúratömböt!

f) Egészítsd ki teljes programmá, melyben bemutatod a függvények használatát!

2. feladat

Írj függvényt, amely valós számokból álló tömböt kap, és azt növekvő sorrendbe rendezi! Segédtömböt ne használj! Írj főprogramot, melynek segítségével kipróbálod a rendezést! Rendezd a tömböt a könyvtári qsort függvénnyel is! Próbáld ki a rendezéseket normál és dinamikus tömbbel is!

3. feladat

Definiálj struktúrát, amely egy ember nevét (max. 40 betűből álló sztring) és egyedi azonosítószámát (egész érték) tartalmazza! Hozz létre egy dinamikus tömböt ilyen struktúrákból, töltsd fel adatokkal, és rendezd
a) azonosító szerint!
b) név szerint!
A rendezést végezd el saját függvénnnyel és a qsorttal is! Rendezd növekvő és csökkenő sorrendbe is!

4. feladat

Írj programot, amely kiírja a saját parancssori paramétereit! Próbáld ki parancssorból futtatva!

5. feladat

Írj programot, amely parancssori paraméterként kapja két fájl nevét, és az első fájlt átmásolja a másodikba!

Az órai feladatok mintamegoldása

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

typedef struct {
    char nev[41];
    char foglalkozas[51];
    int magassag, suly;
} ember;

char *masol_enter_nelkul(char *cel, const char *forras, int maxhossz) {
// A fgets a sorvégi entert is beolvassa, ezt le kell vágnunk.
    int i;
    if (forras == NULL)
        return NULL;
    for (i = 0; i < maxhossz && forras[i] != '\0' && forras[i] != '\n'; i++)
        cel[i] = forras[i];
    cel[i] = '\0';
    return cel;
}

ember *beolvas(const char *fajlnev, int *vissza_tomb_meret) {
    FILE *fp = fopen(fajlnev, "rt");
    char puffer[60];
    int n, i;
    ember *tomb;

    if (fp == NULL)
        return NULL;

    // ne keverjük a teljes sort beolvasó fgets-t a fscanf-fel!
    // ezért csak fgets-sel olvasunk a fájlból
    // Ha számot kell beolvasni, azt a beolvasott sornyi sztringből
    // sscanf-fel olvassuk ki.

    if(fgets(puffer, 60, fp)==NULL)
        return NULL;

    // tömbméret
    if (sscanf(puffer, "%d", &n) != 1)
        return NULL;

    tomb = (ember*)malloc(n*sizeof(ember));
    if (tomb == NULL)
        return NULL;

    // emberek beolvasása

    for (i = 0; i < n; i++) {
        if (masol_enter_nelkul(tomb[i].nev, fgets(puffer, 60, fp), 40) == NULL)
            return NULL;
        if (masol_enter_nelkul(tomb[i].foglalkozas, fgets(puffer, 60, fp), 50) == NULL)
            return NULL;
        if (fgets(puffer, 60, fp) == NULL || sscanf(puffer, "%d", &tomb[i].magassag)!=1)
            return NULL;
        if (fgets(puffer, 60, fp) == NULL || sscanf(puffer, "%d", &tomb[i].suly) != 1)
            return NULL;
    }

    fclose(fp);

    *vissza_tomb_meret = n;
    return tomb;
}

void tombkiir(ember *t, int n) {
    int i;
    for (i = 0; i < n; i++) {
        printf("%s, %s, %d, %d\n", t[i].nev, t[i].foglalkozas, t[i].magassag, t[i].suly);
    }
    printf("\n");
}

bool ment(const char *fajlnev, ember *tomb, int n) {
// bináris fájlba
    FILE *fp = fopen(fajlnev, "wb");
    if (fp == NULL)
        return false;
    if (fwrite(&n, sizeof(int), 1, fp) != 1)
        return false;
    if (fwrite(tomb, sizeof(ember), n, fp) != n)
        return false;
    fclose(fp);
    return true;
}

ember *bin_olvas(const char *fajlnev, int *vissza_tomb_meret) {
// bináris fájlból olvasni sokkal egyszerűbb, mint szövegesből
    FILE *fp = fopen(fajlnev, "rb");
    int n;
    ember *tomb;

    if (fp == NULL)
        return NULL;

    // tömbméret
    if (fread(&n, sizeof(int), 1, fp) != 1)
        return NULL;

    tomb = (ember*)malloc(n*sizeof(ember));
    if (tomb == NULL)
        return NULL;

    // emberek beolvasása
    if (fread(tomb, sizeof(ember), n, fp) != n)
        return NULL;

    fclose(fp);

    *vissza_tomb_meret = n;
    return tomb;
}

int hasonlit(const void *p1, const void *p2) {
    const ember *a = (const ember*)p1;
    const ember *b = (const ember*)p2;
    return strcmp(a->nev, b->nev);
}

void rendez(ember *tomb, int n) {
    qsort(tomb, n, sizeof(ember), hasonlit);
}

int main(){
    ember *tomb;
    int n;

    tomb = beolvas("D:\\emberek.txt", &n);

    if (tomb == NULL) {
        printf("Sikertelen beolvasas (emberek.txt)\n");
        return 1;
    }
    tombkiir(tomb, n);

    if (!ment("ember.adat", tomb, n)) {
        printf("Sikertelen kiiras (ember.adat)\n");
        return 1;
    }

    // töröljük a dinamikus tömböt, hogy ne legyen memóriaszivárgás
    free(tomb);

    // újrahasznosítjuk a pointert, most egy másik tömbre mutat
    tomb = bin_olvas("ember.adat", &n);

    if (tomb == NULL) {
        printf("Sikertelen beolvasas (ember.adat)\n");
        return 1;
    }
    tombkiir(tomb, n);

    rendez(tomb, n);
    tombkiir(tomb, n);

    free(tomb);

    return 0;
}

 

2. feladat
#include <stdio.h>
#include <stdlib.h>

void rendez(double tomb[], int meret){
    int i,j,minindex;
    
    // Az i. tömbelem helyére becseréljül az utána lévo tömbrészbol a legkisebbet
    
    for(i=0; i<meret; i++){
        
        // Megkeressük a legkisebbet a még renddezetlen részen
        
        minindex=i; // Minimumkeresés: a minindex tárolja az eddig megtalált legkisebbet
        for(j=i+1; j<meret; j++){
            if(tomb[j]<tomb[minindex])
                minindex=j;
        }

        // Ha nem a helyén van, megcseréljük

        if(minindex!=i){
            double temp=tomb[i];
            tomb[i]=tomb[minindex];
            tomb[minindex]=temp;
        }
    }
}

int hasonlit(const void *tombelem1, const void *tombelem2){
    const double *a,*b;
    a=(const double*)tombelem1;
    b=(const double*)tombelem2;
    if(*a<*b)return -1; // Ha az 'a' által mutatott tömbelem kisebb, mit a 'b' által mutatott.
    if(*a>*b)return 1;
    return 0; // Ha egyenloek
}

int main(){
    double tomb1[10]={8,-5,1,7,-3,2,10,0,9,4};
    double tomb2[10];
    double *tomb3,*tomb4;
    int i;

    // dinamikus tömbök létrehozása

    tomb3 = (double*)malloc(10*sizeof(double));
    tomb4 = (double*)malloc(10*sizeof(double));
    if(tomb3==NULL || tomb4==NULL) return 1; // sikertelen foglalás

    // átmásoljuk tomb1 tartalmát a böbbibe

    for(i=0; i<10; i++)
        tomb2[i] = tomb3[i] = tomb4[i] = tomb1[i];

    rendez(tomb1,10); // normál tömb rendezése
    rendez(tomb3,10); // dinamikus tömb rendezése: semmi különbség nincs!

    qsort(tomb2,10,sizeof(double),hasonlit);
    qsort(tomb4,10,sizeof(double),hasonlit);

    // kiírás ellenorzésképpen

    printf("\n%g", tomb1[0]); for(i=1; i<10; i++)printf(", %g", tomb1[i]);
    printf("\n%g", tomb2[0]); for(i=1; i<10; i++)printf(", %g", tomb2[i]);
    printf("\n%g", tomb3[0]); for(i=1; i<10; i++)printf(", %g", tomb3[i]);
    printf("\n%g", tomb4[0]); for(i=1; i<10; i++)printf(", %g", tomb4[i]);
    printf("\n");

    // A dinamikus tömbök felszabadítása

    free(tomb3);
    free(tomb4);

    return 0;
}

 

3. feladat
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

typedef struct {
    char nev[40+1];  // A lezáró nullának is kell hely.
    int azonosito;
} Ember;

void kiir(Ember tomb[], int meret){
    int i;
    for(i=0; i<meret; i++)
        printf("%-15s %d\n",tomb[i].nev,tomb[i].azonosito);
    printf("\n");
}

void rendez_a(Ember tomb[], int meret){
    int i,j,minindex;
    
    for(i=0; i<meret; i++){
        
        minindex=i;
        for(j=i+1; j<meret; j++){
            if(tomb[j].azonosito<tomb[minindex].azonosito)
                minindex=j; // Ha megfordítjuk a relációs jelet, csökkenõ sorrendbe rendez.
        }

        if(minindex!=i){
            Ember temp=tomb[i];
            tomb[i]=tomb[minindex];
            tomb[minindex]=temp;
        }
    }
}

void rendez_b(Ember tomb[], int meret){
    int i,j,minindex;
    
    for(i=0; i<meret; i++){
        
        minindex=i;
        for(j=i+1; j<meret; j++){
            if(strcmp(tomb[j].nev,tomb[minindex].nev)<0)
                minindex=j; // Ha megfordítjuk a relációs jelet, csökkenõ sorrendbe rendez.
        }

        if(minindex!=i){
            Ember temp=tomb[i];
            tomb[i]=tomb[minindex];
            tomb[minindex]=temp;
        }
    }
}

int hasonlit_a(const void *a, const void *b){
    Ember * p1 = (Ember*)a;
    Ember * p2 = (Ember*)b;
    return p1->azonosito - p2->azonosito; // Ha a -1-szeresét adjuk vissza, csökkenobe rendez.
}

int hasonlit_b(const void *a, const void *b){
    Ember * p1 = (Ember*)a;
    Ember * p2 = (Ember*)b;
    return strcmp(p1->nev, p2->nev); // Ha a -1-szeresét adjuk vissza, csökkenobe rendez.
}

int main(){
    char *nevek[10]={"Szent Istvan","Kossuth Lajos","Hunyadi Matyas","Deak Ferenc",
                     "Maria Terezia", "Dozsa Gyorgy", "Pazmany Peter", "Rakoczi Ferenc",
                     "Konyves Kalman", "Mikes Kelemen"};
    int i;
    Ember *dintomb;

    dintomb = (Ember*)malloc(sizeof(Ember)*10); // 10 elemu din. tömböt foglalunk
    if(dintomb==NULL){
        printf("Hiba: sikertelen foglalas.\n");
        exit(1);
    }

    srand(time(NULL));
    for( i=0; i<10; i++){
        strcpy(dintomb[i].nev,nevek[i]);
        dintomb[i].azonosito = rand();
    }

    printf("Az eredeti tomb:\n");
    kiir(dintomb,10);

    rendez_a(dintomb,10);
    printf("Azonosito szerint rendezve:\n");
    kiir(dintomb,10);

    rendez_b(dintomb,10);
    printf("Nev szerint rendezve:\n");
    kiir(dintomb,10);

    qsort(dintomb,10,sizeof(Ember),hasonlit_a);
    printf("Azonosito szerint rendezve:\n");
    kiir(dintomb,10);

    qsort(dintomb,10,sizeof(Ember),hasonlit_b);
    printf("Nev szerint rendezve:\n");
    kiir(dintomb,10);

    free(dintomb);

    return 0;
}

 

4. feladat
#include <stdio.h>

int main(int db, char **tomb){
    int i;

    for (i = 0; i < db; i++)
        printf("%d: %s\n", i, tomb[i]);
    return 0;
}

 

5. feladat
#include <stdio.h>

int main(int db, char **tomb){
    FILE *fbe, *fki;
    int n;
    char puffer[1024];

    if (db < 3){
        printf("Hasznalat: prog.exe forrasfajlnev celfajlnev\n");
        return 1;
    }

    fbe = fopen(tomb[1], "rb");
    if (fbe == NULL){
        printf("Nem tudom megnyitni a %s fajlt\n", tomb[1]);
        return 1;
    }

    fki = fopen(tomb[2], "wb");
    if (fki == NULL){
        printf("Nem tudom megnyitni a %s fajlt\n", tomb[2]);
        return 1;
    }

    while ((n = fread(puffer, sizeof(char), 1024, fbe))>0)
        fwrite(puffer, sizeof(char), n, fki);

    fclose(fbe);
    fclose(fki);

    return 0;
}