Próba stworzenia łatwo rozszerzalnej tablicy stringów - czy mój sposób jest poprawny?

0

Próbuję stworzyć tablicę stringów, którą będzie można w łatwy sposób rozszerzać. Program, który napisałem kompiluje się i działa, jednak nie wiem czy jest on całkowicie poprawny z zasadami języka C.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **slowo;
void dodaj(char *wprowadzone);
void wypisz();
int licz = 0;
int main(){
dodaj("pierwsze");
dodaj("drugie");
dodaj("trzecie");
wypisz();
return 0;
}
void dodaj(char *wprowadzone){
licz++;
slowo = realloc(slowo, sizeof(char*)*licz);
int dlugosc = strlen(wprowadzone) + 1;
char *cos = malloc(dlugosc);
strcpy(cos, wprowadzone);
slowo[licz-1] = cos;
};
void wypisz(){
    int i;
    for(i = 0; i < licz; i++){
        printf("%s\n", slowo[i]);
    }
}

1

realokowanie za każdym razem gdy dodajesz nowy element to zły pomysł. np. w pythonie tablice są zaimplementowane w ten sposób, że alokowana jest pamięć dla 4 elementów, a gdy zabraknie, to powiększana jest o kolejne 4. następna rzecz która się rzuca w oczy to użycie zmiennych globalnych, których najlepiej unikać (chyba że masz dobrze uzasadnione zastosowanie zmiennych globalnych). dalej, jeśli wywalimy zmienne globalne, to tablicę i liczbę elementów tablicy zgrupował bym w strukturę. no i niepotrzebna jest zmienna cos. można od razu zarezerwować pamięć dla slowo[licz-1].
ja bym to zrobił tak:

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

#define STRARRAY_STEP 4

typedef struct {
	char **array; // tablica stringow
	size_t length; // na ile elementow zarezerwowane jest miejsce
	size_t elements; // ile elementow na prawde znajduje sie w tablicy
} strArray;

strArray *strArrayInit() {
	strArray *arr = (strArray *)malloc(sizeof(strArray));
	arr->length = STRARRAY_STEP;
	arr->elements = 0;
	arr->array = (char **)malloc(STRARRAY_STEP*sizeof(char*));
	return arr;
}

void strArrayAppend(strArray *arr, char *element) {
	if (arr->elements >= arr->length) {
		arr->length += STRARRAY_STEP;
		arr->array = (char **)realloc(arr->array, arr->length);
	}
	
	// uwaga: jeżeli drugi argument funkcji (string ktory chcemy dodac) jest stały np. ("jeden")
	// albo zmienna która nie jest modyfikowana w innej części programu, to nie musimy kopiować
	// jej całej zawartości, wystarczy że przypiszemy wskaźnik do niej. w przeciwnym wypadku
	// należy odkomentować kod poniżej i usunąć ostatnią linijkę w bloku.
	{
		//arr->array[arr->elements] = (char*)malloc(sizeof(char)*(strlen(element)+1));
		//strcpy(arr->array[arr->elements], element);
		arr->array[arr->elements] = element;
	}
	
	arr->elements += 1;
}

void strArrayPrint(strArray *arr) {
	int i;
	for (i=0; i<arr->elements; ++i) {
		printf("%s\n", arr->array[i]);
	}
}

int main(void) {
	strArray *slowo = strArrayInit();
	
	strArrayAppend(slowo, "jeden");
	strArrayAppend(slowo, "dwa");
	strArrayAppend(slowo, "trzy");
	strArrayAppend(slowo, "cztery");
	strArrayAppend(slowo, "piec");
	
	strArrayPrint(slowo);
	
	return 0;
}

i jeszcze ważna rzecz. w zależności od zastosowania, można by się pokusić o implementacje jako listy jedno-(dwu-)kierunkowej. jeśli stringi z tablicy będziesz odczytywał tylko po kolei i nie będziesz ich sortował, to lista była by o lepszym rozwiązaniem, bo unikniemy sytuacji, gdy przy realokacji zabraknie pamięci w danym miejscu i trzeba będzie całą tablicę kopiować w inne miejsce.

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