Gültigkeitsbereich



  • Einverstanden.. Vielleicht setze ich mich zu stark auf das vorangegangene C Buch. Ich möchte meine Beratungsresistenz ablegen und gelobe Besserung.

    Könnte mir jetzt einer mal sagen warum:

    void readtoarray(FILE *fp, unsigned int &n);
    
    int main(int argc, char **argv){
    	...
    	double ***C;
    	FILE *fp;
    
    	readtoarray(fp,&C,n);
    
    	cout << C[0][0] << C[0][1] << endl;
    
    	// free Coordinate Array **C
    	for(unsigned int i=0;i<n;i++) delete C[i];
    	delete [] C;
    	...
    }
    
    void readtoarray(FILE *fp,double ***C,unsigned int &n){
    
    	...
    	C = new double*[n];
    	for(unsigned int i=0;i<n;i++) C[i] = new double[2];
    	...
    }
    

    Irgendwie kriege ich es selber nicht gebacken und möchte eigentlich vorankommen anstatt mich stundenlang damit zu beschäftigen.



  • Dravere schrieb:

    C++ ist eine sehr komplexe und schwere Sprache. Man sollte sehr behutsam an diese Sprache herangehen. Zuviel auf einmal verwirrt den Anfänger nur oder führt dazu, dass er ein schreckliches C++ schreibt. Zum Beispiel übernimmt er dann das schreckliche C++ von wxWidgets, welches völlig veraltet ist.

    Grüssli

    Hoppla. Wäre dir dankbar wenn du mir das mal näher erläuterst. Ich bin gerade frisch in ein ebenfalls frisches C/C++ Projekt basierend wxWidgets hineingeworfen worden. Habe gerade mal grundlegende Erfahrungen in C sammeln können und kann dazu noch kein Urteil abgeben. Warum soll wxWidgets so schrecklich sein? Was nimmt man stattdessen lieber? Ich benötige OpenGL Beschleunigung.

    Eigenartigerweise sind beide Bücher von Wolf für C++ gar nicht so schlecht bewertet. Wie kommts? Hat es von euch Jemand schon in der Hand gehabt? Vielleicht ist ja die aktuelle Ausgabe doch gar nicht so schlecht?!?
    http://www.amazon.de/gp/product/3836214296


  • Administrator

    Zu deinem Problem:
    Wie SeppJ gesagt hat, solltest du nochmals das Thema zu Zeigern durchlesen. Auch ein Zeiger kann kopiert werden, da er auch nichts anderes darstellt, als ein paar Bytes im Speicher, welcher eine Adresse speichern. Auch wichtig dürfte dann für dich die Möglichkeit der Derefenzierung sein.

    Zu wxWidgets:
    wxWidgets wurde begonnen noch bevor der erste C++ Standard da war. Die Bibliothek ist also wirklich uralt. Die Entwickler wollen auch immer noch Kompiler unterstützten, welche vor 1998 existiert haben, wodurch sie nicht auf alle Möglichkeiten des C++ Standards setzen können. Sie setzen somit ein völlig veraltest C++ für ihre Bibliothek ein. Die Liste was an wxWidgets schrecklich ist, geht ins unendliche, daher liste ich die jetzt nicht auf 😉

    Gute GUI Alternativen gibt es leider nicht. Viele schwören auf Qt, was ich persönlich aber auch nicht so der Hit finde. Es setzt zumindest etwas moderneres C++ ein. Weder wxWidgets noch Qt bauen auf OpenGL auf. Ein gutes C++ Framework für OpenGL ist SFML. Allerdings hast du in SFML kein GUI.

    Zur Amazon Bewertung:
    Die wird von Laien gemacht ohne irgendwelche Ahnung. C++ von A bis Z täuscht dem Lernenden vor, dass er C++ könnte, weil man schnell mit wxWidgets grossartig aussehendes machen kann. Der Lernende merkt aber nicht, dass er so gar kein richtiges und schönes C++ lernt. Dadurch gibt er eine gute Bewertung ab bei Amazon, ist sich aber nicht bewusst, dass das Buch ihm nur geschadet hat.

    Grüssli


  • Mod

    darkfate schrieb:

    Irgendwie kriege ich es selber nicht gebacken und möchte eigentlich vorankommen anstatt mich stundenlang damit zu beschäftigen.

    Guck doch mal selber hin, der Compiler sagt doch schon, was nicht stimmt:

    error: cannot convert 'double**' to 'double***' in assignment
    

    Jetzt gucken wir mal in die Zeile:

    C = new double*[n];
    

    Gucken wir im Funktionskopf, so sehen wir, C ist vom Typ double***. Und new double*[n] liefert bekanntlich einen double**. Und jetzt beschwert sich der Compiler zurecht, dass dies nicht zusammenpasst, denn wie sollte man einem double*** einen double** zuweisen? Das geht einfach nicht.
    Wenn du jetzt meine Lösung nicht blind übernommen hättest, wüsstest du, warum ich dir im Funktionskopf aus dem double** einen double*** gemacht habe. Und dann wüsstest du auch, wie du deine Zuweisung abändern müsstest, damit es funktioniert wie es soll.
    Aber da dieses thema dermaßen elementar ist, dass du das verstehen musst, verweise ich dich nochmals auf dein Buch. Meinetwegen auch das C Buch, denn du machst hier (bis auf Kleinigkeiten) C kein C++. Guck dort mal die Begriffe call-by-reference und call-by-value nach, dann weißt du Bescheid.



  • Ich frage mich wozu es dieses Forum gibt wenn man es sich selber erarbeiten soll. Wenn ich hier nicht weiterkomme dann hat der Herr Wolf es anscheinend nicht gut genug rübergebracht.

    Wenn mir jemand zu Mathematik/Physik eine Frage stellt, dann versuche ich ihm auch zu antworten und verweise ihn nicht auf ein Kapitel aus dem Buch. Spart zwar Mühe, hat aber Null Lerneffekt.

    Man könnte zumindest mal Tips geben woran es scheitert. Einfach zu sagen überlege doch selber ist ein Unding.



  • SeppJ schrieb:

    ....

    Immerhin ein Anhaltspunkt. Danke.

    PS:
    Achso, was das Thema Elementar angeht. Da hat jeder seine eigenen Stärken. Ich kann auch nicht sagen Tensoren oder die Geometrische 5D Algebra gehören zu elementaren Dingen in der Mathematik, sie sind einfach und jeder sollte Sie können bevor er anfängt vernünftig zu rechnen. Ein bisschen Feingefühl wäre da nicht schlecht.


  • Administrator

    darkfate schrieb:

    Ich frage mich wozu es dieses Forum gibt wenn man es sich selber erarbeiten soll.

    Weil man es so lernt, sonst konsumiert man nur und lernt nichts. Wir haben hier ziemlich viel Erfahrung mit Anfängern. Wenn man ihnen die Lösung gibt, sind sie zufrieden gehen weg und kommen Tage darauf mit dem gleichen Problem wieder, weil sie die Lösung nicht verstanden haben.

    darkfate schrieb:

    Man könnte zumindest mal Tips geben woran es scheitert. Einfach zu sagen überlege doch selber ist ein Unding.

    Es wurden doch verschiedene Tipps gegeben. Viel mehr kann man fast nicht sagen, ausser dir die fertige Lösung zu präsentieren. Und Zeiger könnte man in der Mathematik mit dem Addieren und Subtrahieren vergleichen. Du wirst daher wohl begriefen, dass es wirkliche Grundlagen sind, denn ohne Addition kommst du in der Mathematik überhaupt nirgends hin.

    Falls du zusätzliche Literatur willst, dann findet sich zum Beispiel etwas hier (Kapitel 5):
    http://tutorial.schornboeck.net/inhalt.htm

    Grüssli



  • Dravere schrieb:

    Du wirst daher wohl begriefen, dass es wirkliche Grundlagen sind, denn ohne Addition kommst du in der Mathematik überhaupt nirgends hin.

    Na da siehst du mal, hier haben wir den ersten gravierenden Fehler 🙂 so einfach ist es.



  • Irgendwie komme ich von selber nicht drauf. Habe jetzt mal das ganze ein wenig abstrahiert.

    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    
    using namespace std;
    
    void array1d(int &n);
    void array2d(double *A1, int &n);
    
    int main(int argc, char **argv){
    
    	int n;
    	double *A1;
    
    	array1d(n);
    	array2d(A1,n);
    
    	cout << "n : " << n << endl;
    	cout << "A[0] : " << A1[0] << "A[1] : " << A1[1] << endl;
    
    	return EXIT_SUCCESS;
    }
    
    void array1d(int &n){
    	n = 2;
    }
    
    void array2d(double *A1, int &n){
    
    	A1 = new double[n];
    	A1[0] = 0.1234;
    	A1[1] = 0.5678;
    }
    

    In der Zeile 30 bekommt A1 immer eine neue Speicheradresse. So dass ich beim verlassen der Funktion nicht mehr darauf zugreifen kann. Es funktioniert wenn A1 = new double[n] vor der Funktion aufgerufen wird.

    Mit einem Zeiger auf Zeiger habe ich es selber nicht hingekriegt. Wäre nett wenn mal einer einfach die Antwort postet. Wenn die Zeit noch erlaubt, eine kurze Begründung warum das so ist.

    Danke im Voraus.



  • Hallo,

    Ich hab dein Programm so modifiziert, dass der Zeiger als Referenz übergeben wird:

    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    
    using namespace std;
    
    void array1d(int &n);
    void array2d(double *&A1, int &n);
    
    int main(int argc, char **argv){
    
        int n;
        double *A1;
    
        array1d(n);
        array2d(A1,n);
    
        cout << "n : " << n << endl;
        cout << "A[0] : " << A1[0] << "A[1] : " << A1[1] << endl;
    
        return EXIT_SUCCESS;
    }
    
    void array1d(int &n){
        n = 2;
    }
    
    void array2d(double *&A1, int &n){
    
        A1 = new double[n];
        A1[0] = 0.1234;
        A1[1] = 0.5678;
    }
    

    Beachte die Zeilen 8 und 28. Hier wurde die Funktion so verändert, dass nun der Zeiger selbst und nicht eine Kopie des Zeigers an die Funktion übergeben wird.
    Bei mir klappt es. Ich hoffe ich konnte dir weiterhelfen.

    MfG, Jochen



  • Hallo Jochen, danke für die schnelle Hilfe. Hat in jedem Fall weitergeholfen.

    Referenzen werden doch intern mit Zeigern realisiert, also müsste es doch eine Zeier auf Zeiger Lösung (**A1) Lösung geben. Vielleicht könnte hier mal jemand auch daszu was posten. Ich möchte wissen was ich hier so lange falsch gemacht habe.

    Nachtrag:
    Verstehe ich das jetzt richtig dass bei "&A1" die Adresse vom Zeiger genommen wird (nicht worauf er zeigt). Mit "*&A1" wird ein Zeiger auf die Adresse vom Zeiger an die Funktion weitergegeben? Bin ein wenig verwirrt.


  • Mod

    Ok, dies sieht wenigstens aus, wie C++.

    #include <iostream>
    
    using namespace std;
    
    void foo(int &n){
        n = 2;
    }
    
    int main(){
        int i = 0;
    
        foo(i);
    
        cout << "i : " << i << endl;
    }
    

    Guck dir mal dieses Programm an. Wenn man foo() aufruft, wird n auf 2 gesetzt und diese Änderung wird auch im Hauptprogramm bekannt. Die Variable i im Hauptprogramm hat hinterher auch den Wert 2. Du hast selber eine Funktion geschrieben, die genauso aussieht wie foo(), deshalb kannst du diese Fragen beantworten: Warum funktoniert das so? Und was bedeutet dieses &-Zeichen?

    Und jetzt ändere diese Funktion mal in:

    void foo(int n){
        n = 2;
    }
    

    Du wirst sehen, dass dies immer noch compiliert. Aber dieses Mal bleibt der Wert von i im Hauptprogramm gleich 0. Warum ist das so?

    Und wenn du diese Fragen beantwortet hast, dann guckst du dir nochmal deine Funktion an:

    void array2d(double *A1, int &n){
    
        A1 = new double[n];
        A1[0] = 0.1234;
        A1[1] = 0.5678;
    }
    

    Hier wird der Wert von A1 in der Funktion geändert, aber diese Änderung wird nicht weitergegeben. Warum ist das wohl so?


  • Mod

    darkfate schrieb:

    Hallo Jochen, danke für die schnelle Hilfe. Hat in jedem Fall weitergeholfen.

    Referenzen werden doch intern mit Zeigern realisiert, also müsste es doch eine Zeier auf Zeiger Lösung (**A1) Lösung geben. Vielleicht könnte hier mal jemand auch daszu was posten. Ich möchte wissen was ich hier so lange falsch gemacht habe.

    Ja, das geht intern (häufig) mit Zeigern. Und das ist auch der Ansatz den du zuerst versucht hast, den du aber nicht umsetzen konntest, weil du ihn nicht verstanden hast. Um das zu erklären, müsstest du verstehen, was Zeiger sind - dieses Wissen fehlt dir aber anscheinend (Was in C++ übrigens nicht so schlimm ist, da man Zeiger eher selten braucht). Ich kann aber an dieser Stelle Zeiger nicht erklären. Das Thema ist nicht zu unrecht in den meisten Lehrbüchern ein dickes Kapitel. Du musst dir so ein Lehrbuch schon erstmal durchlesen, bevor ich dir erklären kann, was man mit Zeigern wie machen kann.



  • Zum Thema Zeiger gibt es doch einen schönen Artikel im Magazin.
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-254043.html



  • SeppJ schrieb:

    ...

    Also noch einmal. Verstehen ist nicht mit der Syntax zurechtkommen.

    Nachtrag:
    Ich weiß deine Hilfe zu schätzen aber du frustrierst mich mit deinen Leseaufforderungen.

    Du verstehst die Welt auch nicht von Grund auf und trotzdem hältst du dich darin auf. Wenn du Fragen zur Welt hast dann wendest du dich an jemanden der sich auskennt und es dir erklären kann. Als Antwort bekommst du sicherlich nicht eine Seitenzahl genannt obwohl du mehrmals darauf hingewiesen hast dass du es bereits gelesen und nicht ganz verstanden hast.

    Wenn ich es so wie du tun wollte würde ich stur das Buch solange durchlesen bis ich es endlich verstanden habe und nicht ein Forum wie dieses anschreiben. Auf ein Buch zu verweisen, welches du selber nicht kennst ist keine Hilfe. Bücher die ich nicht habe aufzulisten ist genau so sinnvoll.

    Ich verstehe was ein Zeiger ist, ich weiß wie man damit rechnet und umgeht. Ich weiß wie man auf einfache Arrays Zeiger anwendet und wie man sie als Funktionsparameter übergibt. Auch kenne ich den Unterschied zwischen Call by Value und Call by Reference.

    Wie ich schon zehnmal geschrieben habe, beginnen meine Probleme beim "**" und das bei der Syntax. Da mein Buch es offensichtlich nicht klar genug hergibt stelle ich hier eine Frage und möchte kein Rätsel als Antwort. Wenn alle Lehrkräfte so unterrichten würden und jeder für sich selbst alles zerkauen und herleiten musste, wären wir in der Steinzeit.

    Nachtrag 2:
    Hätte man mir wie Jochen direkt genautwortet, wäre ich schon längst zufrieden und hätte den Grund für meinen Fehler erkannt. Stattdessen habt ihr eure Zeit mit Rätselbau und ich meine Zeit mit Rästelraten verloren.



  • darkfate schrieb:

    Wenn alle Lehrkräfte so unterrichten würden und jeder für sich selbst alles zerkauen und herleiten musste, wären wir in der Steinzeit.

    Und das andere Extrem sieht man inzwischen in vielen Schulabgängern: Die langsamsten halten alle auf. Nicht, das man nicht auf einzelne eingehen sollte, aber die Frage ist: wie lange?



  • asc schrieb:

    Und das andere Extrem sieht man inzwischen in vielen Schulabgängern: Die langsamsten halten alle auf. Nicht, das man nicht auf einzelne eingehen sollte, aber die Frage ist: wie lange?

    Wo bitte stellt es ein Extrem da wenn man eine Frage zu einem nicht verstandenen Thema hat?



  • Ein erstes Erfolgserlebnis. Kurz nach Jochens Anwort habe ich das ganze auch auf 2D Arrays usw.. anwenden können. Nicht einmal eine halbe Stunde musste ich opfern um es zu verstehen.

    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    
    using namespace std;
    
    void array1d(int &n);
    void array2d(double *&A1, int &n);
    void array3d(double **&A2, int &n);
    
    int main(int argc, char **argv){
    
    	int n;
    	double *A1;
    	double **A2;
    
    	array1d(n);
    	array2d(A1,n);
    	array3d(A2,n);
    
    	cout << "n : " << n << endl;
    	cout << "A[0] : " << A1[0] << "\tA[1] : " << A1[1] << endl;
    	cout << "A[0][0] : " << A2[0][0] << "\tA[0][1] : " << A2[0][1] << endl;
    	cout << "A[1][0] : " << A2[1][0] << "\tA[1][1] : " << A2[1][1] << endl;
    
    	for(int i=0;i<n;i++) delete A2[i];
    	delete [] A2;
    
    	return EXIT_SUCCESS;
    }
    
    void array1d(int &n){
    	n = 2;
    }
    
    void array2d(double *&A1, int &n){
    
    	A1 = new double[n];
    	A1[0] = 0.1234;
    	A1[1] = 0.5678;
    }
    
    void array3d(double **&A2, int &n){
    
    	A2 = new double*[n];
    	for(int i=0;i<n;i++) A2[i] = new double[2];
    	A2[0][0] = 1234;
    	A2[0][1] = 1234;
    	A2[1][0] = 1234;
    	A2[1][1] = 1234;
    }
    

    Funktioniert einwandfrei. Wenn sich jemand noch die Zeit nehmen könnte und zeigt wie die Syntax aussieht wenn man nur mit Derefferenzierungen arbeitet.
    Also nur "**" ohne das "&".

    Das frustrierende an dieser ganzen Sache ist, dass es mich an meine ersten Monate mit Linux erinnert. Da wird man auch immer gebeten irgend ein unsinniges Manual zu lesen welches für den Leien überhaupt nicht ersichtlich und nachvollziehbar ist.

    Immer muss man mind. 10 Leute fragen bis eine sinnvolle Antwort herauskommt.



  • @darkfate: Falls es dich interessiert, Hier ist noch eine Version deines Programms mit Zeigern auf Zeiger:

    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    
    using namespace std;
    
    void array1d(int &n);
    void array2d(double **A1, int &n);
    
    int main(int argc, char **argv){
    
        int n;
        double *A1;
    
        array1d(n);
        array2d(&A1,n);
    
        cout << "n : " << n << endl;
        cout << "A[0] : " << A1[0] << "A[1] : " << A1[1] << endl;
    
        return EXIT_SUCCESS;
    }
    
    void array1d(int &n){
        n = 2;
    }
    
    void array2d(double **A1, int &n){
    	double *tmp = new double[n];
    	*A1 = tmp;
    	tmp[0] = 0.1234;
        tmp[1] = 0.5678;
    }
    

    Ich hoffe, dass du es jetzt mit den Zeigern auf zeiger besser verstehst, ich kann aber gerne bei Bedarf noch bestimmte Dinge genauer erklären.

    Edit: Hab nicht gesehen, dass du schon wieder was neues gepostet hast, allerdings müsste mein Beispiel auch auf dein neues Programm übertragbar sein. Solltest du nicht klar kommen, kann ich das auch mal Einbauen.

    MfG, Jochen


Anmelden zum Antworten