Funkcja ze zmienną liczbą argumentów - zapewnienie obsługi błędów

0

Witam napisałem taki kod

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

char * sklej(int n, ...)
{
    va_list lista;
    va_start (lista,n);
    int dlugosc=0,i;


    for(i=0;i<n;i++)
    {
        dlugosc+=strlen(va_arg(lista, char*));

    }
    dlugosc++;
    printf("dlugosc: %d\n", dlugosc);
    va_end(lista);
    char * lancuszek;
    lancuszek=(char*)malloc(dlugosc*sizeof(char));
    if(lancuszek==NULL)
    {
        printf("blad przydzielenia pamieci\n");
        return NULL;
    }

    va_start (lista,n);
    int j=0,k=0;
    char * argument;
    for(i=0;i<n;i++)
    {
        argument=va_arg(lista, char*);
            for(j;j<dlugosc;j++)
            {
                *(lancuszek+j)=*(argument+k);
                if(*(argument+k)=='\0')
                {
                    k=0;
                    break;
                }
                else
                {
                    k++;
                }
            }
    }
    va_end(lista);
    *(lancuszek+dlugosc)='\0';
    return lancuszek;

}

int main(int argc, char *argv[])
{
    char * test;
    if((test=sklej(3, "janusz", " pali ", "koty"))==NULL)
    {
        printf("blad");
    }
    else
    {
        printf("%s", test);
    }
    free(test);
    return 0;
}
 

Mam problem z zapewnieniem obsługi błędów, ponieważ nie wiem na co się powołać jeżeli do funkcji przekażemy mniej argumentów niż zadeklarowano, tzn. podajemy, że przekazujemy 4 argumenty a w rzeczywistości są tylko 3. Starałem się poszukać jakichś informacji co stanie się gdy funkcji va_arg zabraknie argumentów do wczytania ale dowiedziałem się, że będzie zwracać losowe błędy. W rzeczywistości objawia się to losowymi znakami gdy program odwołuje się do pamięci do której nie zostało nic przypisane.

  1. W jaki sposób mogę w funkcji sprawdzić czy liczba przekazanych argumentów zgadza się z tą zadeklarowaną?
  2. Co zrobić by te łańcuchy znaków mógł wprowadzić użytkownik z poziomu konsoli, tzn. wiem jak miałbym je wczytać ale jak przekazać je za jednym razem do funkcji sklej w takiej postaci jak jest teraz?
    Sorry za mało profesjonalne wysławianie się ale nie mam jeszcze za wielkiego doświadczenia :). Z góry dziękuje za wszelkie sugestie.
0

W przypadku jeśli używasz standardowego string-a formatującego, to kompilator udostępnia ostrzeżenie, że coś nie pasuje do tego string-a formatującego.
W innych przypadkach nie ma mechanizmu sprawdzającego, chyba, że kompilator udostępnia własny mechanizm.

Jest jednak na to obejście :).

/**
 * wymagany NULL jako ostatni argument.
 */
char * sklejF(const char *pierwszy, ...) {
     …
}

#define sklej( ...) sklejF(##__VA_ARGS__ ,  NULL)

Jak ktoś będzie używał makra to na pewno nie zapomni dopisać NULL na końcu :).
Niestety zapomnij o sprawdzaniu poprawności typów.

Przy okazji funkcje zwracające nowo alokowany fragment pamięci i mające jakąś logikę, zawsze wzbudzają u mnie niechęć (szczególnie, gdy ich nazwa wyraźnie nie mówi o alokowaniu pamięci).
Osobiście preferuję podzielić to na części:

int vPoliczSumeDlugosci(const char *pierwszy, va_list arg) {
     …
}

int policzSumeDlugosci(const char *pierwszy, ...) {
     …
}

void vSklejDo(char *cel, const char *pierwszy, va_list arg) {
     …
}

void sklejDo(char *cel, const char *pierwszy, ...) {
     …
}

char *alokujSklejone(const char *pierwszy, ...) {
    va_list lista;
    va_start (lista, pierwszy);
    char *wynik = alloc(vPoliczSumeDlugosci(pierwszy, lista)+1);
    if (wynik) {
          vSklejDo(wynik, pierwszy, lista);
    }
    va_end(lista);
    return wynik;
}
0

Dzięki **MarekR22 **za rzeczową odpowiedź,
**n0name_l **cóż z tego, że istnieje - takie są uroki ćwiczeń, że powtarza się już istniejące funkcje ale pisząc ich samodzielne odpowiedniki.

1 użytkowników online, w tym zalogowanych: 0, gości: 1