Pointer Arraz an Funktion übergeben
-
Wutz schrieb:
Nirvash schrieb:
*x++ = cvmGet(StotmVals, i, j); *y++ = cvmGet(OctVals, i, j);
Erhöht jeweils den Wert worauf x und y Zeigen um eins, jedoch nicht die Adresse, was du vermutlich eher möchtest.
Möchtest du über ein Array mittels Pointer-Arithmetic indizieren so musst du wie folgt inkrementieren:
*(i++) = x;
Und da sind sie wieder, die C++ler, die Unsinn über Zeiger verbreiten, weil sie es einfach nicht verstanden haben. Du zeigst hier den größten anzunehmenden Unfall, den man hierbei machen kann.
Warum bleibt ihr eigentlich nicht bei eurem vector? Da könnt ihr brav hoch- und runteriterieren und auch nicht allzu viel falsch machen.
Warum benutzt ihr eigentlich Zeiger?
Von Zeigern habt ihr jedenfalls keine Ahnung, also Finger weg, wenn sich C-Programmierer darüber unterhalten bzw. haltet euch einfach mit eurem zusammengegoogelten Halbwissen zurück, wenn es im C-Subforum um Zeiger geht.*x++ = cvmGet(StotmVals, i, j);
weist den cvmGet-Rückgabewert der Speicherstelle zu, auf die x zu Beginn zeigte und liefert als Wert des Gesamtausdruckes eben diesen zurück; zusätzlich wurde x um sizeof(float) Bytes erhöht, zeigt also nach dem Statement auf die float-Speicherstelle direkt nach x zu Beginn.
*(i++) = x;
Ist auch wieder falsch, da *(i++) äquivalent zu *i++ ist, da hat unser C++ Freund also auch wieder falsch geraten und bringt auch keinen Mehrwert zu o.g.
Ich kann kein C++ und habe das auch ne behauptet.
Mit der Inkrementation von Pointern habe ich etwas durcheinander gebracht. Bitte entschuldige.
-
Nimm den Debugger oder baue ein paar printf zur Kontrolle ein (die können später wieder raus)
Dir sollte klar sein, dass du ja x und y (die Zeiger) veränderst. Dadurch zeigen sie am Ende deiner Doppel-Schleife nicht mehr auf den Anfang des Speicherbereichs.
Du musst sie dir vorher merken oder die Arrayschreibweise nehmen.Nutze den Rückgabewert der Funktion. Woher soll die rufende Funktion wissen, ob die Werte gültig sind oder du gerade durch Null teilen wolltest?
Für 8000000 Werte lasse ich
float
gelten, aber für b und a (bzw a1 und a0) und die anderen lokalenfloat-
Variablen sollte schondouble
drin sein.
-
so habe inzwischen den ersten part der werteübergabe hinbekommen aber die übergabe an die funktion linreg funzt nicht wirklich da halt null übergeben wird, obwohl jetzt im speicherbereich die werte stehen.
void TImageCompFrame::CompareProfiles() { char buffer[30]; DWORD retval; int n = OctVals->rows*OctVals->cols;//, step; double m = 0.0, b = 0.0; double *x = (double*)malloc(8000000*sizeof(double)); double *y = (double*)malloc(8000000*sizeof(double)); for(int i = 0;i<OctVals->rows;i++){ for(int j = 0;j<OctVals->cols;j++){ //if((cvmGet(OctVals, i, j)==0) || (cvmGet(StotmVals, i, j) == 0))continue; //sprintf(buffer, "%9.3f\t%9.3f\n", cvmGet(StotmVals, i, j), cvmGet(OctVals, i, j)); x[i] = cvmGet(StotmVals, i, j); y[i] = cvmGet(OctVals, i, j); //buffer[5] = buffer[15]= ','; //WriteFile(hDataFile, buffer, strlen(buffer), &retval, NULL); } } LinReg(n, x, y, &b, &m); sprintf(buffer, "%f\n", b); MessageBox(buffer, "", MB_OK); //CloseHandle(hDataFile); }
void LinReg(int n, double *x, double *y, double *a0, double *a1){ // n = anzahl Werte // *x, *y = Korrespondierende Werte X und Y // Geradengleichung: Y = a1x + a0 ---> mx +b // Funktionsaufruf LinReg(n, &x[0], &y[0]); // Rueckgabeparameter a0, a1 double x1=0,x12=0,y1=0,x1y1=0,e, xn, yn; for(int i=0;i<n;i++){ xn = x[i]; // Bei Übergabe schief gegangen da wahrscheinlich null yn = y[i]; x1+=xn; y1+=yn; x1y1+=xn*yn; x12+=xn*xn; } if((x12 == 0) || (x1 == 0)) return; // großes Problem da division durch null *a1=((n*x1y1)-(x1*y1))/((n*x12)-(x1*x1)); *a0=y1/n-(*a1)*x1/n; e=*y-(*a0)-(*a1)*(*x); *a0+=e; }
-
Ich schreib mal eine kürzere Schreibweise für deine aktuelle Schleifen aus TImageCompFrame::CompareProfiles auf:
for(int i = 0;i<OctVals->rows;i++){ x[i] = cvmGet(StotmVals, i, OctVals->cols-1); y[i] = cvmGet(OctVals, i, OctVals->cols-1); }
Bist du dir sicher das du das so möchtest?
Das macht nicht das gleiche, was in deinem ersten Post stand-
-
naja das ganze ist ne matrix mit werten von opencv. Ich will die werte der reihe nach auslesen daher auch 2 schleifen.
-
Xeno1987 schrieb:
naja das ganze ist ne matrix mit werten von opencv. Ich will die werte der reihe nach auslesen daher auch 2 schleifen.
Deine zweite (innere) Schleife ist aber für die Katz, da du in dieser immer wieder den Wert von x[i] überschreibst.
Daher bleibt nur die eine Schleife übrig, wie ich es gerade gepostet habe.
-
ok danke aber warum werden bei der Übergabe keine werte übertragen.
Ich habe es bis jetzt nicht rausgefunden. Die Werte sollten doch im Speicherbereich den ich reserviert habe solange da bleiben bis ich den Speicher wieder freigebe oder nicht?
-
Das sollte schon passen.
Aber wenn du nur einen Teil des Speicherbereich füllst, dann enthält der Rest halt undefinierte Werte. Die können auch 0 sein.Du schreibst auch "wahrscheinlich null". Also weißt du es noch nicht einmal.
Probier die Funktion doch mal mit nur 4 Wertepaaren aus.
Oder berechne die Werte vorher aus einer (linearen-)Funktion.Und wäre es nicht sinnvoller Speicher für n Werte zu holen, anstatt für 8000000 ?
-
Also ich find deine sehr gut nur habe ich das schon probiert und es klappt wenn ich die Werte im Speicher noch in der selben Funktion verwende ansonsten steht da nichts.
-
Was bedeutet: "... steht da nichts."
Und wie stellst du das fest?Im übrigen ist die Begründung dafür falsch:
if((x12 == 0) || (x1 == 0)) return; // großes Problem da division durch null
Überleg mal wann der Term
((n*x12)-(x1*x1))
Null ergibt.
-
also ich lass immer die werte in eine textdatei reinschreiben und dabei habe ich dann festgestellt dass gar keine werte drin standen, also bekommt die funktion linreg überhaupt nichts übergeben.
-
Das kann auch an der Schreibfunktion liegen.
Es sollte zumindest irgend etwas in der Datei stehen.Zeig Code, sonst kann dir hier keiner helfen.
-
void LinReg(int n, double *x, double *y, double *a0, double *a1){ char buffer[30]; DWORD retval; double x1=0,x12=0,y1=0,x1y1=0,e, xn, yn; HANDLE hDataFile = CreateFile("test.txt", GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); for(int i=0;i<n;i++){ xn = x[i]; // Bei Übergabe schief gegangen da wahrscheinlich null yn = y[i]; sprintf(buffer, "%f\n", x[i]); WriteFile(hDataFile, buffer, strlen(buffer), &retval, NULL); //x1+=xn; //y1+=yn; // x1y1+=xn*yn; // x12+=xn*xn; } CloseHandle(hDataFile); /* *a1=((n*x1y1)-(x1*y1))/((n*x12)-(x1*x1)); *a0=y1/n-(*a1)*x1/n; e=*y-(*a0)-(*a1)*(*x); *a0+=e; */ }
Der Hauptfunktion ist wie auf seite 2 geblieben bis auf die von dir genannten schönheitskorrekturen.
-
Bist du dir sicher, dass
CreateFile
erfolgreich war?
Schaust du dir auch die richtigetest.txt
an?
(Das wär nicht das erste mal, dass jemand im falschen Verzeichnis sucht)Was steht denn nun in
test.txt
drin?Hat das einen Grund warum du nicht die f-Funktionen aus
stdio.h
nimmst?
-
also es ist die richtige file habe ich auch im restlichen programm genau so und da funzt das auch. Das ganze mache ich so da ich mit owl next arbeite also auf die winapi zugreife. Es ist schon strange, die datei zeigt 0 byte an.
-
Xeno1987 schrieb:
..., die datei zeigt 0 byte an.
Daraus kannst du nicht schließen, in den Daten wäre nichts drin.
Deinsprintf
schreibt etwas in den buffer. Und wenn es"0.0\n"
ist.
Nur der Inhalt kommt nicht in die Datei. Demnach liegt das Problem bei den Dateioperationen.
-
jetzt weiss ich auch warum da nichts stand weil ich die Matrixstrucktur falsch ausgelesen habe, die schleifen waren richtig aber dass x[i] ist flasch, da dort die anzahl reihe mal spalte stehen sollte also ne weitere for schleife für die anzahl aller elemte der matrix --> x[cols*rows] = cvmget(i,cols-1)
-
Das hatte ich gemeint mit "es bleibt nur eine Schleife übrig".
Aber deine Lösung ist auch falsch.
Du brauchst eindeutige Wertefür den Index. (z.B. i=3, j=2 und i=2, j=3 führen zum selben Index).Nur, im Speicher steht irgendetwas, was
sprinft
in den buffer schreibt. Leer bleibt der nicht. Du hast halt nur falsche Werte gehabt.