Forum: PC-Programmierung 2-dimension. Array dynamisch erzeugen


von Hans M. (fuxdancer)


Lesenswert?

Hallo!

Ich hätte ein Frage zur dynamischen Allokation der Arraygröße in C.

Und zwar will ich einen eingelesenen String durch Trennzeichen trennen 
und Wort für Wort in ein weiteres dynamisch erzeugtes 2-dimensionales 
Array  kopieren.

Das erste Array, mit dem ich einlese, das erzeuge ich mit malloc und 
einer bestimmten Blockgröße, reallokiere es danach und nun will ich, 
dass mein zweites Array genau soviel Zeilen hat, wie der eingelesene 
String Wörter und genau soviele Spalten pro Zeilen, wie ein Wort 
Buchstaben besitzt.

Nun bin ich soweit, dass ich genauso viele Spalten erzeugen kann, wie 
ein Wort Buchstaben besitzt.
Mein Problem ist aber, ich muss die Größe des 2-dim. Arrays 
(Zeilenanzahl) am Anfang schon in der Main definieren mit einer fixen 
Größe, ich schaffe es nicht, diese auch dynamisch zu erzeugen.
Könnte mir jemand einen Ansatz oder altes Programm senden, in welchem 
man ein 2-dim. Array dynamisch allokiert?

Bsp: That is bad.
                          Spalte
Zeile        0          1          2        3      4     5
0            T          h          a        t     \0
1            i          s          \0
2            b          a          d       \0
3            NULL

von ** (Gast)


Lesenswert?

Hm...
1
char ** array;
2
3
array=malloc(42*sizeof(char*));
4
5
for(uint8_t i=0;i<42;i++)
6
  array[i]=malloc(Größe des Strings)

+ Fehlerbehandlung usw

von ** (Gast)


Lesenswert?

** schrieb:
>   array[i]=malloc(Größe des Strings)
also x*sizeof(char)

von Karl H. (kbuchegg)


Lesenswert?

** schrieb:
> ** schrieb:
>>   array[i]=malloc(Größe des Strings)
> also x*sizeof(char)

(Mehr als Hinweis an den Fragesteller gedacht:)

Meistens (x+1)*szeof(char)
weil x meistens die Länge eines Strings ist, die mit strlen (oder einem 
Äquivalent dazu) bestimmt wird.

von ** (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> ** schrieb:
>> ** schrieb:
>>>   array[i]=malloc(Größe des Strings)
>> also x*sizeof(char)
>
> (Mehr als Hinweis an den Fragesteller gedacht:)
>
> Meistens (x+1)*szeof(char)
> weil x meistens die Länge eines Strings ist, die mit strlen (oder einem
> Äquivalent dazu) bestimmt wird.
Wo du Recht hast hast du Recht... :-)

von Hans M. (fuxdancer)


Lesenswert?

Was ich noch wissen will ist, habe ich beispielsweise so ein 
zweidimensionales Array
char **string1;

brauche ich hier nur ein malloc für die Größe der Spalten und der Zeilen 
machen oder wie?

sagen wir mal, dass mein vorher eingelesener String
"That is bad"
aus 3 Wörtern besteht
und Wort 1 (That) aus 4 Buchstaben.

Wie müsste ich das mit malloc und realloc realisieren?

von ** (Gast)


Lesenswert?

Nicht schön aber selten... Fehlerbehandlung fehlt!
1
#include <stdlib.h>
2
#include <stdio.h>
3
#include <string.h>
4
#include <stdint.h>
5
#include "memcheck.h"
6
7
int main(int argv, char *argc[])
8
{
9
  char **array;
10
  char string[]="This is very bad.";
11
  uint8_t i,j,k;
12
  uint8_t nbel=0;
13
14
  array=malloc(1*sizeof(char*));
15
16
  for(i=0;i<strlen(string);i++)
17
  {
18
    for(j=i;j<strlen(string)&&string[j]!=' ';j++);
19
    nbel++;
20
    array=realloc(array,nbel*sizeof(char*));
21
    array[nbel-1]=malloc((j-i+1)*sizeof(char));
22
    memcpy(array[nbel-1],string+i,j-i+1);
23
    array[nbel-1][j-i]='\0';
24
    _mc_check(NULL);
25
    i=j;
26
    j=0;
27
  }
28
  for(i=0;i<nbel;i++)
29
  {
30
    printf("%s\n",array[i]);
31
  }
32
  return 0;
33
}

Ich gebe zu ich musste debuggen, hatte das ='\0' vergessen...

von ** (Gast)


Lesenswert?

Ich bin definitiv nicht wach heute!

>_mc_check(NULL);
restlos streichen bitte (Debugfunktion).

von ** (Gast)


Lesenswert?

Jetzt rächt sich der Gastaccount. Noch ein Fehler:
memcpy(array[nbel-1],string+i,j-i);
                              ^^^^
SCHÄM

von Hans M. (fuxdancer)


Lesenswert?

Danke für die schnellen Antworten. Ich werd mal versuchen, dass ich eure 
Denkanstöße in einen anständigen Code umsetze.

Gruß Hans

von Karl H. (kbuchegg)


Lesenswert?

Hans M. schrieb:
> Was ich noch wissen will ist, habe ich beispielsweise so ein
> zweidimensionales Array
> char **string1;


Was du damit aufbaust ist streng genommen kein 2D-Array sondern etwas 
das wie ein 2D Array benutzt werden kann. Im Speicher sieht dein Aufbau 
zb so aus
1
   string1
2
   +-------+
3
   |   o   |
4
   +---|---+
5
       |
6
       v
7
   +-------+            +---+---+---+---+
8
   |   o--------------->|   |   |   |   |
9
   +-------+            +---+---+---+---+
10
   |   o----------+   +---+---+---+---+---+---+
11
   +-------+      +-->|   |   |   |   |   |   |
12
   |   o-------+      +---+---+---+---+---+---+
13
   +-------+   |
14
               |   +---+---+---+
15
               +-->|   |   |   |
16
                   +---+---+---+
string1 ist ein Zeiger auf ein 1D Array von Pointern (der Kasten links), 
wobei jeder Pointer wieder auf ein 1D Array von Charactern zeigt.

Da die beiden Arrays unterschiedlicher Natur sind, müssen sie auch 
getrennt allokiert werden.

Zuerst wird das 1D Pointer Array allokiert (mit einem malloc) ....
1
  string1
2
   +-------+
3
   |   o   |
4
   +---|---+
5
       |
6
       v
7
   +-------+
8
   |       |
9
   +-------+
10
   |       |
11
   +-------+
12
   |       |
13
   +-------+
und danach wird für jeden einzelnen Pointer ein malloc für das Character 
Array gemacht und der Pointer drauf eingerichtet

1. Pointer:
1
  string1
2
   +-------+
3
   |   o   |
4
   +---|---+
5
       |
6
       v
7
   +-------+            +---+---+---+---+
8
   |   o--------------->|   |   |   |   |
9
   +-------+            +---+---+---+---+
10
   |       |
11
   +-------+
12
   |       |
13
   +-------+

2. Pointer:
1
  string1
2
   +-------+
3
   |   o   |
4
   +---|---+
5
       |
6
       v
7
   +-------+            +---+---+---+---+
8
   |   o--------------->|   |   |   |   |
9
   +-------+            +---+---+---+---+
10
   |   o----------+   +---+---+---+---+---+---+
11
   +-------+      +-->|   |   |   |   |   |   |
12
   |       |          +---+---+---+---+---+---+
13
   +-------+

3. Pointer:
1
  string1
2
   +-------+
3
   |   o   |
4
   +---|---+
5
       |
6
       v
7
   +-------+            +---+---+---+---+
8
   |   o--------------->|   |   |   |   |
9
   +-------+            +---+---+---+---+
10
   |   o----------+   +---+---+---+---+---+---+
11
   +-------+      +-->|   |   |   |   |   |   |
12
   |   o-------+      +---+---+---+---+---+---+
13
   +-------+   |
14
               |   +---+---+---+
15
               +-->|   |   |   |
16
                   +---+---+---+

In diesem Beispiel sind also 4 mallocs beteiligt.

von Hans M. (fuxdancer)


Lesenswert?

Danke, habs geschafft.

von Daniel F. (df311)


Lesenswert?

Karl Heinz Buchegger schrieb:
> In diesem Beispiel sind also 4 mallocs beteiligt.

und nicht vergessen - allokierter speicher muss auch wieder freigegeben 
werden. 4 malloc -> 4 free

(o.k. wenn man es bei kleinen testprogrammen mal vergisst ist nicht soo 
schlimm, aber man sollte es sich gleich angewöhnen)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.