Forum: Mikrocontroller und Digitale Elektronik C: Mehrdimensionales Array - Problem beim Initialisieren


von Guido (Gast)


Lesenswert?

Hi Leute!

Ich stehe gerade vor dem Problem, dass ich mein Mehrdimensionales Array 
nicht gescheit initialisiert bekomme:
1
char array[10][6];
2
3
array[1] = "Hallo";
4
array[2] = "Welt ";
Ist bestimmt ganz einfach, aber ich bekomme es nicht hin. Sorry, habe 
schon verschiedenes versucht, wie
1
array[1][] = "Hallo";
aber der Compiler meckert beim ersten, das es sich nicht um einen 
modifizierbaren Wert handelt und beim zweiten, dass er einen Ausdruck 
erwartet.

Kann/will jemand helfen?

von J.-u. G. (juwe)


Lesenswert?


von Guido (Gast)


Lesenswert?

Hi & danke.

Das habe ich schon gesehen. OK, dumm formuliert - nicht initialisieren, 
sondern ein Element einzeln beschreiben.

von holger (Gast)


Lesenswert?

>Das habe ich schon gesehen. OK, dumm formuliert - nicht initialisieren,
>sondern ein Element einzeln beschreiben.

Das geht in C so nicht. Nimm strcpy().

von Guido (Gast)


Lesenswert?

Achso, das wusste ich nicht - danke für die Info!

von 123 (Gast)


Lesenswert?

Das Problem ist, dass ein String kein char[] ist, sondern eben ein 
Zeiger auf einen solchen. Klappen würde also
1
array[1]={'H', 'a', 'l', 'l', 'o'}

Oder halt eben strcpy

von sebi707 (Gast)


Lesenswert?

123 schrieb:
> Klappen würde also array[1]={'H', 'a', 'l', 'l', 'o'}

Nein das funktioniert leider auch nicht. Das Problem ist hier, dass man 
Arrays nur bei der Deklaration initialisieren kann und nicht mehr später 
per einfacher Zuweisung. Gehen würde eher sowas:
1
char array[10][6] = {"Hallo", "Welt "};

von 123 (Gast)


Lesenswert?

Hast recht. War wohl gerade was im Hirn verpolt...

von DirkB (Gast)


Lesenswert?

sebi707 schrieb:
> Das Problem ist hier, dass man
> Arrays nur bei der Deklaration initialisieren

Das ist dann die Definition.

von Guido (Gast)


Lesenswert?

Ich verzweifle hier noch mit meinen Arrays...

Folgendes:
1
char array[2][6];
2
3
void kopiere_was_ins_array( char * array )
4
{
5
  // tu dies und das mit dem array
6
}
7
8
void aufrufer( void )
9
{
10
  kopiere_was_ins_array( &array[0] );
11
}
Das funktioniert, aber wenn ich dann das nächste Element nehme
1
void aufrufer( void )
2
{
3
  kopiere_was_ins_array( &array[1] );
4
}
dann wird immer die falsche Adresse übergeben...woran liegts?

von Guido (Gast)


Lesenswert?

Ich revidiere...der Fehler muss vorher passieren. Das Array wird noch 
durchgereicht, da geht wohl der Aufbau des Arrays verloren...also wie 
besser machen?
1
char array[2][6];
2
3
void kopiere_was_ins_array( char * array )
4
{
5
  // tu dies und das mit dem array
6
}
7
8
void unterfunktion( char * array )
9
{
10
  // mache noch dies und das...
11
  kopiere_was_ins_array( &array[0] );
12
}
13
14
void main( void )
15
{
16
  unterfunktion( *array );
17
}
Da weiß die Funktion wohl nicht mehr, wo das eine Element anfängt und 
das andere aufhört.

von Guido (Gast)


Lesenswert?

Mal was anderes...bin ich jetzt total blöd, oder wird ein array nicht 
mit array[y][x] angeben? Also
1
array[2][6]
2
3
00 01 02 03 04 05
4
10 11 12 13 14 15
hier:
http://pronix.linuxdelta.de/C/standard_C/c_programmierung_14_2.shtml
ist es doch andersherum?!

von Max H. (hartl192)


Lesenswert?

Guido schrieb:
> dann wird immer die falsche Adresse übergeben...woran liegts?
array[0] ist schon der Pointer auf das ersten Elements der der ersten 
Zeile, Versuch mal einfach array[0] ohne '&' an die Funktion zu 
übergeben:
1
char array[2][6];
2
3
void kopiere_was_ins_array( char * array )
4
{
5
  // tu dies und das mit dem array
6
}
7
8
void aufrufer( void )
9
{
10
  kopiere_was_ins_array( array[0] );
11
}

: Bearbeitet durch User
von Guido (Gast)


Lesenswert?

Das geht auch nicht. Das muss irgendwie daran liegen das bei der ersten 
Übergabe die Dimension verloren geht. Aber wie schicke ich die mit?

von Yalu X. (yalu) (Moderator)


Lesenswert?

Guido schrieb:
> Das funktioniert, aber wenn ich dann das nächste Element nehme
>
> void aufrufer( void )
> {
>   kopiere_was_ins_array( &array[1] );
> }

&array[1] ist vom Typ char(*)[6], kopiere_was_ins_array erwartet aber
ein char*. Da sollte der Compiler mindestens eine Warnung ausgeben.

Der Argumenttyp ist char* und damit passend, wenn du das & weglässt:
1
  kopiere_was_ins_array( &array[1] );

> dann wird immer die falsche Adresse übergeben...woran liegts?

Welche Adresse erwartest du denn?

Mit &array[1] wird ein Zeiger auf das zweite Unter-Array, mit array[1]
ein Zeiger auf das erste Element des zweiten Unter-Arrays übergeben.
Beide haben zwar einen unterschiedlichen Typ, aber den gleichen
numerischen Wert.

Guido schrieb:
> Mal was anderes...bin ich jetzt total blöd, oder wird ein array nicht
> mit array[y][x] angeben? Also
>
> array[2][6]
>
> 00 01 02 03 04 05
> 10 11 12 13 14 15

Ja.

> hier:
> http://pronix.linuxdelta.de/C/standard_C/c_programmierung_14_2.shtml
> ist es doch andersherum?!

Die Initialisierung im Link ist fehlerhaft. Wie du richtig erkannt hast,
müssen dort die Zeilen und Spalten vertauscht werden.

von Guido (Gast)


Lesenswert?

Ok, danke schonmal, aber ich kriege es nicht hin. Wie müsste es denn 
jetzt lauten? Ich habe ein Array
1
char array[2][6];
Dann habe ich die Funktion die mir was ins Array schreiben soll. Hier 
muss die Adresse des ersten Elementes von array[0] oder [1] übergeben 
werden.
1
void schreibe_ins_array( char * array )
2
{
3
  array[0] = 'T';
4
  array[1] = 'E';
5
  array[2] = 'X';
6
  array[3] = 'T';
7
  array[4] = '0';
8
  array[5] = '1';
9
}
Dann gibt es eine Unterfunktion, welche das komplette Array bekommen 
soll, um damit zu arbeiten. Hier muss ja bekannt sein, wo die beiden 
ersten Elemente beginnen, also quasi der "Aufbau" des Arrays, damit es 
bei der Übergabe von array[0] oder array[1] das jeweilige erste Element 
übergibt, bzw. dessen Adresse.
1
void unterfunktion( char * array )
2
{
3
  schreibe_ins_array( array[0] );
4
}
Und dann ist da noch die main, aus der die Unterfunktion aufgerufen wird 
und das komplette Array an die Unterfunktion übergibt
1
void main( void )
2
{
3
  unterfunktion( array );
4
}
Wie ist hierfür jetzt die richtige Syntax? Woher weiß die Unterfunktion, 
wie das Array aufgebaut ist? Das Array ist ja statisch, liegt also im 
Speicher direkt hintereinander? Ich bräuchste doch quasi ein Zeiger auf 
Zeiger, oder nicht?

Ich blicks nicht, sorry.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Wenn die Größe des inneren Arrays (6) immer gleich ist, kannst du das so
schreiben:
1
#include <stdio.h>
2
3
char array[2][6];
4
5
void schreibe_ins_array(char *array) {
6
//void schreibe_ins_array(char array[]) {
7
  array[0] = 'T';
8
  array[1] = 'E';
9
  array[2] = 'X';
10
  array[3] = 'T';
11
  array[4] = '0';
12
  array[5] = '1';
13
}
14
15
void unterfunktion(char (*array)[6]) {
16
//void unterfunktion(char array[][6]) {
17
  schreibe_ins_array(array[0]);
18
  schreibe_ins_array(array[1]);
19
}
20
21
int main(void) {
22
  unterfunktion(array);
23
24
  for(int i=0; i<2; i++) {
25
    for(int j=0; j<6; j++)
26
      putchar(array[i][j]);
27
    putchar('\n');
28
  }
29
  return 0;
30
}

Die auskommentierten Zeilen enthalten jeweils eine alternative, aber
äquivalente Schreibweise der Funktionsköpfe.

Ausgabe:
1
TEXT01
2
TEXT01

Wenn an unterfunktion zweidimensionale Arrays unterschiedlicher Größe
übergeben werden sollen, kannst du das auch mit "variable-length arrays"
(VLAs) bewerkstelligen.

Edit:

Vielleicht hilft dir dieser Beitrag zu mehrdimensionalen Arrays und
Zeigern in C etwas weiter:

  Beitrag "Re: Ein Zeiger auf ein mehrdimensionales Feld"

: Bearbeitet durch Moderator
von Dr. Sommer (Gast)


Lesenswert?

Falls das Programm nicht gerade auf einem winzigen Mikrocontroller 
laufen soll, kannst du auch C++ und std::vector und std::string 
verwenden. C++ ist abwärtskompatibel wie C, aber seine Arrays & Strings 
verhalten sich so wie man es erwarten würde:
1
#include <vector>
2
#include <string>
3
#include <iostream>
4
5
void schreibe_string (std::string& str) {
6
  str = "Welt!";
7
}
8
9
int main () {
10
  std::vector<std::string> array (2);
11
  
12
  array[0] = "Hallo ";
13
  schreibe_string (array [1]);
14
  
15
  std::cout << array[0] << array [1] << std::endl;
16
}
"array" ist hier ein Array aus Strings. Diese kann man zuweisen (Zeilen 
5 und 11), Referenzen darauf erstellen (Zeile 13), und zugreifen & 
ausgeben (Zeile 15).

So ersparst du dir die Frickelage mit C-Arrays, kannst aber immer noch 
alles machen was C auch kann.

Nachteil: Es wird dynamischer Speicher benötigt, was aber nur auf 
kleinen Mikrocontrollern problematisch ist.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Wenn die einzelnen Elemente des Arrays konstante, nullterminierte
Strings sind, die immer nur als Ganzes ersetzt werden, kannst du statt
eines zweidimensionalen Arrays auch ein Array von Zeigern nehmen. Das
sieht dann so aus:
1
#include <stdio.h>
2
3
const char *array[2];
4
5
void schreibe_ins_array(const char **array) {
6
//void schreibe_ins_array(char *array[]) {
7
  *array = "TEXT01";
8
}
9
10
void unterfunktion(const char **array) {
11
//void unterfunktion(char *array[]) {
12
  schreibe_ins_array(&array[0]);
13
  schreibe_ins_array(&array[1]);
14
}
15
16
int main(void) {
17
  unterfunktion(array);
18
  for(int i=0; i<2; i++)
19
    printf("%s\n", array[i]);
20
  return 0;
21
}

Da nur Zeiger umkopiert werden, wird auch weniger Rechenzeit verbraucht,
und die Länge der einzelnen Strings ist beliebig, muss also nicht schon
bei der Deklaration des Arrays mit angegeben werden. Da die Strings aber
konstant sind, kannst du ihre Inhalte nicht ändern.
1
array[1][3] = 'x';  // Fehler

im Hauptprogramm, um das vierte Zeichen des zweiten Strings in ein 'x'
zu ändern, geht also nicht.

von J. (Gast)


Lesenswert?

Wozu brauchst du überhaupt das Array?  Vielleicht ist ja der ganze 
Ansatz verkehrt.

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.