Computerhilfen.de Logo
Forum
Tipps
News
Frage stellen

Übergabe von mehrdimensionalen Arrays in C/C++

Hallo!

Ich hoffe mir kann jemand helfen ???! Ich bin blutiger C/C++ Anfänger und versuche wohl gerade ein Anfänger Standard Problem zu lösen. Das erstellen eines Skat Programmes. Ich habe Probleme mit der Übergabe eines zweidimensionalen Arrays!
Es ist fast 4 Uhr morgens :-\. Die letzten beiden Tage habe ich durch programmiert, doch jetzt bin ich seid 5-6 Stunden vor dem gleichen Problem und ich komme einfach nicht mehr weiter! Ich habe eine wahrscheinlich viel zu komplizierte Funktion geschrieben, die ein zweidimensionales Array mit Werten füllt:

#include "header.h"

void blatt() //Sotiert in ein zwei dimensionales    
             //Array 32 Karten ein
{
char karten[32][3];
int i = 0, j = 0;

for(i=0;i<8;i++)
   {
   karten[  i ][ 0 ] = 4; //Symbol für Karo
   karten[i+8 ][ 0 ] = 3; //Symbol für Herz
   karten[i+16][ 0 ] = 6; //Symbol für Pik
   karten[i+24][ 0 ] = 5; //Symbol für Kreuz
   }
for (i=0;i<3;i++)
   {
   j = i + 55;//ASCII-Wert für 7,8 und 9
   karten[ i  ][1] = j;
   karten[i+8 ][1] = j;
   karten[i+16][1] = j;
   karten[i+24][1] = j;
   }
for (i=3;i<6;i++)
   {
   j = i + 47; //ASCII-Wert für 2,3 und 4
   karten[ i  ][1] = j;
   karten[i+8 ][1] = j;
   karten[i+16][1] = j;
   karten[i+24][1] = j;
   }
for (i=6;i<8;i++)
   {
   j = 49; //ASCII-Wert für 1
   karten[ i  ][1] = j;
   karten[i+8 ][1] = j;
   karten[i+16][1] = j;
   karten[i+24][1] = j;
   }
for (i=0;i<6;i++)
   {
   j=0; //Wert für alle Karten unter 10
   karten[ i  ][2] = j;
   karten[i+8 ][2] = j;
   karten[i+16][2] = j;
   karten[i+24][2] = j;
   }
for (i=6;i<8;i++)
   {
   j = i + 42; //ASCII-Wert für 11 und 12
   karten[ i  ][2] = j;
   karten[i+8 ][2] = j;
   karten[i+16][2] = j;
   karten[i+24][2] = j;
   }
for(i=0;i<32;i++)//Ausgabe des Arrays
   for (j=0;j<3;j++)
      cout << karten[j];

}
Soweit funktioniert diese seltsame Funktion, sie macht was ich von ihr will, nur wie kann ich mit den Werten weiter arbeiten? Alle meine Versuche das Array in Zeiger zu pressen sind völlig gescheitert. Ich weiß absolut nicht mehr weiter. Ich bedanke mich im voraus schon einmal für eure Hilfe!

Mit freundlichen Grüßen
Daniel

« Letzte Änderung: 22.05.04, 04:03:24 von Draglan »

Antworten zu Übergabe von mehrdimensionalen Arrays in C/C++:

Entweder machst du karten zu einer globalen Variable oder du machst dir das Karten-Array schon in main und übergibst es dann an die Funktion.
Der Funktionskopf muss dann so aussehen:
void blatt(char [][3])
und in main:
char KartenM[32][3];
blatt(KartenM);

Hat dir diese Antwort geholfen?

Danke ButtonHilfreiche Antwort Button

oder du benutzt eine etwas abstraktere technik ;D

eine funktion:

void foo(int **_ptr);

irgendwo im programm:

int **pparray = new int *[grösse_x];
pparray[ 0 ] = new int [grösse_x * grösse_y];

for(int i = 0; i < grösse_y;i++)
     pparray[ i ] = array[ 0 ] + i * ny;

foo(pparray);

du kannst nun einfach den zeiges zeiger 'pparray' wie ein normales 2d array benutzen (klasse ned? ;D) und die funktion 'foo' kann beliebig grosse 2d arrays aufnehmen
(hoffentlich isses verständlich ;D)

« Letzte Änderung: 22.05.04, 18:24:32 von void »

Unterstriche bei Bezeichnern sollten nicht vorangestellet werden,da diese für den Compiler reserviert sind.Ansonsten...erklär mal deinen Code. ::)

Hi,

wenn ich das richtig verstanden habe, dann ist Dein Problem eher prinzipieller Natur. Ich gehe davon aus das Du das Array "karten[32][3]" welches Du am Anfang der Funktion anlegst "irgendwie" zurückgeben willst um damit weiterzuarbeiten. Falls dies so ist, wirst Du bei Deiner Funktion IMMER scheitern. Das Problem liegt darin, dass lokale Variablen einer Funktion immer auf dem STACK angelegt werden. Wenn die Funktion nun beendet ist existiert auch der STACK nicht mehr und somit ist auch dein Array futsch. Damit das nicht passiert musst Du das Array auf dem HEAP anlegen und zwar ganz einfach mit dem Schlüsselwort new ( ist C++ in C mit malloc ). Also z.B. so:

char** karten    //ein Zeiger auf ein Feld von chars

karten = new char*[2]; //Speicher für 2 char-pointer
karten[0] = new char[32]; //Speicher für 32 chars
karten[1] = new char[3];  //Speicher für 3 chars

Den Speicher den Du so mit new besorgt hast musst Du aber irgendwann auch wieder freigeben, damit keine memory leaks entstehen, das geht in dieserm Fall so:

delete []  karten[0];  //lösche die 32 chars
delete []  karten[1];  //lösche die 3 chars
delete []  karten;     //lösche die beiden Zeiger

Wenn Du C statt C++ verwendest machst Du das mit free.

Achja, zurückgeben kannste das folgendermassen:

char** blatt()
{
   char** karten;

   // Speicher mit new besorgen ....
   .
   .
   .
   .

   return karten;  //Das Array zurückgeben
}


Nun brauchst Du nur noch in deinem Hauptprogramm einen Zeiger deklarieren und ihm den return Wert zuordnen:


char** pArray;

pArray = blatt();

Nun kannst Du auf das Array zugreifen.

Huch,

der Code ist ein wenig verunstaltet worden beim posten, aber ich hofe Du weisst was gemeint ist ;)

template<typename T>
T** dim2arr(int x,int y)
{
 T** ppArr = new T*[ x ];
 for(int i = 0;i < x;++i)
  ppArr = new T[y];
 return ppArr;
}

Aufruf:

blatt(dim2arr<char>(32,3));
Meinst du das 123?
Geht natürlich nur mit C++.

Hat dir diese Antwort geholfen?

Danke ButtonHilfreiche Antwort Button
Unterstriche bei Bezeichnern sollten nicht vorangestellet werden,da diese für den Compiler reserviert sind.Ansonsten...erklär mal deinen Code. ::)

der code is ned 100% von mir und hab mir bis jetzt nur wenig gedanken über ihn gemacht, aber er funktioniert einwandfrei. mit templates wäre das ganze noch etwas dynamischer ;D

ps: die unterstriche sind meine sache mecker ned an meinem programmierstil ;D

Hmm,eigentlich ist dein Code sogar völlig in Ordnung, ein Unterstrich ist ok solange die Variable nicht global ist und nach dem _ kein Großbuchstabe ist.
 ::)

@Windows.exe:

ok, nu hast Du das als template deklariert, aber was die Allozierung betrifft meine ich genau das.

Hat dir diese Antwort geholfen?

Danke ButtonHilfreiche Antwort Button

Hallo!

Ersteinmal Danke für die Antworten! Leider habe ich nicht alle so ganz verstanden :-[. Nun habe ich das ausprobiert was 123 meinte aber dabei bekomme ich leider eine für mich wilde Fehlermeldung:

------------------------------------------------------
Die Anweisung in "0x0041e522" verweist auf Speicher in 0x00000000. Der Vorgang "written" konnte nicht auf dem Speicher durchgeführt werden.
------------------------------------------------------

Mein jetziger Code:
......................................................
"header.h"

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include "string.h"
using namespace std;

extern void farbsymbole(char *karo_sym, char *herz_sym, char *pik_sym, char *kreuz_sym);
extern char** blatt();
......................................................
#include "header.h"

void farbsymbole(char *karo_sym, char *herz_sym, char *pik_sym, char *kreuz_sym)
{
*karo_sym  = 4; //Karosymbol &#9830;
*herz_sym  = 3; //Herzsymbol &#9829;
*pik_sym   = 6; //Piksymbol &#9824;
*kreuz_sym = 5; //Kreuzsymbol &#9827;
}
......................................................
#include "header.h"

char** blatt()
{
char karo_sym  = 0;
char herz_sym  = 0;
char pik_sym   = 0;
char kreuz_sym = 0;
int  i=0, j=0;
char** karten;    //ein Zeiger auf ein Feld von chars
karten    = new char*[2]; //Speicher für 2 char-pointer
karten[0] = new char[32]; //Speicher für 32 chars
karten[1] = new char[3];  //Speicher für 3 chars

/* In der Funktion(farbsymbole) sind die Symbolwerte festegelegt.  */
farbsymbole(&karo_sym, &herz_sym, &pik_sym, &kreuz_sym);

for(i=0;i<8;i++)
   {
   karten[  i ][ 0 ] = 4; //Symbol für Karo
   karten[i+8 ][ 0 ] = 3; //Symbol für Herz
   karten[i+16][ 0 ] = 6; //Symbol für Pik
   karten[i+24][ 0 ] = 5; //Symbol für Kreuz
   }
for (i=0;i<3;i++)
   {
   j = i + 55;//ASCII-Wert für 7,8 und 9
   karten[ i  ][1] = j;
   karten[i+8 ][1] = j;
   karten[i+16][1] = j;
   karten[i+24][1] = j;
   }
for (i=3;i<6;i++)
   {
   j = i + 47; //ASCII-Wert für 2,3 und 4
   karten[ i  ][1] = j;
   karten[i+8 ][1] = j;
   karten[i+16][1] = j;
   karten[i+24][1] = j;
   }
for (i=6;i<8;i++)
   {
   j = 49; //ASCII-Wert für 1
   karten[ i  ][1] = j;
   karten[i+8 ][1] = j;
   karten[i+16][1] = j;
   karten[i+24][1] = j;
   }
for (i=0;i<6;i++)
   {
   j=0; //Wert für alle Karten unter 10
   karten[ i  ][2] = j;
   karten[i+8 ][2] = j;
   karten[i+16][2] = j;
   karten[i+24][2] = j;
   }
for (i=6;i<8;i++)
   {
   j = i + 42; //ASCII-Wert für 11 und 12
   karten[ i  ][2] = j;
   karten[i+8 ][2] = j;
   karten[i+16][2] = j;
   karten[i+24][2] = j;
   }
return karten;
}
......................................................
#include "header.h"

void main()
{
char karten[32][3];
int i,j;
char** pArray;
pArray = blatt();
for(i=0;i<32;i++)//Ausgabe des Arrays
   for (j=0;j<3;j++)
      cout << karten[j];
delete []  karten[0];  //lösche die 32 chars
delete []  karten[1];  //lösche die 3 chars
delete []  karten;     //lösche die beiden Zeiger
}
......................................................

Es ist wohl noch immer mein Problem, dass ich die Zeigersyntax bei mehrdimensionalen Arrays nicht völlig verstehe. Der Versuch mit der abstrakten Technik von void ist bei mir auch mächtig in die Hose gegangen :o. Templates habe ich mir bisher noch nicht angelesen. Ich würde es gerne mit Zeigern machen da ich sonst Angst habe vielleicht Globale Variablen zu überschreiben.

Freundliche Grüsse
Daniel

Eigentlich sollten da viel viel mehr Fehlermeldungen kommen. ::)
Ich hab an deinem Code jetzt ein paar Sachen geändert und das ganze mit dem Template realisiert.
----------------------------------------
#include <iostream>
using namespace std;
template<typename T>
T** dim2arr(int x,int y)
{
T** ppArr = new T*[ x ];
for(int i = 0;i < x;++i)
  ppArr = new T[y];
return ppArr;
}
void farbsymbole(char *karo_sym, char *herz_sym, char *pik_sym, char *kreuz_sym)
{
*karo_sym  = 4; //Karosymbol &#9830;
*herz_sym  = 3; //Herzsymbol &#9829;
*pik_sym  = 6; //Piksymbol &#9824;
*kreuz_sym = 5; //Kreuzsymbol &#9827;
}

void blatt(char** karten)
{
char karo_sym  = 0;
char herz_sym  = 0;
char pik_sym  = 0;
char kreuz_sym = 0;
int  i=0, j=0;    //ein Zeiger auf ein Feld von chars
/* In der Funktion(farbsymbole) sind die Symbolwerte festegelegt.  */
farbsymbole(&karo_sym, &herz_sym, &pik_sym, &kreuz_sym);

for(i=0;i<8;i++)
  {
  karten[  i ][ 0 ] = 4; //Symbol für Karo
  karten[i+8 ][ 0 ] = 3; //Symbol für Herz
  karten[i+16][ 0 ] = 6; //Symbol für Pik
  karten[i+24][ 0 ] = 5; //Symbol für Kreuz
  }
for (i=0;i<3;i++)
  {
  j = i + 55;//ASCII-Wert für 7,8 und 9
  karten[ i  ][1] = j;
  karten[i+8 ][1] = j;
  karten[i+16][1] = j;
  karten[i+24][1] = j;
  }
for (i=3;i<6;i++)
  {
  j = i + 47; //ASCII-Wert für 2,3 und 4
  karten[ i  ][1] = j;
  karten[i+8 ][1] = j;
  karten[i+16][1] = j;
  karten[i+24][1] = j;
  }
for (i=6;i<8;i++)
  {
  j = 49; //ASCII-Wert für 1
  karten[ i  ][1] = j;
  karten[i+8 ][1] = j;
  karten[i+16][1] = j;
  karten[i+24][1] = j;
  }
for (i=0;i<6;i++)
  {
  j=0; //Wert für alle Karten unter 10
  karten[ i  ][2] = j;
  karten[i+8 ][2] = j;
  karten[i+16][2] = j;
  karten[i+24][2] = j;
  }
for (i=6;i<8;i++)
  {
  j = i + 42; //ASCII-Wert für 11 und 12
  karten[ i  ][2] = j;
  karten[i+8 ][2] = j;
  karten[i+16][2] = j;
  karten[i+24][2] = j;
  }
}

int main()
{
int i,j;
char** ppKarten = dim2arr<char>(32,3);
blatt(ppKarten);
for(i=0;i<32;i++)//Ausgabe des Arrays
  for (j=0;j<3;j++)
      cout << ppKarten[j];
Sleep(3000);
}
--------------------------------------
Was für einen Compiler benutzt du,der noch void main zulässt?

Moin nochmal,

kann auch noch nicht funktionieren so wie Du das im Moment hast, bist aber schon nahe dran ;)

Folgender Auszug aus Deinem Code:

...
for(i=0;i<8;i++)
{
  karten[  i ][ 0 ] = 4; //Symbol für Karo
  karten[i+8 ][ 0 ] = 3; //Symbol für Herz
  karten[i+16][ 0 ] = 6; //Symbol für Pik
  karten[i+24][ 0 ] = 5; //Symbol für Kreuz
}
...

Das schlägt schon fehl, weil es lauten muss:

for(i=0;i<8;i++)
{
  karten[ 0 ][  i ] = 4; //Symbol für Karo
  karten[ 0 ][i+8 ] = 3; //Symbol für Herz
  karten[ 0 ][i+16] = 6; //Symbol für Pik
  karten[ 0 ][i+24] = 5; //Symbol für Kreuz
}

da ja karten[ 0 ] Dein Array von 32 chars ist, also karten[ 0 ][ 0 ] bis karten[ 0 ][31]

entsprechend enthält karten[ 1 ] Dein Array von 3 chars, also
karten[ 1 ][ 0 ] bis karten[ 1 ][ 2 ].

Da Du oben die Indizes vertauscht hast greifst Du auf Speicher zu der Dir gar net gehört und somit gibt's die  Schutzverletzung.

Ich hoffe das ist Dir nun klar.


Hat dir diese Antwort geholfen?

Danke ButtonHilfreiche Antwort Button

Hi!

@123: Erstmal wieder Danke! Ja hatte es bisher noch nicht begriffen wo nun wie die neu erstellten Zeiger drauf zeigen, aber ich werde es gleich mal testen, ob es so funktioniert, obwohl ich mittlerweile eine etwas küzere Funktion gefunden habe de mir mein Array auch füllt und ich es übergeben kann. Auch wenn leider nicht mit Zeigern. Verstehen tue ich sie auch noch immer nicht ganz in Fall eines zweidimensionalen Arrays. Weiß vielleicht jemand dazu einen guten Link ::)?

@windows.exe: Mmmhh *duck* ich benutze Windows mit Visual Studio.net 2003. Eigentlich komme ich damit relativ gut klar und über void main() meckert er nicht. Soweit ich weiß würde es unter Linux nur mit int oder so gehen. Bei Windows kann ich aber glaube so ziemlich "alles" vors main schreiben wozu ich Lust habe? Naja void main() funst auf jedenfall.

Was die Template Variante angeht bin ich mir relativ sicher, dass sie klappen wird, nur was sind Templates überhaupt ??? ? Ich habe mir Templates noch nicht angeschaut, sollte ich wohl mal unbedingt tun.

@alle die es interessiert:

Meine jetzige Funktion habe ich mit Strukturen gelößt ud ist viel kürzer geworden:

......................................................
"header.h"

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include "string.h"
using namespace std;

extern void farbsymbole(char *karo_sym, char *herz_sym, char *pik_sym, char *kreuz_sym);
extern void farbenwert(int *karo, int *herz, int *pik, int *kreuz, int *grand, int *grand_ouvert);
extern struct karte* blatt();

struct karte
{
char farbe;
int wert;
};  
......................................................
#include "header.h"

struct karte* blatt()
{
char karo_sym  = 0;
char herz_sym  = 0;
char pik_sym   = 0;
char kreuz_sym = 0;
int  i=0, j=0;
struct karte* karten = new karte[32];
/* In der Funktion(farbsymbole) sind die Symbolwerte festegelegt.  */
farbsymbole(&karo_sym, &herz_sym, &pik_sym, &kreuz_sym);

for(i=0;i<8;i++)
   {
   karten.farbe    = karo_sym;  //Symbol für Karo
   karten[i+8 ].farbe = herz_sym;  //Symbol für Herz
   karten[i+16].farbe = pik_sym;   //Symbol für Pik
   karten[i+24].farbe = kreuz_sym; //Symbol für Kreuz
   }
for(j=0;j<4;j++)
   {
   for(i=0;i<5;i++)
      {
   karten[i+j*8].wert=7+i;
      }
   for(i=5;i<8;i++)
      {
      karten[i+j*8].wert=i-3;
      }
   }
for(i=0;i<32;i++)
   {
   cout << karten.farbe << karten.wert;
   }
return karten;
}
......................................................
#include "header.h"

void main()
{
blatt();
}
......................................................

Nun sollte ich eigentlich mit struct vor die Funktion schreiben, in der ich die Funktion blatt() benutzen will, das Array mit meinen Karten weiter benutzen können, oder?

Mit freundlichen Grüßen
Daniel

Unter C++ sollte man,plattformunabhängig,kein void main verwenden,weil es gegen den Standard verstößt und eigentlich sollte man es nicht kompilieren können.


« BB multiplikative chiffre / moduloBB Blitz Basic Frage zu einem Programm »
 

Schnelle Hilfe: Hier nach ähnlichen Fragen und passenden Tipps suchen!

Fremdwörter? Erklärungen im Lexikon!
Standardgateway
Das Standardgateway dient in einem Netzwerk ist das Gerät, das als Vermittler den Datenverkehr zwischen dem lokalen Netzwerk (wie einem Heim- oder Büronetzwerk)...

Compiler
Als Compiler bezeichnet man ein Programm zum Übersetzen der Quellprogramme einer bestimmten Programmiersprache in ausführbare Dateien, also in die Maschinenspra...

Quellcode
Ein Quellcode, auch als Quelltext bekannt, bezeichnet den unkompilierten Programm-Code einer Software. Quell- oder Programm-Code ist der auch für Menschen lesbare Co...