2013-09-28 23 views
18

Próbuję napisać program, który czyta serię ciągów z pliku tekstowego i zapisuje je w tablicy łańcuchów, dynamicznie alokując pamięć dla każdego elementu. Mój plan polegał na przechowywaniu każdego ciągu znaków w tablicy przy użyciu wskaźnika, a następnie zwiększeniu rozmiaru tablicy, gdy więcej było czytanych. Mam problem z zrozumieniem, dlaczego mój testowy kod nie działa. Czy to jest praktyczny pomysł?Dynamiczna alokacja pamięci dla tablic wskaźnika

+1

To nie działa, ponieważ 'malloc' przestrzeni dla pojedynczego znaku, a następnie spróbować przypisać cały ciąg do' char' wpisany lwartości. –

+0

Zalecane uwagi: [Kiedy należy używać malloc w C i kiedy nie mam?] (Http://stackoverflow.com/a/1963812/2455888). – haccks

Odpowiedz

15

W języku C ciąg znaków to char*. Tablica dynamiczna typu T jest reprezentowana jako wskaźnik do T, więc dla char* byłaby to char**, a nie tylko char* w sposób, w jaki ją zadeklarowałeś.

Kompilator bez wątpienia wydał ostrzeżenia na ten temat. Uważaj na te ostrzeżenia, bardzo często pomagają ci zrozumieć, co robić.

Oto jak można rozpocząć testowanie:

char **aPtr; 
int len = 1; // Start with 1 string 
aPtr = malloc(sizeof(char*) * len); // Do not cast malloc in C 
aPtr[0] = "This is a test"; 
printf("%s",aPtr[0]); // This should work now. 
+0

Aby zweryfikować (proszę o wyrozumiałość, jestem nowicjuszem =]), jeśli chciałbyś mieć dynamiczną tablicę wskaźników do zwrócenia uwagi (np. W razie potrzeby w aplikacji, gdzie może być konieczne przechowywanie ciągów znaków o zmiennej liczbie np. Od czytając plik tekstowy bez znajomości jego długości lub zbierając dane wejściowe użytkownika o nieokreślonej długości), potrzebna jest dynamiczna tablica Char *, więc potrzebujesz Char **. Znak char może wskazywać na różne znaki, które mogą być początkowym adresem różnych ciągów znaków. –

+0

po co jest "len = 1"? Wygląda na to, że 'To jest test' miałby 14 znaków, z których każdy jest bajtem ... ale ten kod nie wspomina o 14, ani też nie ulega awarii po uruchomieniu. – nmz787

+0

@ nmz787 Zwróć uwagę na typ 'aPtr', to podwójna wskazówka, więc reprezentuje tablicę wskaźników char. Wskaźnik char jest następnie ustawiony na element zero; w tym kodzie nie ma miejsca na kopiowanie ciągów. – dasblinkenlight

5
char * aPtr; 

jest jako wskaźnik do znaku, do którego przydzielona pamięć do przechowywania dokładnie 1 charakter.

Doing

aPrt[0] = "test"; 

adresowania pamięci dla tej jeden znaków i spróbuj zapisać adres dosłownym "test" do niego. To się nie uda, ponieważ ten adres jest bardziej szeroki niż znak.

Poprawkę do kodu oznaczałoby przydzielenie pamięci dla wskaźnika do znaku.

char ** aPtr = malloc(sizeof(char *)); 
aPtr[0] = "test"; 
printf("%s", aPtr[0]); 

są bardziej elegancki i bardziej nad solidnego podejścia byłoby przeznaczyć te same (jak również dodanie obowiązkowe sprawdzanie błędów), wykonując:

char ** aPtr = malloc(sizeof *aPtr); 
if (NULL == aPtr) 
{ 
    perror("malloc() failed"); 
    exit(EXIT_FAILURE); 
} 

... 
9
char *str; //single pointer 

Z tego można przechowywać jeden strunowy.


Aby zapisać array of strings jest potrzebne two dimensional character array

albo array of character pointers albo double pointer


char str[10][50]; //two dimensional character array 

Jeśli zadeklarujesz tak nie trzeba przydzielić pamięci jako ta jest statyczna deklaracja


char *str[10]; //array of pointers 

Tutaj trzeba przydzielić pamięci dla każdego wskaźnika

pętlę poprzez tablicę przydzielić pamięci dla każdego wskaźnika

for(i=0;i<10;i++) 
str[i]=malloc(SIZE); 

char **str; //double pointer 

Tutaj trzeba przydzielić pamięci dla Ilość wskaźniki, a następnie przydzielić pamięć dla każdego wskaźnika.

str=malloc(sizeof(char *)*10); 

I następnie pętli tablicy przydzielić pamięci dla każdego wskaźnika

for(i=0;i<10;i++) 
str[i]=malloc(SIZE); 
-1

robisz to całkowicie błędne. Poprawna wersja twojego kodu powinna wyglądać następująco:

int main() 
{ 
char *aPtr; 
aPtr =(char*)malloc(20*sizeof(char)); 
aPtr ="This is a test"; 
printf("%s",aPtr); 
} 

Możesz użyć tablicy wskaźnikowej. jeśli chcesz przechowywać wiele ciągów. Tak, wiem, że używanie pętli for będzie łatwe. Ale staram się wyjaśnić w prosty sposób, nawet początkujący mogą to zrozumieć.

int main() 
{ 
char *aPtr[10]; 
aPtr[0] =(char*)malloc(20*sizeof(char)); 
aPtr[0] ="This is a test"; 
aPtr[1] =(char*)malloc(20*sizeof(char)); 
aPtr[1] ="This is a test2"; 
printf("%s\n%s\n",aPtr[0],aPtr[1]); 
} 
+0

Twój pierwszy przykład przecieka pamięć, czyli 20 bajtów. Robiąc "aPtr =" To jest test ";" tracisz odwołanie do tego, co zwróciło 'malloc()'. Pamięć ta nigdy nie była używana i nigdy nie będzie używana w czasie trwania programu. – alk

+0

'sizeof (char)' to '1' to definicja. Przesyłanie wyniku 'malloc/calloc/realloc' nie jest konieczne w C ani zalecane: http://stackoverflow.com/a/605858/694576 – alk

+0

Dziękuję wszystkim, którzy odpowiedzieli, że była to świetna pomoc – user2826534