IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

13. diel - Funkcie s variabilným počtom a Typo argumentovať (stdarg.h)

V minulej lekciám, Ako testovať programy v C (knižnica assert.h) 2. časť , bola reč o TDD. Nedávno som sa pri potulkách internetom Stretol s celkom zaujímavú kniznica a rozhodol som sa, že vás s nou trocha zoznámim. Jedná sa o knižnice stdarg.h.

Všetky štandardné vstupné výstupné funkcií (knižnica stdio.h) s formátovaním používajte knižnice stdarg.h. Sú to Všetky funkciám ktore maju v časti názve slovo printf Alebo scanf, napríklad: printf (), sprintf (), fprintf (), a pod., Scanf (), sscanf (), fscanf (), a pod ... keď som si prezeral Súbor stdio.h, bol som veľmi prekvapený, kolkov je tam funkcií, s ktorými som sa este nestretol.

V tomto článku si v krátkosti vysvetlíme, Ako sa funkciám používať v prípade, že chcete použiť premenlivý počet argumentovať.

Ďalej si ukážeme príklad funkciám kde použijeme premenlivý počet a hľa premenlivé typy argumentovať.

A Nakoniec si vysvetlíme Ako s pomocou knižnice stdarg.h Pracovať vo funkciám s argumentom Ako ŠÚ pointer na funkciám.

Dajme tomu, že ste dostali za úlohu Napíšte krátky program s tymto zadaním:

Zadania

"Napíš funkciám, ktora zo zadaných celých čísiel (argumentovať) typu 'int' vyberie Najväčšie a vráti ho. Prvé číslo určuje počet čísiel, z ktorych sa bude výber Najväčšie. Počet zadaných čísiel Moze hoci ražni. "

Volanie Funkcie Moze hoci Sledujte priame prenosy:

1. najvacsie(2, 25, 68);  // 2 – počet argumentov, 25 a 68 – argumenty ( výsledok 68)
2.najvacsie(5, 56, 58, 98, 45, 33);  // 5 – počet argumentov, 56 …33 - argumenty (výsledok 98)

Priznám sa, že som Dlho premýšľal, ako to Napísať bez použitím stdarg.h a Nakoniec som na nič neprišiel. Ale ak má niekto nejaký nápad, napíšte to v komentároch, doplním to sem.

Klasicky by sa to dalo riešiť asi ľan takto:

1. int najvacsie(const int pocet, int a, int b);
2. int najvacsie(const int pocet, int a, int b, int c, int d, int e);

Ale to neries jednu funkciám na variabilný počet vstupov, Preto sa pozriem ako to Napísať s použitím knižnice stdarg.h.

Najprv som napísal to čo chce dosiahnuť, čiže funkciám main ().

#include <stdio.h>

int main(void)
{
    printf("Najvacsie cislo: %d\n", najvacsie(4, 5, 78, 78, -46));
    printf("Najvacsie cislo: %d\n", najvacsie(7, 2565, 1178, 925, 12546, 2568, 12547, 1234));
    printf("Najvacsie cislo: %d\n", najvacsie(4, -85, -78, -78, -46));

    return 0;
}

Teraz si napíšeme funkciám s variabilným počtom argumentovať.

Úplný funkčný prototyp Funkcie vyzerá takto:

int najvacsie(const int pocet_argumentov, ...);

Pekné, že áno?

Samotná funkciám je tu:

int najvacsie(const int pocet_argumentov, ...) // 1
{
    int i = -1, argumenty_int, pom = INT_MIN, vysledok; // 3
    va_list argumenty; // 4
    va_start(argumenty, pocet_argumentov); // 5

    while((++i) ^ pocet_argumentov) { // 7
        argumenty_int = va_arg(argumenty, int); // 8
        vysledok = pom > argumenty_int ? pom : argumenty_int; // 9
        pom = vysledok;
    }
    va_end(argumenty); // 12

    return vysledok;
}

Vysvetlíme si jednotlivé časti kódu:

  • 3 - deklarácia premenných
  • 4 - vyvíjaním ukazovateľom, ktory moze ukazovať na blok argumentovať / typ §va_list z knižnice /
  • 5 - spustí Spolupráca s blokom argumentovať / funkciám va_start () z knižnice /
  • 6 - prechod vsetkym argumentom v bloku argumentovať
  • 7 - vložením získaného argumentu do premennej
  • 8-9 - výpočet najväčšieho čísla
  • 12 - ukončenie práce s blokom argumentovať / funkciám va_end () z knižnice /

A to je celé.

Ďalej tu mám pre vás ukážku Funkcie miniprintf () s variabilným počtom a Typo argumentovať.

Ukážka funkcie miniprintf ()

Je to funkciám, ktora vypíše na obrazovku zadanej premenné typu int, char a string, ale dala by sa samozrejme rozšíriť aj na ostatné formátovacom prvky.

#include <stdio.h>
#include <stdarg.h>

void miniprintf(char *fmt, …) // *fmt je pointer na makro, ktoré rieši formátovacie prvky
{
    va_list ap;
    int d;
    char c, *s;

    va_start(ap, fmt);
    while (*fmt)
        switch(*fmt++) {
    case 's':  /* string */
        s = va_arg(ap, char *);
        printf("string %s\n", s);
        break;
    case 'd':  /* int */
        d = va_arg(ap, int);
        printf("int %d\n", d);
        break;
    case 'c':  /* char */
        c = (char) va_arg(ap, int);
        printf("char %c\n", c);
        break;
    }
    va_end(ap);
}

int main(void)
{
    int i = 25;
    char c  = 'A';
    char *s = "test";

    miniprintf("%d\n%c\n%s\n", i, c, s);

    return 0;
}

Musím sa priznať, že Ako pracuje * fmt, __fmt Alebo * format v tychto funkciách mi nie je celkom jasné, ai keď som sa dosť túlal po nete. Ak to niekto vie, prosím o doplnenie.

Na koniec si vysvetlíme prácu Funkcie s argument typu pointer na funkciám.

Práca Funkcie s argumentom typu pointer na funkciám

Najskôr si pozrite dve Funkcie main () (samozrejme, že kódu je v programe podstatne viac), ktore robia to isté, ale v kóde sa pomerne dosť odlišujte.

int main(void)
{
    int vyber;

    srand(time(0));
    printf("Ak je to tvoja prva hra, stlac cislo 1, ak nie, stlac cislo 2 ");
    scanf(" %d", &vyber);
    if (vyber == 1) {
        vytvor_pole(pole);
        zahajenie();
        ulohy(pole);
        vypis(pole);
        uloz_txt(pole);
        uvolni_pole(pole);
    }
    else {
        vytvor_pole(pole);
        nacitaj_txt(pole);
        zahajenie();
        vypis(pole);
        ulohy(pole);
        vypis(pole);
        uloz_txt(pole);
        uvolni_pole(pole);
    }

    return 0;
}
int main(void)
{
    int vyber;

    srand(time(0));
    printf("Ak je to tvoja prva hra, stlac cislo 1, ak nie, stlac cislo 2 ");
    scanf(" %d", &vyber);
    if (vyber == 1) {
        foo(7, vytvor_pole, zahajenie, ulohy, vypis, uloz_txt, uvolni_pole);
    }
    else {
        foo(7, vytvor_pole, nacitaj_txt, zahajenie, vypis, ulohy, vypis, uloz_txt, uvolni_pole);
    }

    return 0;
}

Určite ste si všimli, že jediný Rozdiel je v tom, že v prvej funkciám sa Funkcie Volajte klasicky, teda názvom, zátvorkou a vstupnými parametrami a v druhej za pomoci Funkcie foo (), Ako ho variabilné parametre, ale už sa Volajte iba názvom.

Moze to byť dosť výhodné, ak treba pri Pisano, alebo ladenie programu často s funkciám manipulovať, takto je to myslím rýchlejšími a jednoduchšie.

Ako teda vyzerá funkciám foo ()?

Úplný funkčný prototyp je jednoduchý:

void foo(const int, ...);

a vlastne ani samotný kód nie je zložitá:

void foo(const int num_of_func, ...)
{
    va_list args;
    int i;
    va_start(args, num_of_func);
    for (i = 0; i < num_of_func; i++) {
        void (*bar)() = va_arg(args, void (*)());
        (*bar)();
    }
    va_end(args);
}

Oproti tomu, čo sme si tu dnes Povedala, ŠÚ tú ľan dver "odlišnosti":

void (*bar)() = va_arg(args, void (*)());

vloží do prázdneho pointera void (* bar) () pointer na konkrétnych funkciám z bloku

a

(*bar)();

zavolá konkrétnych funkciám.

Ako som už v úvode pisala, nemám s tím ešte veľké Skúsenosti, ale Aj napriek tomu som vás chcel nasmerovať na Niečo, čo ste možno ešte nepoužili a bolo by to pre vás výhodné.

Do prílohy som vložil nejaké zdrojáky, aby ste si to mohli bezpracné vyskúšať. Je tam hľa jeden projektík, ale scompilovaný na Linux. Nie je však problém scompilovať ho ja na win.

Ak máte výhrady, iné Skúsenosti, popripade nejaké nápady na vylepšením článku, napíšte do komentárov, budem sa tešiť. ;-)

Kurz programovaním v jazyku C pokračuje Práca so subor.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 45x (17.56 kB)
Aplikácia je vrátane zdrojových kódov v jazyku C

 

Predchádzajúci článok
Ako testovať programy v C (knižnica assert.h) 2. časť
Všetky články v sekcii
Pokročilé konštrukcia jazyka C
Článok pre vás napísal Libor Šimo (libcosenior)
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Obľúbil som si jazyk C a snažím sa ho spoznať čo najhlbšie. Začal som používať c# WPF, je to krása.
Aktivity