C++ Problem mit Übergabe von mehreren Werten

camthalion

Newbie
Registriert
Mai 2009
Beiträge
3
Guten Abend zusammen. Ich bastel gerade an einer dialogbasierten MFC-Anwendung mit VS2005.
Ich rufe aus der Dialog-Klasse eine zweite Klasse auf, die 2 Zeichenketten vergleichen soll. Soweit klappt auch alles. In der 2. Klasse werden Gewichtungen, je nach Art des Vergleichsergebnisses in From von 4 int Variablen erstellt. Diese möchte ich nun zurück an die DLg-Klasse geben. Zu diesem Zweck habe ich eine externe Struktur erstellt, die diese Werte aufnimmt.
Nun zu meinem Problem: Immer wenn die Funktion der 2. Klasse abgearbeitet ist, springt der Debugger ja zurück in die Dialogklasse. Und mit verlassen der 2. Klasse verschwinden auch die Werte, die ansich in der externen Struktur gespeichert werden sollten. Und das obwohl das Objekt ansich noch nicht gelöscht wurde.

Wie kann ich also von der aufgerufenen Klasse mehrere Werte an die Ursprungsklasse zurückgegen? Bin da schon am Verzweifeln.
 
Zeig uns doch mal den (relevanten) Code. Die Idee ist ja an sich die richtige.
 
Genau, Code wäre sehr hilfreich.

Ohne mich groß reinzudenken:
Speicher deine 4 variablen in einem Array und gib eine Referenz (einen Pointer) darauf an die aufrufende Funktion zurück.
 
Ich würde es nicht über Referenz/Pointer machen, es sei denn, es ist performance-kritisch... aber ansonsten ist es mit statischen structs meiner Meinung nach besser.
 
Ich würde es nicht über Referenz/Pointer machen, es sei denn, es ist performance-kritisch...
Generell sollte man immer (außer bei plain old data) wo es möglich ist mit Referenzen/Pointern arbeiten (soll der Inhalt nicht verändert werden dürfen mit const). Man gewöhnt sich somit schon keinen schlechten Programmierstil an und schneller ist es außerdem.

aber ansonsten ist es mit statischen structs meiner Meinung nach besser.
das wiederum klingt nun ziemlich abenteuerlich. Begründung?

Zum Thema:
Am besten postest du wirklich mal wie du das machst weil mir scheint du wirfst da auch von den Begrifflichkeiten etwas durcheinander.
 
Du hast die Struktur innerhalb der Methode erzeugt. Mit verlassen des Scopes wird diese natürlich ungültig. Besser wäre es, wenn du die Struktur in der Dialog-Klasse erzeugst, und dann als Referenz an die Auswertungs-Klasse übergibt. Diese schreibt ihre Ergebnisse einfach in die als Referenz übergebene Struktur.
Hier ein bisschen Pseudo-Code:
Code:
strukt ergebnis {int a; int b; int c; int d;};

//Dialog-Klasse: 
ergebnis meinErgebnis;
Auswertungs_Klasse->vergleiche (a, b, meinErgebnis); 

//Auswertungs-Klasse: 
void auswertungklasse::vergleiche (const string a, const string b, &meinErgebnis)
{
     //Die strings vergleichen, und die Ergebnisse in das als Referenz übergebene Strukt speichern: 
     meinErgebnis.a = 5;
}
Dies soll nicht mehr als Pseudo-Code sein. Ich möchte nur das Prinzip erläutern. ;)
 
Zuletzt bearbeitet:
Den ganzen Code hier zu posten wäre etwas zu viel denk ich. Vielleicht reichen euch ja schon die Schnipsel hier:

Dies ist erstmal die Struktur, die ich neben vielen anderen in einer einer Datei mit dem Namen "mfGeneralDeclarations.h" gesammelt habe.
Code:
#ifndef MF_STRUCT_ALIGNMENT_RESULTS
 #define MF_STRUCT_ALIGNMENT_RESULTS

typedef struct _mfAlignmentResults {

	int iReplaceRes;
	int iInsertRes;
	int iMatchRes;
	int iDeletRes;
}mfAlignmentResults;

#endif

Der Header für die Dlg-Klasse:

Code:
// AlignItDlg.h : Headerdatei
//
#define IDD_ALIGNIT_DIALOG 102
#pragma once
#include "mfGeneralDeclarations.h"
#include "mfDynamicProgramming.h"

// CAlignItDlg Dialogfeld
class CAlignItDlg : public CDialog
{
// Konstruktion
public:
	CAlignItDlg(CWnd* pParent = NULL);	// Standardkonstruktor

// Dialogfelddaten
	enum { IDD = IDD_ALIGNIT_DIALOG };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV-Unterstützung


// Implementierung
protected:
	HICON m_hIcon;

	// Generierte Funktionen für die Meldungstabellen
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()

	char *szA;
	char *szB;
	char *_szDateiTextA;
	char *_szDateiTextB;
	CEdit  *_objEdit;
	CEdit  *_objEdit2;
public:
	_mfAlignmentWeights _stWeights; 
	_mfAlignmentResults _stResults;
	int _iTest;
	afx_msg void OnBnClickedSeqEinl();
	void OnSequenzeinlesen(void);
	char * GetFileName(char* szFileName, char bOpenFlag);
	void LeseTextDateiA(char *szDatei);
	void LeseTextDateiB(char *szDatei);
	afx_msg void OnBnClickedGlobal();
public:
	int m_iMatch;
	int m_iReplace;
	int m_iDelet;
	int m_iInsert;
protected:
	bool m_bGobal;
public:
//	int _iTest;
	
	
};

Die entscheidende Funktion aus der Dlg-Klasse

Code:
void CAlignItDlg::OnBnClickedGlobal()
 {
		mfDynamicProgramming *objDynPro;
		objDynPro =NULL;
		objDynPro= new mfDynamicProgramming();
		objDynPro->Initialize(szA,szB);
		_stWeights.ubType = MINIMIZATION;
		_stWeights.iInsertion =2;
		_stWeights.iDeletion =2;
		_stWeights.iReplacement = 1;
		_stWeights.iMatch = 0;
		_stWeights.ubAlignmentStrategy=MF_GLOBAL;
		
		objDynPro->AddWeights(& _stWeights);
		objDynPro->DoGlobalAlignment();                <-- Um diese Funktion geht es
		m_iInsert=_stResults.iInsertRes;
		m_iDelet=_stResults.iDeletRes;
		m_iMatch=_stResults.iMatchRes;
		m_iReplace=_stResults.iReplaceRes;
		UpdateData(false);
		delete objDynPro;
 }

Der Header der augerufenen Klasse

Code:
#include "mfGeneralDeclarations.h"


#ifndef MF_DYNAMIC_PROGRAMMING
 #define MF_DYNAMIC_PROGRAMMING



 class mfDynamicProgramming {


  public:
         mfDynamicProgramming(void);            // Konstruktoren ...
		 mfDynamicProgramming(char *,char*);    // ... .
		 ~mfDynamicProgramming(void);           // Destruktor.


         void AddWeights(mfAlignmentWeights *);         // Gewichtung in Objekt setzen.
         void DoEndsFreeAlignment(void);                // Mit diesen Funktionen können aufrufende  ...
         void DoGlobalAlignment(void);                  // ... Objekte, je nach vorher festgelegter ...
	     void DoLocalAlignment(void);                   // ... Gewichtung, entsprechende Alignments anstoßen.
	     unsigned char ObjectReady(void);               // Testen, ob das Objekt einsatzbereit ist.
	     unsigned char SetNewStringA(char *);           // Mit diesen Funktionen können dem Objekt zur Lauf- ...
	     unsigned char SetNewStringB(char *);           // ... zeit neue Zeichenketten für das Alignment   ...
	     unsigned char SetNewStringPair(char *,char *); // ... eingegeben werden.
   		 unsigned char Initialize(char *,char *);
     
  protected:
         char *_szA;                                    // Objektglobale Verfügbarkeit der Zeichen- ... 
         char *_szB;                                    // ... ketten A unde B, die aligned werden sollen.
	     unsigned char _ubObjectReady;                  // Flag zur Einsatzbereitschaft des Objektes.
		 mfAlignmentWeights _stWeights;                 // Objektglobale Verfügbarkeit der Gewichtungen.
         mfAlignmentResults _stResults;
		 int **Allocate2DimMatrix(unsigned int,         // Speicherplatz für eine zweidimensionale Matrix ...
		                          unsigned int);        // ... des Typs(int|int) dynamisch allokieren.
         void BackTracing(int **);                      // Das gefundene Alignment zurückverfolgen.
         void Free2DimTable(int **,unsigned int);       // Freigabe einer allokierten 2D Matrix.
         void GetAnchors(mfAlignmentAnchors *,          // Die Indices für die Ausgabe des Allignments ...
								  int **,mfAlignmentString *);   // ...berechnen und die Alignmentzeichenkette ermitteln.
         int GetMaximumOfThree(int *);                  // Mit diesen Funktionen wird aus n Daten der ...
         int GetMaximumOfFour(int *);                   // ... größte oder kleinste Wert ermittelt. ...
         int GetMinimumOfThree(int *);                  // ... .
         void GlobalAlignmentBackTracing(int **);       // Eine einfache Darstellung eines Backtracings.
         void Initialize(void);                         // Vorbelegung der objektglobalen Mitgliedsvariablen ...
                // ... mit fehlersensitiven Werten oder Einsatzwerten.
         char LookAround(int **,int *,int *);           // Diese Funktionen testen das Vorgängerfeld auf die ...
         char LookAround(int **,int *,int *,            // ... entsprechenden Werte. ...
		                 unsigned char *);              // ... .
         void PrintAlignment(mfAlignmentAnchors *,      // Ausgabe des indicierten Alignments (für EndsFree...
		                     mfAlignmentString *);      // ... und Local).
         int WeightDetection(unsigned int,unsigned int);// Unterscheidung für "M"atch und "R"eplace.
 };



#endif

Die wichtige Funktion aus der aufgerufenen Klasse

Code:
void mfDynamicProgramming::DoGlobalAlignment(void)
 {
 
  unsigned int uiI=0;
  unsigned int uiJ=0;
  unsigned int uiN=0;
  unsigned int uiM=0;
  int iD[3];
	

  int **iMatrix=NULL;

  uiN= strlen(_szA);
  uiM= strlen(_szB);
  
  iMatrix=Allocate2DimMatrix(uiN+1,uiM+1);
  if(iMatrix==NULL)
	return;
  
 
  //---------------------- Initialization ------------------------
  iMatrix[0][0]=0;

  for(uiI=1;uiI<=uiN;uiI++)
    iMatrix[uiI][0]=iMatrix[uiI-1][0]+_stWeights.iInsertion;

  for(uiJ=1;uiJ<=uiM;uiJ++)
    iMatrix[0][uiJ]=iMatrix[0][uiJ-1]+_stWeights.iDeletion;	


  //---------------------- Local distances -----------------------
  for(uiJ=1;uiJ <= uiM;uiJ++)     
   for(uiI=1;uiI <=uiN;uiI++)
    {
	 iD[0]= iMatrix[uiI-1][uiJ]+_stWeights.iDeletion;
     iD[1]= iMatrix[uiI-1][uiJ-1]+WeightDetection(uiI,uiJ);
     iD[2]= iMatrix[uiI][uiJ-1]+_stWeights.iInsertion;
	 if(_stWeights.ubType == MINIMIZATION) 
       iMatrix[uiI][uiJ]=GetMinimumOfThree(iD);
	 if(_stWeights.ubType == MAXIMIZATION) 
       iMatrix[uiI][uiJ]=GetMaximumOfThree(iD);

	}


  for(uiJ=0;uiJ <=uiM;uiJ++) {
   for(uiI=0;uiI <= uiN;uiI++)
     printf("%d\t",iMatrix[uiI][uiJ]);
   printf("\n");
  }

  printf("Levinshtein Edit-Distanz von %s gegen %s = %d\n\n",_szA,_szB,iMatrix[uiN][uiM]);

	
  GlobalAlignmentBackTracing(iMatrix);     //  Hier wird die Fkt Lookaround aufgerufen, die unter anderem die Werte in die Variablen aus der Struktur schreibt

Free2DimTable(iMatrix,uiN) ;
 }

Code:
void mfDynamicProgramming::GlobalAlignmentBackTracing(int **iMatrix)
 {
  int iI=0;
  int iJ=0;
  unsigned int uiA;
  unsigned int uiN=0;
  unsigned int uiM=0;
  unsigned char *ubTs=NULL;
  unsigned int uiTcnt=0;
  uiN= strlen(_szA);
  uiM= strlen(_szB);
   

  iI=(int)uiN;  // Beim globalen Alignment beginnt das Backtracing an der rechten unteren ...
  iJ=(int)uiM;  // ... Ecke der Matrix.

  ubTs= new unsigned char [uiN+uiM+2];  // Array zur Aufnahme der Transformationen.
  if(ubTs==NULL) return ;

  char *szTmp= NULL;
  szTmp= new char [uiN * uiM];
  szTmp[0]='\0';


  for(;;)                               
   {
	ubTs[uiTcnt++]=LookAround(iMatrix,&iI,&iJ);
     
    if(iI < 0)                          //           MRIMMMRIRDMMM
     iI=0;                              //           ##-####-#####
                                        //           #########-###
    if(iJ < 0)
	 iJ = 0;                            

    if(!iI  &&  !iJ)
     break;
   }


  //printf("\n");
  strcat(szTmp,"\n");
  char szNucleotid[2];
  szNucleotid[1]= '\0';
  for(uiA=uiTcnt;uiA > 0;uiA--)         // Das Array mit den Transformationen wird ausgegeben. 
  {
   //printf("%c ",ubTs[uiA-1]);
   szNucleotid[0]=ubTs[uiA-1];
   strcat(szTmp,szNucleotid);
  }

  MessageBox(NULL,szTmp,"Info",MB_OK);
  printf("\n");                         // In der nächste Zeile erfolgt die Ausgabe der  ...
  unsigned int uiB=0;                   // ...
  for(uiA=uiTcnt;uiA > 0;uiA--)         // ... ersten Zeichenkette. Dabei wird das Array  ...
   {                                    // ... mit den Transformationen dazu herangezogen,...
    if(ubTs[uiA-1] == MF_INSERTION)     // ... an die betreffenden Stellen mit Insertionen...
	 printf("- ");                  // ... entsprechend "-" zu schreiben.
	else                            // ...
	 printf("%c ",_szA[uiB++]);     // ...
   }                                    // ...
  uiB=0;                                // ...
  printf("\n");                         // ... In der nächste Zeile wird die zweite Zeichen...
                                        // ...
  for(uiA=uiTcnt;uiA > 0;uiA--)         // ... kette in gleicher Weise, jedoch unter Berück-...
   {                                    // ... sichtigung der Deletionen ausgegeben.
    if(ubTs[uiA-1] == MF_DELETION)
	 printf("- ");
	else
	 printf("%c ",_szB[uiB++]);
   }


  printf("\n");
  delete [] ubTs;
 }

Und zu guter Letzt:

Code:
char mfDynamicProgramming::LookAround(int ** iMatrix,int *iI,int *iJ)
 {
  int iD[3];
  int iHit;


    
    if((*iJ > 0) && (*iI > 0))
	 {
      iD[0]=iMatrix[*iI][*iJ-1];    // Insertion
      iD[1]=iMatrix[*iI-1][*iJ-1];  // Match/Replace
      iD[2]=iMatrix[*iI-1][*iJ];    // Deletion
	 }
    else
	 {
	  if(*iI > 0)
	   {
        // iD[2]=iMatrix[*iI-1][*iJ];     Deletion.
        *iI-=1;
	    return MF_DELETION;
	   }
	  else  // Element (0|0)
	   {
        // iD[0]=iMatrix[*iI][*iJ-1];     Insertion
        *iJ-=1;
	    return MF_INSERTION;
	   }
     }


    if(_stWeights.ubType == MINIMIZATION)
     iHit=GetMinimumOfThree(iD);
    if(_stWeights.ubType == MAXIMIZATION)
     iHit=GetMaximumOfThree(iD);


    if(iHit == iD[1])
     {
      *iI-=1;
      *iJ-=1;
	  if(_szA[*iI] != _szB[*iJ])
	  {
			_stResults.iReplaceRes++	;
		  return MF_REPLACE;
	  }
		  if(_szA[*iI] == _szB[*iJ])
		  {
			_stResults.iMatchRes++	;
			return MF_MATCH;
		  }
		  return '?';
     }

    if(iHit==iD[0])
	 {
      *iJ-=1;
		_stResults.iInsertRes++	;
	  	  return MF_INSERTION;
	 }


    if(iHit==iD[2])
	 {
      *iI-=1;
	  _stResults.iDeletRes++	;
	  
	  return MF_DELETION;
	 }

  return iHit;
 }

Und am Ende steht in meinen Variablen _stResults.****Res immer die schöne Zahl -858993460.
 
Der Grund warum das nicht funktioniert ist folgender:
_stResults existiert zweimal. Einmal als
_mfAlignmentResults _stResults; in der Dialog Header
und einmal als
mfAlignmentResults _stResults; in der mfDynamicProgramming Header.

Beim Funktionsaufruf werden die Ergebnisse in zweitere geschrieben.

Code:
m_iInsert=_stResults.iInsertRes;
		m_iDelet=_stResults.iDeletRes;
		m_iMatch=_stResults.iMatchRes;
		m_iReplace=_stResults.iReplaceRes;

da liest du aber aus der Dialog-Member. Deswegen auch -858993460. Die ist nicht initialisiert.
Lösen kannst du das so z.B.:
m_iInsert=objDynPro->_stResults.iInsertRes;
Da _stResults aber protected ist müsste das auf public umgestellt werden. Andere Möglichkeit wäre z.b. das _stResults in mfDynamicProgramming ganz weg zulassen und stattdessen einen Zeiger/Referenz zu übergeben. Da musst du halt selbst schauen wie du es löst

Warum soll es schlechter Programmierstil sein?
z.B. wegen Kapselung
 
Danke Leute, funktioniert jetzt. Hab es so gemach, wie wayne es geschrieben hat. Die Idee mit dem Pointer probier ich aber auch nochmal aus. Habt mir das Wochenende gerettet ;)
 
Zurück
Oben