Pointer Arraz an Funktion übergeben
-
Hallo,
Ich habe das Problem, dass ich aus einer einem Array Werte an eine andere Funktion übergeben möchte aber dies nicht klappt. Habe inzwischen rausgefunden dass die Werte null sind, also werden die nicht übergeben.
Hauptfunktion:
void TImageCompFrame::CompareProfiles() { char buffer[30]; DWORD retval; float m = 0.0, b = 0.0; //CvMat* final = cvCreateMat(img_sttm[0]->height, img_sttm[0]->width, CV_32FC1); //GetOCTProfile(img_sttm[0]); //GetSTOTMProfile(img_sttm[1]); //HANDLE hDataFile = CreateFile("final.dat", GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); float *x = (float*)malloc(8000000*sizeof(float)); float *y = (float*)malloc(8000000*sizeof(float)); 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++ = cvmGet(StotmVals, i, j); *y++ = cvmGet(OctVals, i, j); //buffer[5] = buffer[15]= ','; if(*x != 0){ sprintf(buffer, "%f\n", *x); MessageBox(buffer, "", MB_OK); } //WriteFile(hDataFile, buffer, strlen(buffer), &retval, NULL); } } LinReg((int)(OctVals->rows*OctVals->cols), x, y, &b, &m); sprintf(buffer, "%f\n", b); MessageBox(buffer, "", MB_OK); //CloseHandle(hDataFile); }
Nebenfunktion:
void LinReg(int n, float *x, float *y, float *a0, float *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 float x1=0,x12=0,y1=0,x1y1=0,e, xn, yn; x = (float*)malloc(n*sizeof(float)); y = (float*)malloc(n*sizeof(float)); for(int i=0;i<n;i++){ xn = *x++; // Bei Übergabe schief gegangen da wahrscheinlich null yn = *y++; 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; }
-
Glaub das gehört eher ins C++ Forum, ~~dennoch:
[code="c"]*x++ = cvmGet(StotmVals, i, j);
*y++ = cvmGet(OctVals, i, j);[/code]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:
[code="c"]*(i++) = x;[/code]
Dies wird vermutlich auch der Grund sein, warum dein übergebenes Pointer-Array leer ist.~~
Bitte Wutz Beitrag beachten.
-
Nirvash schrieb:
Glaub das gehört eher ins C++ Forum,
Technisch richtig, aber ich bin mir nicht sicher, ob dem Threadersteller überhaupt bewusst ist, dass er C++ macht oder was C++ überhaupt ist. Bis auf eine Zeile ist das typischer C-Code. Mit dem üblichen Schrott, den Leute reinmachen, denen nicht bewusst ist, dass sie einen C++-Compiler benutzen.
-
Set me free!
-
Was sollen denn die Zeilen 10 und 11 in
LinReg
machen?
-
zeile 10 und 11 sind eig falsch/überflüssig da speicher schon im hauptprogramm allokiert wurden. Wäre aber dennoch dankbar wenn den code jemand korrigieren könnte da ich das dringend für ein teil meiner bachelor arbeit brauche. Hab es erst mal ohne pointer direkt im hauptcode integriert da brauch ich auch keine speicher allokation, aber es wäre schön das als unabh funktion zu haben für spätere einsetze wegen code duplizierung. Vielen lieben dank! Wie gesagt es werden die Werte bzw 2 Arrays nicht übergeben warum auch immer.
-
Xeno1987 schrieb:
zeile 10 und 11 sind eig falsch/überflüssig da speicher schon im hauptprogramm allokiert wurden.
Nicht nur eigentlich falsch, sondern total falsch. Mit den Parametern x und y hast Du nach den beiden Zeilen nur noch Zugriff auf einen neuen Speicherbereich, nicht aber auf den in der aufrufenden Funktion erstellten.
-
Xeno1987 schrieb:
zeile 10 und 11 sind eig falsch/überflüssig da speicher schon im hauptprogramm allokiert wurden. Wäre aber dennoch dankbar wenn den code jemand korrigieren könnte da ich das dringend für ein teil meiner bachelor arbeit brauche. Hab es erst mal ohne pointer direkt im hauptcode integriert da brauch ich auch keine speicher allokation, aber es wäre schön das als unabh funktion zu haben für spätere einsetze wegen code duplizierung. Vielen lieben dank! Wie gesagt es werden die Werte bzw 2 Arrays nicht übergeben warum auch immer.
Dem kann man fast entnehmen, du möchtest das Problem nicht selbst lösen, sondern hast hier einfach nur gepostet, um dein Problem lösen zu lassen. Ergo, wäre der Abschnitt für Auftragserteilung wohl eher besser geeignet für deinen Post.
Anhand deines Codes und auch deiner Beschreibung wird ersichtlich, dass du das Grundprinzip der Speicherallokierung und des Variablenzugriffs nicht ganz verstanden hast.Zudem arbeitest du an einer wissenschaftlichen Arbeit, dies impliziert auch eine gewisse Fähigkeit zur selbstständigen Lösung von komplexen Problemen und der Aneignung zusätzlichen Wissens zur Bewältigung derer. Möchtest du einen akademischen Grad erlangen, so sollte man meiner Meinung nach, zu diesem auch in der Lage sein. Bei meiner Thesis war es schließlich nicht anders.
-
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.
-
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.