2-Dimensionales Feld auf anderes Feld zeigen lassen



  • Wade1234 schrieb:

    *(*(*(A + i) + j) + k) = 0;
    

    ist alles andere als übersichtlich.

    A[i][j][k] = 0;
    

    finde ich deutlich lesbarer.



  • Vielen Dank schon mal. Ich habe es jetzt mal so übernommen und das Programm läuft.
    Jedoch verstehe ich noch nicht so ganz die Bedeutung von diesen Ausdrücken, wie zum Beispiel

    ((*(A + i) + j) + k) = 0;



  • A[i] ist identisch mit *(A+i)

    demnach ist A[i][j] identisch mit *(A[i]+j) und nochmal ersetzt mit ((A+i)+j)

    die nächste Stufe ist für dich.

    Hinweis:
    Da für die Addition das Kommutativgesetz gilt, ist A+i = i+A
    Und für *(i+A) kannst du auch i[A] schreiben.



  • Ich habe das ganze also jetzt noch ein wenig angepasst und auch die anderen Aufgabenteile erfüllt.

    Und lass den Typecast (int**) weg.

    Das habe ich auch im Buch "C-für Dummies" so gelesen. Unser Professor besteht allerdings darauf, habe ihm extra deswegen auch eine Mail geschickt. Er ist der Meinung ich solle nicht so ein "Low-Budget" Buch nehmen und dann würde ich verstehen warum man den typecast braucht... 🙄

    Naja, so sieht jetzt jedenfalls das Ganze aus. Falls noch jemand nen Fehler findet bin ich dankbar für Verbesserungen 🙂

    #include <stdio.h>
    #include <stdlib.h>
    
    void drucken(int ***a,int n)
    {
    	int i,j,k;
    
    	for(i=0;i<n;i++)
    		for(j=0;j<n;j++)
    			for(k=0;k<n;k++)
    				printf("a[%d][%d][%d] = %d\n",i,j,k,a[i][j][k]);
    }
    
    void swap(int *x,int *y)
    {
    	int puffer;
    
    	puffer=*x;
    	*x=*y;
    	*y=puffer;
    }
    
    int main()
    {
    	//variable für matrix aus n zeilen zu n spalten zu n arrays
    	int ***A; 
    	int n,i,j,k;
    	int p=10,q=20;
    
    	//n einlesen
    	printf("n = ");
    	scanf("%d",&n);
    
    	//Speicher für die Zeilen anfordern 
    	A = (int***)malloc(n*sizeof(int**));
    
    	//Speicher für die Spalten anfordern 
    	for(i = 0; i < n; i++)  
         	A[i] = (int**)malloc(n*sizeof(int*)); 
    
    	//Speicher für die dynamisch angelegten arrays anfordern 
    	for(i = 0; i < n; i++) 
        	for(j = 0; j < n; j++)  
            	A[i][j] = (int*)malloc(n*sizeof(int)); 
    
    	//jedes element mit 0 initialisieren 
    	for(i = 0; i < n; i++) 
         	for(j = 0; j < n; j++) 
              	for(k = 0; k < n; k++) 
                	A[i][j][k] = 0;
    
    	//A an Funktion übergeben für Ausgabe
    	drucken(A,n);
    
    	//Funktion zum Tauschen von p und q
    	swap(&p,&q);
    	printf("\np = %d\nq = %d",p,q);
    
    	//Zeilen freigeben
    	for(i = 0; i < n; i++) 
        	for(j = 0; j < n; j++) 
         		free(A[i][j]);
    
        for(i = 0; i < n; i++)
         	free(A[i]);
    
    	//Feld freigeben
    	free(A); 
    
    	return 0;
    }
    


  • dennis98 schrieb:

    Vielen Dank schon mal. Ich habe es jetzt mal so übernommen und das Programm läuft.
    Jedoch verstehe ich noch nicht so ganz die Bedeutung von diesen Ausdrücken, wie zum Beispiel

    ((*(A + i) + j) + k) = 0;

    A + i: erhöhe die adresse von A um i * sizeof(A), faktisch i * 4 oder i * 8

    *(A + i): hole den wert an dieser adresse hervor (adresse des zeigers auf die i-te zeile)

    (A + i) + j: erhöhe die adresse um j * sizeof((A + i)), wieder j * 4 oder j * 8

    ((A + i) + j): hole wieder den wert an dieser adresse hervor (adresse des zeigers auf die j-te spalte in der i-ten zeile)

    (((A + i) + j) + k: erhöhe die adresse um k * sizeof(...), blabla k * 4 oder k * 8

    ((*(A + i) + j) + k): hole den wert an dieser adresse hervor, dies ist der wert des k-ten elements des arrays in der j-ten spalte der i-ten zeile.



  • dennis98 schrieb:

    Und lass den Typecast (int**) weg.

    Das habe ich auch im Buch "C-für Dummies" so gelesen. Unser Professor besteht allerdings darauf, habe ihm extra deswegen auch eine Mail geschickt. Er ist der Meinung ich solle nicht so ein "Low-Budget" Buch nehmen und dann würde ich verstehen warum man den typecast braucht... 🙄

    Echt jetzt? Sowas schreibt ein Professor?

    Bitte hier die erste Antwort lesen, die mit den 1800 Likes:
    https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc

    Wohlgemerkt, wir sind hier in C. In C++ müsste man den Cast machen, weil es sonst ein Fehler wäre. In C++ würde man aber malloc überhaupt nicht verwenden.



  • @Wade1234:
    Danke, das hat es etwas klarer gemacht 🙂

    @Printe

    Echt jetzt? Sowas schreibt ein Professor?

    Fand ich auch nicht ganz angebracht... Müll steht ja sicher auch nicht in diesem Buch drin. Er war da aber klipp und klar und besteht darauf, dass wir in der Klausur mit dem Typecast arbeiten. Da bleibt mir wohl nichts anderes übrig



  • dennis98 schrieb:

    Er war da aber klipp und klar und besteht darauf, dass wir in der Klausur mit dem Typecast arbeiten.

    Hat er irgendeine sachliche Begründung dafür gegeben? Würde mich interessieren.

    Da bleibt mir wohl nichts anderes übrig

    Nö. Macht das in der Prüfung so und vergesst es danach wieder.



  • Hat er irgendeine sachliche Begründung dafür gegeben? Würde mich interessieren.

    Nein, nur dass ich, wie schon gesagt, in einem "besseren" Buch nachschlagen soll und dann schon herausfinden würde aus welchem Grund das in C auch nötig ist.



  • So, jetzt wollte ich es wissen und hab mal gesucht: google "c malloc tutorial"

    Ich finde es erstaunlich, wie viele Online-Tutorials den Cast im Beispielcode verwenden. Erstaunlich auch, wie viele davon im erklärenden Text den Cast entweder überhaupt nicht erwähnen oder zwar erwähnen, aber nicht begründen.

    "Rühmliche" Ausnahme ist http://www.c-howto.de/tutorial/arrays-felder/speicherverwaltung, mit folgender Begründung:

    Es ist jedoch sauberer und erleichtert die Arbeit, wenn man den Code später in C++ Projekten verwenden möchte.

    Verschwiegen wird freilich, warum das Weglassen "unsauber" sein soll. Und ob man denselben Code mit C- und C++-Compilern übersetzen sollte, darüber kann man auch geteilter Meinung sein.

    Übrigens: Keins der gefundenen Tutorials castet den Pointer, der an free() übergeben wird, zurück auf void*. Warum nicht? Wäre das nicht "sauberer"?



  • dennis98 schrieb:

    Nein, nur dass ich, wie schon gesagt, in einem "besseren" Buch nachschlagen soll

    Welche Bücher empfiehlt er denn? Kannste die Liste hier mal posten?



  • dennis98 schrieb:

    Schreiben Sie sein C–Programm–Fragment (also kein vollst¨andiges Programm), welches zun¨achst einen
    positiven ganzzahligen Wert n einliest, danach voll dynamisch eine n × n–Matrix A von int–Zeigern
    allokiert ...

    warum nicht so?

    ...
        // Pointer-Matrix erzeugen
        int **matrix = malloc(n*n*sizeof(int*));  
        // Matrix füllen
        int x,y;
        for (x=0; x<n; x++)
            for (y=0; y<n; y++)
                matrix[x*y] = malloc (L);
        ...
    

    Also ohne hässliche Dreifachzeiger.


  • Mod

    Dynamische mehrdimensionale Felder sind übrigens DER Anwendungszweck für den VLAs (variable length arrays) perfekt sind. Also nicht in dem Sinne, dass man das ganze Dingen als VLA macht (das wäre genau der falsche Anwendungszweck), sondern dass man damit dynamisch den korrekten Zeigertypen für das malloc erzeugen kann. Somit hat man ganz korrekt ein zusammenhängendes Feld (viele Leute hier im Thread haben fälschlich etwas gezeigt, wo alles wild und ineffizient kreuz und quer verteilt ist) und hat trotzdem die bequeme Möglichkeit, die Adressierung der Indizes vom Compiler automatisch berechnen zu lassen, anstatt selber dafür eine Funktion schreiben zu müssen.

    Beispielhaft für ein 2D-Feld von ints:

    int N = 10, M = 20;  // keine Konstanten!
    int (*array)[M] = malloc(N*M*sizeof(int)); 
    array[4][7] = 3;  // Geht!
    

    Ich überlasse es dem geneigten Leser, dies auf die Aufgabenstellung zu übertragen, wo verlangt wird, dass es ein 2D-Feld von int* sein soll, die dann jeweils auf ein dynamisch erzeugtes 1D-Feld zeigen sollen. Wobei ich es komisch finde, dass man da kein 3D-Feld haben möchte. Absicht, um verschiedene Mechanismen zu üben, oder Unwissen, dass dies überhaupt möglich wäre?



  • Welche Bücher empfiehlt er denn?

    Dazu sagt er nichts genaues



  • Say no to triple* schrieb:

    warum nicht so?

    Weil das hier falsch ist:

    matrix[x*y] = malloc (L);
    

    Spiel die Doppelschleife mal durch und achte drauf, welche Werte x*y annimmt.



  • dennis98 schrieb:

    Welche Bücher empfiehlt er denn?

    Dazu sagt er nichts genaues

    Nicht mal ne Literaturliste zur Vorlesung? Das gehört sich aber eigentlich so ...



  • Printe schrieb:

    Say no to triple* schrieb:

    warum nicht so?

    Weil das hier falsch ist:

    matrix[x*y] = malloc (L);
    

    Spiel die Doppelschleife mal durch und achte drauf, welche Werte x*y annimmt.

    Richtig, war unachtsam. Muss [n*x+y] statt [x*y] sein.



  • don't like triple* schrieb:

    Richtig, war unachtsam. Muss [n*x+y] statt [x*y] sein.

    Genau. Aber das "Matrix-Feeling" geht bei deiner Anordnung verloren, du kannst nicht mit matrix[i][j] auf die Elemente zugreifen.


  • Mod

    Wozu man mehrfach malloc aufrufen muss, wenn doch in dem Speicher alles leben kann, wird sich mir wohl nie erschliessen.

    int** matrix = calloc(n*(sizeof(*matrix)+n*sizeof(**matrix))); // wir können auch gleich schön initialisieren
        for (int i=0; i!=n; i++)
            matrix[i] = (int*)(matrix+n)+i*n; // wo ist das decltype(*matrix) für C ?
    

Anmelden zum Antworten