Matrix übergeben



  • Wie bekomme ich es hin das ich einen Zweidimesionalen Array einer Funktion übergeben kann? Ich habe nun drei Datein:

    funktionen.cpp

    #include "funktionen.h"
    
    #include <iostream>
    #include <conio.h>
    #include <windows.h>
    
    using namespace std;
    
    ausgabe_spielfeld(?){
        for(unsigned int y=0;y<10;y++){ //Gibt das Spielfeld aus 0-9
            if(y==0){
            }
            else{
                cout << "\n";
            }
                for(unsigned int x=0;x<10;x++){
                    cout << feld[y][x];
                }
        }
    }
    

    funktionen.h

    #ifndef FUNKTIONEN_H_INCLUDED
    #define FUNKTIONEN_H_INCLUDED
    
    ausgabe_spielfeld(?);
    
    #endif // FUNKTIONEN_H_INCLUDED
    

    main.cpp

    #include "funktionen.h"
    
    #include <iostream>
    #include <conio.h>
    #include <windows.h>
    
    using namespace std;
    
    int main(){
        char feld[10][10];
    
        ausgabe_spielfeld(?);
    }
    

    Wie schaffe ich es nun das ich das Feld in der Funktion Spielfeld genauso ansprechen kann wie in der main.cpp?


  • Mod

    Kommt auf die Details an, welche Größen man als Konstanten betrachten kann und welche nicht. Ist beispielsweise die innere Dimension konstant 10, dann kann man das Feld in Form eines Zeigers auf ein char[10] übergeben (also genau so, wie man ein normales Array übergeben würde, als ein Zeiger auf sien erstes Element). Wenn nicht, dann wird es komplizierter.

    Alle Probleme würden sich aber ganz automatisch auflösen, wenn du:
    -std::array benutzen würdest, anstatt mit rohen Arrays zu hantieren. (Alternativ kannst du dir auch selber das Array in ein struct wrappen, nichts anderes macht std::array. Man spart bloß die nötige Schreibarbeit.)
    -Objektorientiert programmieren würdest. So ein Spielfeld schreit doch geradezu nach einer eigenen Klasse.

    Die beiden Vorschläge sind natürlich auch kombinierbar für noch bessere Ergebnisse.



  • Mit einem Template geht es recht einfach, solange die Feldgröße zur Compile-Zeit bekannt ist:

    template<std::size_t N, std::size_t U>
    void func(char (&arr)[N][U])
    {
        // Do something
    }
    


  • SeppJ schrieb:

    Alle Probleme würden sich aber ganz automatisch auflösen, wenn du:
    -std::array benutzen würdest, anstatt mit rohen Arrays zu hantieren.
    -Objektorientiert programmieren würdest. So ein Spielfeld schreit doch geradezu nach einer eigenen Klasse.

    Was ist mit dem ersten Punkt genau gemeint 😕
    Und ja mit den Klassen wollte ich schon immermal Arbeiten habe es aber nicht richtig hinbekommen, es wäre nett wenn du mir ein wenig helfen könntest.
    Ich weiß wohl das man dort (in der Klasse) Variablen hat in (private) und die nur mit den Funktionen in dem (public) Bereich "benutzen" kann. Aber muss ich in der Klasse dann alle Funktionen auflisten? Und was ist der Sinn dahinter? (nur um die Variablen einen besseren "Schutz" zu bieten?)

    patrick246 schrieb:

    Mit einem Template geht es recht einfach, solange die Feldgröße zur Compile-Zeit bekannt ist:

    template<std::size_t N, std::size_t U>
    void func(char (&arr)[N][U])
    {
        // Do something
    }
    

    Danke, aber den Template würde ich aus der Maindatei doch auch auslagern oder nicht? Und da habe ich auch Probleme... . Ich habe auch noch nie richtig etwas mit Templates gemacht da ich keine richtige benutzung gefunden habe und falls dann hieß es immer "dafür sollte man den Template nicht benutzen sondern eine Funktion". 🙄
    Und ja die Feldgröße ist zur Compilerzeit bekannt.

    Ich finde es ja immer schwer wenn man mehrere verschiedene Antworten bekommt (oder Vorschläge) und man muss sich einen raussuchen. 😃



  • Vorschlag zur Güte:

    struct Spielfeld
    {
       char Feld[10][10];
    };
    
    void ausgabe_spielfeld( const SpielFeld& sf )
    {
       ...
    }
    
    int main()
    {
       SpielFeld Feld;
       ausgabe_spielfeld( Feld );
    }
    

    Sieht natürlich etwas doof aus, weil Spielfeld nur ein Member hat, aber vielleicht kommen da noch andere dazu, von denen du uns bisher nichts erzählt hast. Damit hättest du alle Spielfeld-relevanten Daten in einer struct zusammengefasst.
    Hat SeppJ allerdings schon vorgeschlagen.

    Edit:
    SpieldField nach SpielFeld umbenannt.



  • DocShoe schrieb:

    Vorschlag zur Güte:

    struct Spielfeld
    {
       char Feld[10][10];
    };
    
    void ausgabe_spielfeld( const SpielField& sf )
    {
       ...
    }
    
    int main()
    {
       SpielFeld Feld;
       ausgabe_spielfeld( Feld );
    }
    

    Danke für die Antwort. Aber ist das struct Element jedzt nicht Global? Und was ist das für ein Parameter bei der ausgabe_spielfeld (sf)?
    Und ich dachte SeppJ meinte mit einer Klasse z.B. das hier (aus dem Internet kopiert).

    class EineKlasse
    {
      public:                              // öffentlich
        EineKlasse();                      // der Default-Konstruktor
        EineKlasse(int a=0);               // weiterer Konstruktor mit Parameter und Defaultwert
        EineKlasse(const EineKlasse& a);   // Copy-Konstruktor
        ~EineKlasse();                     // der Destruktor
    
        int eineFunktion(int x=42);        // eine Funktion mit einem (Default-) Parameter
    
      private:                             // privat
        int m_eineVariable;
    };
    


  • Aber ist das struct Element jedzt nicht Global?

    Nein. Da ja das Spielfeld in der main initialisiert wird.

    Und was ist das für ein Parameter bei der ausgabe_spielfeld (sf)?

    Eine Referenz auf eine Variable des Typs Spielfeld.

    Und ich dachte SeppJ meinte mit einer Klasse z.B. das hier (aus dem Internet kopiert).

    Ein struct ist einer Klasse ähnlich. Hier ist aber alles öffentlich. (public)



  • Auch wenn ich mich jedzt für class oder struct entscheiden würde, müsste ich trodzdem doch noch einen Parameter angeben oder nicht? Und was würdet ihr mir den empfehlen? (bitte nur 1ne Sache 😃 )


  • Mod

    Fensterscheibe schrieb:

    Auch wenn ich mich jedzt für class oder struct entscheiden würde, müsste ich trodzdem doch noch einen Parameter angeben oder nicht? Und was würdet ihr mir den empfehlen? (bitte nur 1ne Sache 😃 )

    Eine gute, einfache Möglichkeit hat DocShoe doch schon gezeigt. Lies seinen Beitrag noch einmal vollständig.



  • Aber etwas irritierend (evtl. für einen Anfänger), da Feld zwei verschiedene Objekte bezeichnet.
    Besser daher

    struct Spielfeld
    {
       char Feld[10][10];
    };
    
    void ausgabe_spielfeld( const SpielField& sf )
    {
       // Zugriff jetzt mittels
       sf.Feld[y][x];
    }
    
    int main()
    {
       SpielFeld spielfeld;
       ausgabe_spielfeld( spielfeld );
    }
    


  • Also ich glaube ich stelle mich ein wenig blöd an. 😃
    Mein Ziel ist es erstmal eine Verbindung (die 3 Datein) zu schaffen.

    Meine main.cpp

    int main(){
       SpielFeld spielfeld;
       ausgabe_spielfeld(spielfeld);
    }
    

    Sieht so wie in dem Beispiel von DocShoe aus.

    Meine funktionen.h

    #ifndef FUNKTIONEN_H_INCLUDED
    #define FUNKTIONEN_H_INCLUDED
    
    struct Spielfeld{
        char feld[10][10]; 
    };
    
    void ausgabe_spielfeld(SpielField& sf );
    
    #endif // FUNKTIONEN_H_INCLUDED
    

    Ich würde auch gerne dem Array einen Wert für jede Zeile zuweisen, das geht aber nicht. Sollte ich in main an erster Stelle dort Wert reinstecken?

    Meine Funktionen.cpp

    void ausgabe_spielfeld(SpielField& sf){
        for(unsigned int y=0;y<10;y++){ //Gibt das Spielfeld aus 0-9
            if(y==0){
            }
            else{
                cout << "\n";
            }
                for(unsigned int x=0;x<10;x++){
                    cout << feld[y][x];
                }
        }
    }
    

    Ich glaube ich habe die Teile auch falsch eingesetzt...
    Und noch eine Frage:

    void ausgabe_spielfeld(SpielField& sf)
    

    wieso SpielField sf 😕
    Ich hoffe ihr helft mir nocheinmal.


  • Mod

    Mach aus "SpielField" "SpielFeld". Oder programmier auf Englisch, wie es die Mehrheit tut.



  • SeppJ schrieb:

    Mach aus "SpielField" "SpielFeld". Oder programmier auf Englisch, wie es die Mehrheit tut.

    So doof bin ich nun wieder auch nicht 😃 😃
    Es ist mir schon klar das, das das Spielfeld sein soll 😃
    Ich meine den Hintergrund warum da ein sf steht und ein SpielField.

    Und das Programm geht auch nicht. Ich habe es nun weiter probiert bekomme es aber nicht hin.



  • Fensterscheibe schrieb:

    Und das Programm geht auch nicht.

    Gewöhn dir das gleich wieder ab. Auf "Programm geht nicht" kriegst du nur Müllantworten wenn überhaupt. Minimalen Programmcode zeigen, schreiben was du erwartest, was stattdessen passiert (inklusive Fehlermeldung hier reinkopiert) und was du eigentlich machen willst.

    Fensterscheibe schrieb:

    Und noch eine Frage:

    void ausgabe_spielfeld(SpielField& sf)
    

    wieso SpielField sf 😕

    Wieso nicht? SpielField ist der Typ und sf der Name. DocShoe ist eben kein besserer Name eingefallen, mir fällt auch keiner ein.


  • Mod

    Wir wissen nicht, wie doof du bist 😃 . Über kurze Textnachrichten kann man nur sehr schwer Ironie übertragen. Wir können daher nur Fragen beantworten, die du stellst; und Probleme lösen, die du beschreibst. "Und das Programm geht auch nicht." ist beispielsweise keine Problembeschreibung.

    Jedenfalls sind in deinem Programm die Bezeichner kreuz und quer vermischt. Mal SpielFeld, mal SpielField. Mal sf, mal feld. Ob dir das klar ist oder ob du doch "so doof" bist, können wir nicht wissen, wir können dich bloß darauf aufmerksam machen, dass es ein Kuddelmuddel ist.



  • Vor allen Dingen ist das so trivial, dass es schwierig ist, dir zu helfen. Wenn du mit dem o.g. Dreizeiler Probleme hast ist es höchste Zeit, sich die entsprechenden Grundlagen anzueignen, bevor man weitermacht.
    Ich habe in meinem Quelltext einen Fehler, statt SpielField muss es SpielFeld heißen. In den 16 Zeilen kommt vier mal SpielFeld vor, und ein mal SpielField . Wir reden hier die ganzen Zeit von einem Spielfeld und dein Compiler nennt dir als Fehlermeldung (sinngemäß) Unbekannter Typ 'SpielField' . Dass man dir da noch Hilfestellung geben muss lässt vermuten, dass die einfachsten Grundlagen und Verständnis für´s Programmieren generell fehlen.
    Am besten schnappst du dir dein C++ Lehrbuch und arbeitest das Kapitel Klassen und Strukturen (oder ähnlich) inklusive aller Übungsaufgaben noch ein mal durch.

    Ergänzung:
    Wenn man wüsste, was char Feld[10][10] eigentlich ausdrücken soll könnte man es anders benennen, z.B. Position. Aber ohne Genaueres bleibt das wieder ein Ratespiel.



  • Meine eigendliche Frage war es wie ich einen Array (zweidimensional) einer Funktion übergeben kann. Dann habt ihr gesagt ich sollte besser class oder strcut benutzen. Da DocShoe das mit strcut gezeigt hatte, habe ich das auch genommen. Ich habe das nun in meinen Code eingebaut.

    main.cpp

    int main(){
       ausgabe spielfeld;
       ausgabe_spielfeld(spielfeld);
    }
    

    funktionen.cpp

    void ausgabe_spielfeld(ausgabe &feld){
    int x=5;
        for(unsigned int y=0;y<10;y++){ //Gibt das Spielfeld aus 0-9
            if(y==0){
            }
            else{
                cout << "\n";
            }
                for(unsigned int x=0;x<10;x++){
                    cout << feld[y][x]; // Hier
                }
        }
    }
    

    funktionen.h

    struct ausgabe{
        char feld[10][10];
    };
    
    void ausgabe_spielfeld(ausgabe &feld);
    

    Nun bekomme ich in der funktionen.cpp eine Fehlermeldung (makiert im code), unzwar : [b] no match for operator[] in feld[y]

    [quote=SeppJ]Mach aus "SpielField" "SpielFeld". Oder programmier auf Englisch, wie es die Mehrheit tut.[/quote] Gut ich bin wirklich so doof ich habe nicht auf die Namenunterschiede geachtet.



  • Deine Variable feld in der Funktion ist ja nun vom Typ ausgabe. Dementsprechend musst Du sie auch behandeln:

    cout << feld.feld[y][x]; // Hier
    


  • Danke es geht.
    Nun habe ich noch ein paar Fragen, damit ich das auch verstehe was ihr mir da jedzt geschrieben habt.

    1. In der main steht ja ausgabe_spielfeld(spielfeld); warum ist spielfeld in den klammern, obwohl die Variable im struct feld heißt? Angenommen ich habe im struct mehrere Variablen wie will man die den Unterscheiden?
    2. Warum cout << feld.feld[y][x]; und nicht cout << ausgabe.feld[y][x];

    Sonst ist alles soweit klar 😃



  • 1. Du hast vorher eine Variable namens spielfeld angelegt.
    Mit

    ausgabe spielfeld;
    

    hast Du gesagt, Du möchtest eine Variable namens spielfeld haben. Typ der Variablen ist der von Dir vorher definierte Typ ausgabe.
    Du kannst die in Deiner struct definierten Variablen ansprechen, wie ich es Dir in meinem letzten Posting gezeigt habe, zB.

    struct ausgabe
    {
       int eins;
       int zwei;
       char drei;
    };
    ...
    ausgabe variablenName;
    variablenName.eins = 1;
    variablenName.zwei = 2;
    variablenName.drei = 'c';
    ...
    

    2. In Deinem Funktionskopf definierst Du, welche Variablen Deine Funktion übergeben bekommen soll, und von welchem Typ sie sind.
    Ansprechen musst Du in der Funktion die konkrete Variable. In Deinem Fall ist ausgabe& der Typ (Referenz auf ausgabe) und feld der Name der Variablen.


Log in to reply