2009-05-01 14 views
2

als C-Neuling Ich bin ein wenig verwirrt über zweidimensionale Arrays."Richtung" von zweidimensionalen Arrays in C

Wenn ich will, um eine Matrix von 3 Reihen und 5 Spalten darzustellen, ich denke, die richtige Erklärung ist:

char a[3][5]; 

Also, das ist ein Array von 3 Zeigern auf 5-Arrays von Zeichen, oder was?

Wie kommt es, wenn ich versuche, es wie folgt zu durchlaufen, scheint es die falschen Ergebnisse zu lesen?

int x, y; 
for(x=0; x<3; x++){ 
    for(y=0; y<3; y++){ 
     printf("%c", a[x][y]); 
    } 
} 

Sind die folgenden äquivalenten und korrekten Möglichkeiten, es zu initialisieren?

char a[3][5] = { 
       {1,0,0,0,1}, 
       {1,0,0,0,1}, 
       {1,0,0,0,1}, 
       }; 

char a[3][5] = {1,0,0,0,1, 
       1,0,0,0,1, 
       1,0,0,0,1}; 

Vielen Dank für eine eventuelle bevorstehende Erklärung.


EDIT

Leider die Fehler, wird der Code nicht kopiert. Übrigens lasse ich sie weiterlesen, als ob sie vertikal gelesen würden, nicht in einer horizontalen.

Auch in dem Beispiel in diesem Tutorial http://www.cplusplus.com/doc/tutorial/arrays/ es liest das Array in einer Weise, die nicht streight-forward mir ist, wie es auf einem 5x3 zu funktionieren scheint, Höhe Breite, y x, cols Reihen Struktur statt a 3x5, Breite Höhe, x y. Reihen cols ein:

#define WIDTH 5 
#define HEIGHT 3 

int jimmy [HEIGHT][WIDTH]; 
int n,m; 

int main() 
{ 
    for (n=0;n<HEIGHT;n++) 
    for (m=0;m<WIDTH;m++) 
    { 
     jimmy[n][m]=(n+1)*(m+1); 
    } 
    return 0; 
} 
+0

Ihre verschachtelten Fors sollten y auf der inneren Schleife verwenden ... das könnte die falschen Ergebnisse erklären;] –

+0

Ihre for-Schleifen sind falsch. – DevinB

+0

Übrigens, beide Wege zur Initialisierung Ihres Arrays sind korrekt. Die zweite nutzt Klammer Elision - aber das ist natürlich erlaubt. Die erste verwendet ein nachkommendes Komma, aber es ist auch erlaubt. Persönlich mag ich eine Version mit Klammern und ohne Nachkomma am meisten - aber das ist nur mein Geschmack. –

Antwort

2

Sie falsche Ergebnisse haben, weil Sie x zweimal (sieht aus wie ein Copy/Paste-Fehler) verwenden. Versuchen

int x, y; 
for (x = 0; x < 3; x++) { 
    for (y = 0; y < 5; y++) { 
     printf("%c", a[x][y]); // Emil H says "%d" might be more useful 
    } 
} 

Edit: Ich bin nicht sicher, was ist mit diesem Tutorial verwirrend. Es entspricht genau Ihrem Code, außer dass das Array nicht gedruckt wird, sondern jedes Element auf (Zeile * Spalte) gesetzt wird (wobei Zeile und Spalte auf Eins basieren, also die + 1).

+0

Ich denke, er wird% d verwenden wollen, da es nicht sehr nützlich ist, null Bytes auszugeben. Ich tippte zuerst die falsche Reihenfolge ein. Das tut mir leid. :) –

+1

es ist verwirrend die Tatsache, dass im Allgemeinen width == x, height == y und er deklariert es gerne und liest es wie [Höhe] [Breite] (oder [y] [x]) das ist nicht wirklich, was ich a Zeilen * Spalten Struktur aber Spalten * Zeilen – pistacchio

+0

Danke, pistacchio. Ich habe gerade gesehen, dass HÖHE und BREITE waren und habe nicht gemerkt, welche welche Dimension war. –

0

Sie verwenden printf auf die falsche Weise. Versuchen Sie:

printf("%d", a[x][y]); 

Ich bin mir nicht sicher, ob Sie% c oder% d verwenden möchten. Wenn Sie die Nummer drucken möchten, verwenden Sie% d. Wenn Sie ein tatsächliches Zeichen drucken möchten, verwenden Sie% c.

1
int x, y; 
for(x=0; x<3; x++){ 
    for(x=0; x<3; x++){ 
     printf(a[x][y]); 
    } 
} 

Sie müssen die 2. for Schleife ändern, um auf 'y' anstelle von 'x' zu verweisen.

hoffe das hilft.

2

Ich sehe ein paar Probleme mit Ihrem Code. First (von oben kopiert):

int x, y; 
for(x=0; x<3; x++){ 
    for(x=0; x<3; x++){ 
     printf(a[x][y]); 
    } 
} 

In Ihrer inneren Schleife, es sieht aus wie Sie y statt x verwenden wollen, und Sie wollen y von 0..5 zu gehen. Momentan wiederholen Sie die Variable x. Außerdem haben Sie ein Problem mit Ihrer printf() - Anweisung.Hier einige korrigierte Code:

int x, y; 
for(x=0; x<3; x++){ 
    for(y=0; y<5; y++){ 
     printf("%d\n", a[x][y]); 
    } 
} 

Zweitens, wenn Sie Array initialisieren, Ihr Code ist fast korrekt. Hier ist die korrigierte Version:

char a[3][5] = { 
       {1,0,0,0,1}, 
       {1,0,0,0,1}, 
       {1,0,0,0,1} 
       }; 

(Ich entfernte die , nach der letzten „Reihe“ von Daten -, die ein Syntaxfehler war.)

Die zweite Syntax geschrieben Sie ist falsch (die mit nein Geschweifte Klammern).

1

Das Bild, das in dem Tutorial ist eine große Darstellung der Daten: alt text http://www.cplusplus.com/doc/tutorial/arrays/bidimensional_arrays3.gif

Aus dem Beispiel durchlaufen die verschachtelten for Schleifen über (links -> rechts) die Array-Reihe für Reihe und füllen eine Wert für jede Spalte.

+0

aber ich habe nicht die Beziehung zwischen dem Bild und diesem: int jimmy [HÖHE] [BREITE]; Es scheint mir, dass eine 3x5-Struktur deklariert und wie eine 5x3-Struktur zugegriffen wird. Kannst du das bitte erklären? – pistacchio

+0

Es kommt darauf an, wie Sie auf die Arrays zugreifen wollen. Wenn Sie das Diagramm zur Seite drehen, haben Sie das gleiche Array, aber jetzt ist es mehr wie 3x5. Wenn das für Sie sinnvoller ist, können Sie Ihr Array-Repräsentationsdiagramm auf diese Weise zeichnen, es ist immer noch das gleiche Array. – nivnad

0

char a [3] [5];

Also, ist dies ein Array von 3 Zeigern zu 5 Arrays von Zeichen oder was?

Ja, das ist es. Obwohl Sie es auch als aufeinanderfolgende Gruppe von 15 Zeichen manipulieren könnten.

Per Konvention würden die meisten Menschen es als eine Matrix mit 3 Zeilen und 5 Spalten (denke ich), aber es gibt nichts über die Datenstruktur selbst, die das erfordert. Sie könnten genauso gut 5 Zeilen und 3 Spalten darstellen. Oder 3 Sätze, die jeweils 5 Elemente enthalten, aber überhaupt keine sinnvolle Beziehung zueinander haben.

Eine bestimmte Bibliothek für Matrixmanipulation hätte eine Konvention dafür.

+0

Es gibt keine Zeiger. Es ist 15 Bytes Daten, in 3 Gruppen von 5 organisiert. – Robert

+0

Ich kann es auf einen Zeiger umwandeln und Zugriff auf die Daten mit diesem Zeiger, so konzeptionell denke ich, es ist sinnvoll, es einen Zeiger zu nennen. –

+0

In der Tat kann ich die Feldvariable als Zeiger auf einen Zeiger verwenden, ohne selbst Gießen: int main (int argc, char ** argv) { char a [3] [5] = { {0, 1,2,3,4}, {5,6,7,8,9}, {10,11,12,13,14}, }; printf ("% d \ n", ** a); } Also würde ich das einen Zeiger nennen. Es ist natürlich ein konstanter Zeiger. –

4

Nur für was es ist und was nicht.

char a[3][5]; 

Es sind keine Zeiger beteiligt. Ein mehrdimensionales Array wie dieses ist ein Array von Arrays von ... und so weiter. In Ihrem Fall haben Sie ein Array von 3 Arrays mit 5 Zeichen. Es wird klarer, wenn Sie es mit typedefs machen.

typedef char T[5]; 
T a[3]; 

Keine Zeiger sind überhaupt beteiligt. Wenn Sie die erste Reihe dieser drei Einsen zugreifen möchten, können Sie dies tun:

a[0]; 

Und es wird Sie ein Objekt vom Typ char[5] zurückgeben. Normalerweise bemerken Sie das nicht, weil Sie normalerweise alle Dimensionen indizieren. So ist das Array, das von a[0] zurückgegeben wird, durch den nächsten Index tiefgestellt, z. B. a[0][1]. Die [1] wird auf das Array angewendet, das von a[0] zurückgegeben wurde, das, wie wir früher herausgefunden haben, char[5] Typ hat.

Also, ist dies ein Array von 3 Zeigern zu 5 Arrays von Zeichen oder was?

Lassen Sie uns diesen Typ erstellen und sehen, wie es sich von den oben genannten unterscheidet.Erstellen es einfach ist, wenn Sie die grundlegenden Deklaratoren erhalten:

  • einen Zeiger erstellen: *D
  • ein Array erstellen: D[N]

D ist eine bestehende gerade einen anderen declarator. So, jetzt lass uns weitermachen. Zuerst sagst du array of 3 pointers to 5 arrays of chars.... Ich glaube du meinst array of 3 pointers to arrays of 5 chars. Zunächst wird array of 5 erstellt wie

D1[5] 

Jetzt wollen wir ersetzen D1 durch einen pointer to declarator:

(*D2)[5] 

Wir Klammern einfügen musste, weil der Index-Operator [N] besser bindet als der Dereferenzierungsoperator * und es würde sonst als *(D2[5]) gelesen werden, was nicht das ist, was wir wollen. Jetzt haben wir pointer to array of 5.

Jetzt machen wir die array of 3. Ersetzen D2 durch D3[3] ergibt dies:

(*D3[3])[5] 

Große, jetzt wir eine array of 3 pointer to array of 5 bekommen haben. Nur darum, den Basistyp, dass diese declarator appertains Ausbeuten die komplette Erklärung:

char (*D3[3])[5]; 

Das ist natürlich eine ganz andere Sache :) Sie es Zeiger auf Ihre anderen Array speichern verwenden könnte, die array of 3 arrays of 5 char vom Typ war. Speichern wir einen Zeiger auf das erste Sub-Array von a in D3[0]. Wir haben herausgefunden, dass a[0] den Typ char[5] hat. Wir können einen Zeiger auf dieses Array in D3[0] speichern, weil D3 ein Array von Zeigern zu char[5] ist, was für ein Zufall!

Ich hoffe, diese kleine Übung hat Ihnen einige der Beziehungen zwischen Zeigern und Arrays gezeigt. Prost!

1

Die kleinen Fehler wie die Verwendung von "% c", wenn Sie wahrscheinlich "% d" wollen und solche sind nicht das, was Sie wirklich beantwortet werden wollen ich demütig denke. Sie sagen, Sie sind etwas verwirrt über Arrays und erwähnen auch, dass Sie erwarten, dass Zeiger als Array-Elemente des Arrays mit Arrays zu sehen sind. Sie

Das letzte Komma in Ihrer Definition des Array-of-Arrays ist kein Syntaxfehler. Es ist ab C99 erlaubt.

Was wirklich klären wird, ist zu wissen, dass Arrays keine Zeiger sind. Es stimmt, dass ein Array-Name als Konstantenzeiger (für das erste Element) verwendet werden kann und dass Zeiger wie Arrays artikuliert werden können. Dies bedeutet jedoch nicht, dass Arrays und Zeiger gleich sind. Sie sind nicht.

Sie fragen, was das Symbol "a" in Ihrem Programm tatsächlich ist. Es ist ein Array von Arrays. Das Speicherlayout kann wie eine lange Linie dargestellt werden, die in drei Teile geschnitten ist, aber immer noch auf einer durchgehenden Linie. Dann schneiden Sie jeden von diesen in fünf Teile auf die gleiche Weise. Wenn Sie ein Element adressieren, müssen Sie zwei Indizes verwenden. zuerst für welches Fünf-Elemente-Array Sie wollen und dann für welches Fünftel dieses Element möchten Sie.

Das Speicherlayout ist nicht wie ein Raster aus Zeilen und Spalten. Der Speicher wird mit einem Skalar adressiert, also linear. Zeigerarithmetik kann das nächste Ding sein, in das Sie schauen konnten, und sehen, wie ein Inkrement auf einem Zeiger funktioniert.

Verwandte Themen