Zwracanie tablicy przez funkcję

0

Witam wszystkich,

ostatnio dostałem do rozwiązania pewien problem, mianowicie przekazywanie / zwracanie tablicy do funkcji w języku C.
Zadanie polegało na tym aby stworzyć funkcję, która przyjmuje tablicę znaków, a zwraca nową tablicę, pomniejszoną o cyfry występujące w tej pierwszej tablicy (fajnie jakby i rozmiar tej nowej tablicy się zmniejszył do niezbędnego minimum), oraz zwraca ilość wystąpień każdej cyfry w tablicy wejściowej).

Wymyśliłem coś takiego, ale nie wiem czy to jest najoptymalniejsze rozwiązanie (kod się pewnie nie kompiluje, wymyślony na szybko):

char * funkcja(char string[], char *wsk_do_zwrocenia, int cyfry[10])
{
memset(cyfry, 0, 10 * sizeof(int));
int i = 0, j = 0;
char * tmp = (char
)calloc(strlen(string)+1,1);
while(string[i] != '\0')
if(isdigit(string[i]))
++cyfry[string[i++] - '0'];
else
tmp[j++]=string[i++];
*wsk_do_zwrocenia= calloc(strlen(tmp)+1,1);
strcpy(tmp,*wsk_do_zwrocenia);
free(tmp);
return *wsk_do_zwrocenia;
}

int main()
{
char * tablica = "sdsa7d6783ry348y3728f784rfg74378f34";
char * nowatablica;
char cyfry[10];
funkcja(tablica, &nowatablica, cyfry);
free(nowatablica);
}

Proszę o wszelkie uwagi, czy tak można zrobić, czy free(nowatablica) zadziała tak jak powinno etc).

Pozdrawiam.

0

Na pierwszy rzut oka jest w porządku. free zadziała poprawnie.

fajnie jakby i rozmiar tej nowej tablicy się zmniejszył do niezbędnego minimum

Możesz użyć realloc zamiast kopiować wszystko do nowej tablicy. Jeżeli zależy ci na wydajności nawet nad realloc można się zastanawiać czy ma sens, bo nawet w przypadku zmniejszenia kawałka pamięci na stercie runtime C / system operacyjny ma prawo skopiować wszystko do nowego miejsca.

edit: typ argumentu cyfry ci się nie zgadza (alokujesz tablicę char, a przyjmujesz int).

0

Z tym char/int to literówka. A da się zrobić tak, żeby nie trzeba było poza funkcją używać free na zwróconym wskaźniku i jednocześnie uniknąć wycieku pamięci ? Albo da się tak zrobić, żeby nie przesyłać jako argument funkcji adresu wskaźnika ?

0

Nic ciekawego już z tym nie zrobisz. Tak działa C. Żebyś nie musiał wołać free trzeba by użyć inteligentnego wskaźnika liczącego odwołania czy działającego w scope, ale do tego potrzebne jest wsparcie od strony języka, które C otrzymało dopiero w C++ czy Objective C. Albo w ogóle całe GC. Są jakieś pomniejsze rozwiązania dla C, poszukaj w google pod hasłem "smart pointer C".

0

Można to zrobić bez realokacji pamięci. W niektórych przypadkach wykona się nawet szybciej.

char * funkcja(const char *string, char **wsk_do_zwrocenia, int *cyfry)
  {
   memset(cyfry,0,10*sizeof(int));
   int n=0;
   char ch,*tmp=string;
   cyfry-='0'; // teraz cyfry to tablica z poprawną indeksacją '0'..'9'
   while((ch=*(tmp++))!=0) if(isdigit(ch)) ++cyfry[ch]; else ++n;
   tmp=(char*)malloc(n+1);
   *wsk_do_zwrocenia=tmp;
   char *cp=string;
   while((ch=*(cp++))!=0) if(!isdigit(ch)) *(tmp++)=ch;
   *tmp=0;
   return *wsk_do_zwrocenia;
  }

Poza tym może warto się zastanowić nad przekazaniem bufora który możesz psuć:

char * funkcja(char *string,int *cyfry)
  {
   char *wsk_do_zwrocenia=string,*tmp=string,*out=string,ch;
   memset(cyfry,0,10*sizeof(int));
   cyfry-='0';
   while((ch=*(tmp++))!=0) if(isdigit(ch)) ++cyfry[ch]; else *(out++)=ch;
   *out=0;
   return wsk_do_zwrocenia;
  }

int main()
{
    char tablica[]= "sdsa7d6783ry348y3728f784rfg74378f34";
    char cyfry[10];
    char *nowatablica=funkcja(strdup(tablica),cyfry); // sposób wywołania jeżeli jednak nie chcesz psuć tablica
    free(nowatablica);   
}

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