• Aktualisierte Forenregeln

    Eine kleine Änderung hat es im Bereich Forenregeln unter Abschnitt 2 gegeben, wo wir nun explizit darauf verweisen, dass Forenkommentare in unserer Heftrubrik Leserbriefe landen können.

    Forenregeln


    Vielen Dank

[C] mehrdim. Arrayübergabe an Funktionen

T

the_sacrificer

Gast
[C] mehrdim. Arrayübergabe an Funktionen

Hallo zusammen,

ich hab ein essentielles Verständnisproblem was o.g. Problem betrifft. Wie übergebe ich Arrays korrekt? Stimmt der Prototyp überhaupt? Der Compiler meckert jedenfalls in Zeile 34, "Übergabe des Arguments 1(-3) von »mult« von inkompatiblem Zeigertyp".

Code:
#include <stdio.h>
#include <math.h>

/* Prototyp */
void mult(double **, double **, double **);


/* Funktion zur Matrizenmultiplikation */
void mult(double **a, double **b, double **c)
	{
	int i, j, k;
	
	for(i=0;i<3;i++)
		{
		for(j=0;j<3;j++)
			{
			for(k=0;k<3;k++)
				{
				c[i][j] += a[i][k] * b[k][j];
				}
			}
		}
	}

/* Hauptprogramm */
int main()
{
	/* 3 Matrizen */
	double a[3][3]={{1., 0., 0.},{.3, 1., 0.},{.6, 0., 1.},};
	double b[3][3]={{3., 6., 0.},{0., 5., 5.},{0., 0., -8.},};
	double c[3][3]={{0., 0., 0.},{0., 0., 0.},{0., 0., 0.},};
	
	/* Funktionsaufruf */
	mult(&a, &b, &c);
	
	
	/* Ausgabe */
	int i,j;
	for(i=0;i<3;i++)
		{
		for(j=0;j<3;j++)
			{
			printf("%lf\t", c[i][j]);
			}
		printf("\n");
		}

	return 0;

}

Wäre nett, wenn das jemand korrigieren könnte. Vllt komm ich dann auf den Hintergrund.

Gruß
the_sacrificer
 
AW: [C] mehrdim. Arrayübergabe an Funktionen

Du hast bei mult die Parameter falsch übergeben. Meiner Meinung nach ist double** a dasselbe wie double a[ ][ ]. Das heißt, du musst nicht &a, sondern nur a übergeben.
 
AW: [C] mehrdim. Arrayübergabe an Funktionen

mcShredder am 05.06.2009 13:35 schrieb:
Du hast bei mult die Parameter falsch übergeben. Meiner Meinung nach ist double** a dasselbe wie double a[ ][ ]. Das heißt, du musst nicht &a, sondern nur a übergeben.
Es kommt der selbe Fehler.
 
AW: [C] mehrdim. Arrayübergabe an Funktionen

mcShredder am 05.06.2009 13:35 schrieb:
Du hast bei mult die Parameter falsch übergeben. Meiner Meinung nach ist double** a dasselbe wie double a[ ][ ]. Das heißt, du musst nicht &a, sondern nur a übergeben.
Öhm **a ist ein Pointer vom Pointer, kein Pointer auf ein zwei-dimensionales Array, oder wie war das nochma. Hm, ein Pointer auf ein Pointer ist im Prinzip ja auch ein Pointer auf ein zweidimensionales Array....
Ich schau grad mal über den Code und versuch das zu verbessern...

Also was schonma nicht geht:
c[j] += a[k] * b[k][j];
c[j] ist ja ein Pointer auf ein Array. Du kannst (solltest) keine Pointer addieren oder gar multiplizieren (außer du weißt, was bei rauskommen soll). Du musst schon das jeweilige Element also c[j][k] zB zuweisen, aber das muss noch mit den Pointern klappen...

Ich glaub über den Index kannste net auf die Pointer zugreifen, musst glaub die Adresse aufzählen. Also c wäre *(c + i).
So etwa: http://www.java2s.com/Tutorial/C/0140__Array/Getthevaluesinatwodimensionalarraythrougharraypointer.htm

Allerdings muss ich jetzt wech, der Biergarten ruft ganz laut...
 
AW: [C] mehrdim. Arrayübergabe an Funktionen

Onlinestate am 05.06.2009 17:11 schrieb:
Also was schonma nicht geht:
c[j] += a[k] * b[k][j];
c[j] ist ja ein Pointer auf ein Array. Du kannst (solltest) keine Pointer addieren oder gar multiplizieren (außer du weißt, was bei rauskommen soll). Du musst schon das jeweilige Element also c[j][k] zB zuweisen, aber das muss noch mit den Pointern klappen...
Da hat das copy&paste einiges verschlungen, das hatte ich schon richtig.
Hab mein Problem gelöst, allerdings tun sich schon wieder neue auf. Die werd ich dann "später" mitteilen :B

Onlinestate am 05.06.2009 17:11 schrieb:
Allerdings muss ich jetzt wech, der Biergarten ruft ganz laut...
ich höre ihn auch schon ;)
 
AW: [C] mehrdim. Arrayübergabe an Funktionen

Sodele :B

der Compiler meckert nicht mehr, also wirds bei der Fehlersuche schwierig.

Grober Überblick:

* Matrizen liegen in einer .dat vor
2 2 <- Zeilen/Spalten
1. 2. <- Matrix
3. 4.
...

* read_matrix() liest aus .dat in Array

* Test auf multiplizierbarkeit

* print_matrix() mach Bildschirmausgabe und schreibt in eine beliebige .dat


Vorgaben:

* read_matrix() muss zuerst Dimensionen (int) und anschließend die entsprechende Anzahl an doubles einlesen - das Ganze zwei Mal für Matrix a und b


meine gedankliche Vorraussetzung, dass bestimmte Dinge funktionieren:

* nach dem Aufruf von read_matrix(fr, n, a); ist der stackinterne Zeiger noch am Ende der ersten Matrix wenn dann read_matrix(fr, m, b); aufgerufen wird?

* wenn ich den dim-Array m beim zweiten Mal übergebe, werden die Dimensionen auch in m und nicht in m abgespeichert (gleiches für Matrizen a und b)?


bekannte Fehler:

* Bei der Abfrage, ob die die Matrizen die Vorraussetzung für eine Multiplikation erfüllen wird verneint, obwohl zwei quadratische Matrizen gleicher dim vorliegen.

* kommentiere ich diese Abfrage aus geht es so weiter:
*** glibc detected *** ./test: free(): invalid pointer: 0x0804aa20 ***
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6[0xb7f2b604]
/lib/tls/i686/cmov/libc.so.6(cfree+0x96)[0xb7f2d5b6]
./test[0x8048687]
./test[0x8048a94]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe5)[0xb7ed2775]
./test[0x80484e1]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:07 467139 /home/the_sacrificer/test/test
...
damit kann ich nicht so viel anfangen (außer, dass es einen ungültigen Zeiger gibt)


Vermutungen:

* *fr wird nicht richtig übergeben?

* generell werden die Arrays falsch übergeben?


Ich weiß es ist viel und Fehler suchen dauert meist länger als das Programm neu schreiben, aber ich bin für jede Hilfe mehr als dankbar!


Code:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

#define MAX 10

int i, j, k;										/* Laufvariablen */
int n[2], m[2], o[2];								/* dim Matrizen */
FILE *fr;											/* Stack fileread */
FILE *fw;											/* Stack filewrite */
char fn[64];										/* filename I/O.dat */
double a[MAX][MAX], b[MAX][MAX], c[MAX][MAX]={.0};	/* leere Matrizen */


/* Matrizen einlesen */
void read_matrix (FILE *fr, int *n, double a[][MAX])
		{
		
		fscanf(fr, "%d%d", &n[0], &n[1]);			/* dim einlesen */
     	for (i=0; i<n[0]; i++)						/* Matrixkomponenten einlesen */
    		{
        	for (j=0; j<n[1]; j++)
        		{
           		fscanf(fr, "%lf", &a[n[0]][n[1]]);
           		}
           	}
           	
        }
	
			
/* Matrix ausgeben und speichern */
void print_matrix (int *n, double a[o[0]][o[1]])
	{
	
	free(fn);										/* alten Dateinamen entfernen */
	printf("Bitte Dateinamen fuer Ergebnisausgabe angeben:\n");
	scanf("%s", fn);
	fw = fopen(fn, "a");
	
	for(i=0; i<o[0]; i++)
		{
		for(j=0; j<o[1]; j++)
			{
			printf("%lf\t", a[i][j]);				/* Bildschirmausgabe */
			fprintf(fw, "%lf\t", a[i][j]);			/* in Ausgabedatei speichern */
			}
		printf("\n");
		}
	
	fclose(fw);
	
	}


/* Matrizenmultiplikation */
void mult_matrix (int *n, double a[][n[1]], double b[][n[1]], double c[][n[1]])
	{
	for(i=0; i<n[1]; i++)
		{
		for(j=0; j<n[1]; j++)
			{
			for(k=0; k<n[1]; k++)
				{
				c[i][j] += a[i][k] * b[k][j];
				}
			}
		}
	}


/* Hauptprogramm */
int main()
{
	
	printf("Bitte Namen der Eingabedatei angeben:\n");
	scanf("%s", fn);
	
	if(!(fr = fopen(fn, "r")))
		{
		printf("Datei nicht gefunden!\n");
		return 1;
		}
	else
		{
		read_matrix(fr, n, a);						/* Einlesen der Matrix in (n,a) */
		read_matrix(fr, m, b);						/* Einlesen der Matrix in (m,b) */
		
		fclose(fr);
			
		if(n[1]!=m[0])
			{
			printf("Spaltenanzahl von A muss mit Zeilenanzahl von B uebereinstimmen!\n");
			return 1;
			}
		else
			{
			
			o[0] = n[0];							/* dim Spalten a = dim Spalten c */
			o[1] = m[1];							/* dim Zeilen b = dim Zeilen c */
			
			mult_matrix(n, a, b, c);				/* AB = C */
			
			print_matrix(o, c);						/* Ausgabe und speichern */
			}
		}
			
	
	return 0;
}


Ich sehe grad, dass wieder vieles abgeschnitten wurde.
test.c
daten.dat
 
AW: [C] mehrdim. Arrayübergabe an Funktionen

Also erstma kannste in deiner daten.dat nicht 2/3 schreiben. Das kann der nicht parsen. Da musste dann 0.66666666 hinschreiben.
Das free in Zeile 40 ist auch sinnfrei, da du gar nichts dynamisch allokiert hast (das geschieht per malloc).
In Zeile 29 schreibste das immer an die selbe Stelle, meintest wohl eher fscanf(fr, "%lf", &a[#i][j]); (das # mal rausdenken)

Und um Fehler zu finden benutze doch den Debugger oder mach dir wenigstens Debug-Meldungen, dann hättest du auch schnell gemerkt, dass deine Matrizen überhaupt nicht eingelesen werden.
 
AW: [C] mehrdim. Arrayübergabe an Funktionen

Onlinestate am 06.06.2009 00:47 schrieb:
Also erstma kannste in deiner daten.dat nicht 2/3 schreiben. Das kann der nicht parsen. Da musste dann 0.66666666 hinschreiben.
2/3!=0.66666666 - aber vllt kann ich mit der Ungenauigkeit leben :)
Beim Multiplizieren hat es geklappt, aber beim Einlesen macht das sicher Probleme.

Das free in Zeile 40 ist auch sinnfrei, da du gar nichts dynamisch allokiert hast (das geschieht per malloc).
ich dachte, dass fn ja noch "belegt ist" mit daten.dat und wenn jetzt die Ausgabedatei zB erg.dat genannt wird würde letztendlich "erg.dat.dat" drinstehen - oder wird der Array erstmal komplett geleert, wenn man ihn neu beschreibt?

In Zeile 29 schreibste das immer an die selbe Stelle, meintest wohl eher fscanf(fr, "%lf", &a[#i][j]); (das # mal rausdenken)
das ist natürlich bitter

Und um Fehler zu finden benutze doch den Debugger oder mach dir wenigstens Debug-Meldungen, dann hättest du auch schnell gemerkt, dass deine Matrizen überhaupt nicht eingelesen werden.
empfehl mir bitte einen, ich bin neu in der Linuxgeschichte (Ubuntu Jaunty)
 
AW: [C] mehrdim. Arrayübergabe an Funktionen

Eclipse + CDT installieren, dürfte wohl der Standardeditor sein. Ist für C/C++ nicht ganz so schön wie Visual Studio, aber ebe sehr vielseitig und für Java gibts eh nichts besseres.

free() leert nicht den Inhalt von fn, sondern versucht der Speicher von fn freizugeben. Wenn du die Datei überschreibst, sollte der alte Inhalt auch verloren gehen. Zum anhängen müsstest du eher Funktionen wie strcat verwenden.

Gleitkommazahlen sind ja sowieso nie genau, aber sonst musst du das halt parsen und das Ergebnis temporär zwischenspeichern.

Paar Kleinigkeiten noch:
Mach deine Variablen so lokal wie möglich und so global wie möglich. Solche Sachen wie Laufvariablen immer in der jeweiligen Funktion unterbringen, selbst wenn du es in mehreren Funktionen brauchst.
 
AW: [C] mehrdim. Arrayübergabe an Funktionen

fein fein, jetzt läuft das gute Teil bis auf, dass die eigentliche Multiplikation nur die erste Zeile hinbekommt und danach nur noch Nullen schreibt. Hab die Dateien mal aktualisiert.

Ich musste erst an einer anderen Aufgabe verzweifeln, um zu merken dass die Matrizenübergabe an die Funktion mult_matrix() falsch läuft. Leider hab ich keinen Blassen, wie es richtig ablaufen soll. Hilfe :rolleyes:
 
AW: [C] mehrdim. Arrayübergabe an Funktionen

Das Problem liegt darin, dass ich die Arraydimensionen weder als Variablen noch Integerwerten (also n[0] bzw 3) in der Kopfzeile einer Funktion angeben darf ( void mult_matrix (int *n, double a[][n[1]], double b[][n[1]], double c[][n[1]]) ). Dafür werden defined-Werte ohne Meckern angenommen.

WARUM?
 
AW: [C] mehrdim. Arrayübergabe an Funktionen

the_sacrificer am 07.06.2009 20:40 schrieb:
Das Problem liegt darin, dass ich die Arraydimensionen weder als Variablen noch Integerwerten (also n[0] bzw 3) in der Kopfzeile einer Funktion angeben darf ( void mult_matrix (int *n, double a[][n[1]], double b[][n[1]], double c[][n[1]]) ). Dafür werden defined-Werte ohne Meckern angenommen.

WARUM?
Ich glaub das kann C nicht. Bei C müssen afaik die Dimensionen eines Arrays zur Compilezeit bekannt sein.
Könnte man vielleicht mit Pointern umgehen und die Adressen selbst weiterrechnen (mit sizeof(Typ) ). Spontan würde ich eher auf ne verkettete Liste zurückgreifen.
 
AW: [C] mehrdim. Arrayübergabe an Funktionen

Onlinestate am 07.06.2009 20:54 schrieb:
Ich glaub das kann C nicht. Bei C müssen afaik die Dimensionen eines Arrays zur Compilezeit bekannt sein.
blöd :) aber damit leb ich jetzt einfach mal.
naja, jetzt kommt die nächste Hürde: malloc ^^ Ich meld mich dann sobald es für mich unerklärliche Probleme gibt...
 
AW: [C] mehrdim. Arrayübergabe an Funktionen

the_sacrificer am 07.06.2009 21:12 schrieb:
blöd :) aber damit leb ich jetzt einfach mal.
naja, jetzt kommt die nächste Hürde: malloc ^^ Ich meld mich dann sobald es für mich unerklärliche Probleme gibt...
Du kannst auch relativ einfach dynamische Arrays machen, die du einfach über den Index ansprechen kannst. Solltest dir vielleicht die aktuelle Zahl speichern oder gleich nen Mini-Stack machen.
Einfach mit malloc initialisieren und kannst mit realloc den reservierten Speicher vergrößern oder verkleinern. Ist zwar nicht ganz performant das so oft zu verwenden, aber das ist ja jetzt nicht von Interesse :)
 
AW: [C] mehrdim. Arrayübergabe an Funktionen

Unser Prof hat heute erzählt, dass die echten Programmierer gar nicht mit Matrizen, sondern nur mit Vektoren arbeiten mit eben deiner genannten Indizierungssache. Ich werd mir mal die Sache genauer anschauen.
 
AW: [C] mehrdim. Arrayübergabe an Funktionen

the_sacrificer am 08.06.2009 19:53 schrieb:
Unser Prof hat heute erzählt, dass die echten Programmierer gar nicht mit Matrizen, sondern nur mit Vektoren arbeiten mit eben deiner genannten Indizierungssache. Ich werd mir mal die Sache genauer anschauen.
Ja, also Matrizen sind ja statische Arrays und ein Vektor ein dynamisches. Statisch ist für Laufvariablen oder Booleans, aber bei größeren Daten kannste das net bringen. Da kriegste nen Stack-Overflow, aber das schlimmste ist ja, dass die ganze Zeit so viel Speicher verbraucht wird, wie maximal hinein passt.
Ich bin jetzt im 4. Semester, da hab ich die schlimmsten Vorlesungen (Algorithmen & Datenstrukturen zB) hinter mir. Da haste noch ein paar interessante Themen vor dir (sofern du weiter programmierst und das jetzt nicht ein Nebenfach ist).
Kannst dir ja zB das Open-Book zum Thema verkette Listen anschaun. Hatte anfangs auch so meine Problemchen damit, aber irgendwann steigt man da auch ganz leicht durch. Mit Listen kann man sich schon nen kleines Verwaltungstool machen.
Fallste mal wieder Probleme hast, kannste mich gerne fragen. Mach das gerne, da gerade mein C da etwas eingerostet ist. Selbst wenn ich in der Firma bin, verbringe ich die geringste Zeit mit der Implementierung.

Ach, hier noch Beispiele zu dynamischen Arrays bzw zwei-dimensionales dynamisches Array.
 
AW: [C] mehrdim. Arrayübergabe an Funktionen

Onlinestate am 08.06.2009 21:00 schrieb:
Ich bin jetzt im 4. Semester, da hab ich die schlimmsten Vorlesungen (Algorithmen & Datenstrukturen zB) hinter mir. Da haste noch ein paar interessante Themen vor dir (sofern du weiter programmierst und das jetzt nicht ein Nebenfach ist).
Es ist ein Wahlnebenfach, sprich ich habs mir selber eingebrockt, will es aber wegen C auf jeden Fall machen. Ist auch eigentlich "nur" ne Numerik-VL, bei der C eben das Hilfsmittel der Wahl ist.

Kannst dir ja zB das Open-Book zum Thema verkette Listen anschaun.
Das hat mir ixquick auf der Suche nach Antworten auch schon ein paar mal empfohlen. Zufälligerweise war genau dieses Bildchen gestern an der Tafel ;)

Fallste mal wieder Probleme hast, kannste mich gerne fragen. Mach das gerne, da gerade mein C da etwas eingerostet ist.
Danke Dude! Das ist mal ein starkes Angebot auf das ich sicher zurückkommen werde =)
Ich kann dir dann evtl bei Thermodynamik, Strömungslehre und Mikrobiologie unter die Arme greifen :P
 
Matrix belegen und einfache Rechenoperationen

Hallo onlinestate, hallo begeisterte C-Coder,

folgendes:
Code:
int n=10;
double x[10] = {hier sind 10 Werte > 0 drin};
double y[10] = {hier sind 10 Werte > 0 drin};
// c ist ausreichend allokiert
/* ------------------------------ */
for(i=0, j=0; i<n; i++)
	{
		c[i][j] = 1.;
		c[i][j+1] = 1. / x[ i ] );
		c[i][j+2] = log(y [ i ] ) / x [ i ] ;
	}

bereitet mir Kopfzerbrechen.

Die erste Spalte wird ja noch korrekt beschrieben :B , aber bei der 2. stehen nur 0er und in der 3. 0er mit variierendem Vorzeichen drin.

Und wenn es eine elegantere Methode gibt, eine Matrix spaltenweise zu belegen, dann nur her damit. j kann2 oder 3.


Wie immer ewig dankbar
the_sacrificer
 
AW: Matrix belegen und einfache Rechenoperationen

the_sacrificer am 07.07.2009 09:43 schrieb:
Hallo onlinestate
Hi :-D
Hm, dass die i's in eckigen Klammern als kursiv-Tag verwendet werden macht das Lesen im ersten Moment etwas kompliziert ;)

Also, ich weiß jetzt nicht ob du das falsch rauskopiert hast, aber da war eine schließende Klammer zu viel, was zu einem Compilerfehler führt, also nicht dein eigentliches Problem sein kann.
Ich hab einfach versucht dein Problem zu reproduzieren und dabei diesen Code verwendet.
Ich habs nicht nachgerechnet, aber bei mir spuckt er folgendes Ergebnis raus:
1.000000 - 0.500000 - 1.098612
1.000000 - 0.333333 - 0.693147
1.000000 - 0.250000 - 0.486478
1.000000 - 0.200000 - 0.358352
1.000000 - 0.166667 - 0.268240
1.000000 - 0.142857 - 0.198042
1.000000 - 0.125000 - 0.137327
1.000000 - 0.111111 - 0.077016
1.000000 - 0.100000 - 0.000000

Könnte zumindest richtig sein.
 
AW: Matrix belegen und einfache Rechenoperationen

Onlinestate am 07.07.2009 17:12 schrieb:
Hm, dass die i's in eckigen Klammern als kursiv-Tag verwendet werden macht das Lesen im ersten Moment etwas kompliziert ;)
ah, daher kommt das :-D

Also, ich weiß jetzt nicht ob du das falsch rauskopiert hast, aber da war eine schließende Klammer zu viel, was zu einem Compilerfehler führt, also nicht dein eigentliches Problem sein kann.
Ich hab einfach versucht dein Problem zu reproduzieren und dabei diesen Code verwendet.
Ich habs nicht nachgerechnet, aber bei mir spuckt er folgendes Ergebnis raus:
1.000000 - 0.500000 - 1.098612
1.000000 - 0.333333 - 0.693147
1.000000 - 0.250000 - 0.486478
1.000000 - 0.200000 - 0.358352
1.000000 - 0.166667 - 0.268240
1.000000 - 0.142857 - 0.198042
1.000000 - 0.125000 - 0.137327
1.000000 - 0.111111 - 0.077016
1.000000 - 0.100000 - 0.000000

Könnte zumindest richtig sein.
Die Klammer ist es nicht, die ist da irgendwie mit reingerutscht. Bei dir fehlt die 1. Zeile, ist aber auch nicht schlimm.
Viel schlimmer ist, dass wenn ich den code auslagere, funktioniert es bei mir auch, nur halt nicht da wo ich ihn brauche...
 
Zurück