Seltsames Problem mit char Feld *Help*



  • Guten Morgen!

    Das sieht ganz danach aus, als ob feisx kein '\0' am Ende des char-Feldes eingefügt hat. IMHO wird eine Struktur als zusammenhänger Speicherbereich allokiert. Das heißt, wenn man bank1 ausgeben will, wird bank1 auch ausgegeben. Da aber '\0' fehlt, wird der Speicher so lange weiter ausgegeben, bis mal ein '\0' kommt.

    Deswegen sind die Ausgaben auch:

    bank1 bank2 bank3 '\0'
    bank2 bank3 '\0'
    bank3 '\0'

    Also jedes char-Feld mit '\0' beenden, dann sollte die Ausgabe auch klappen!



  • Hallo,

    zunächst mal danke für schnellen Antworten.

    Aber beides hilft nicht, habs ausprobiert. Ich hab die Struktur in stdafx.h definiert und die Funktion ist in stdafx.cpp drin. stdafx ist keine Klasse. Denn die Struktur sowie die Funktion sollen in meinem progi global sein. Könnte das ein Problem sein?



  • Poste bitte nochmal den Code aus den drei Dateien (stdafx.h, stdafx.cpp und deine Anwendung).



  • DarthZiu schrieb:

    Das sieht ganz danach aus, als ob feisx kein '\0' am Ende des char-Feldes eingefügt hat.

    Wer hat denn von nullterminierten Strings gesprochen? Ich sehe bisher einfach nur char Arrays, mehr nicht. Deshalb macht es auch keinen Sinn, einfach so ein Nullzeichen am Ende jedes Arrays einzufügen. Man sollte halt nur die Ausgabe dann auch richtig handeln, und nicht erwarten, dass man simple char Arrays genauso wie C-Strings ausgeben kann. ZB

    printf("%.4s", msw_struct.bank1);
    

    Wobei simple Datenarrays sowieso nicht wie Strings gehandhabt werden sollten, da es immer noch das Problem mit der 0 gibt.



  • Ich denke aber, dass das genau das Problem ist. Er hat nicht gepostet, wie er sich die char's dann anzeigen lässt.

    Aber das hier sieht so aus, als ob er versucht unterminierte char-Arrays wie Strings ausgeben:

    Der so aussieht:
    bank1: abcdefghijklmnpqrs
    bank2: efghijklmnpqrs
    bank3: mnpqrs

    Deswegen würde ich den Code gerne mal sehen.



  • ich glaub dass DarthZiu recht hat!
    feisX muss einfach mal den code zum anzeigen posten. wenn dann ein printf("%s") vorkommt (wie das in c++ ausschaut weiß ich leider nicht), dann wissen wir was los ist...
    @DarthZiu: auf die idee wär ich übrigens nicht so schnell gekommen 🕶

    mfg
    Sebastian



  • Das sind schmerzhafte Erfahrungen, die ich in langen Nächten gesammelt habe; sofern die Vermutung stimmt.



  • Dass die Vermutung stimmt ist offensichtlich. Lest euch doch bitte nochmal meinen ersten Beitrag durch. Ich wollte eigentlich, dass feisX selber darauf kommt, dass seine Ausgabe nicht stimmen kann. Aber jetzt habt ihr ihm den ganzen Spass genommen.
    Und sofern feisX nicht erklärt, was er eigentlich vorhat, ist alles weitere Rätselraten. Letztendlich bleiben ihm 2 Möglichkeiten, entweder er ändert seine Datenstruktur, wie DarthZiu geschrieben hat oder er ändert seine Ausgabe, was man aus meinem letzten Beitrag entnehmen kann.



  • Hi! Wow da hat ich ja bereits ne richtige Diskussion entfacht 🙂

    Zur Ausgabe: Eigentlich werden diese char Felder garnicht ausgegeben. Im Grunde müssen Diese auch nicht vom Typ char sein. Die könnten auch int oder short oder byte sein. Aber darum gehts ja nicht. Ich habe char verwendet da es sich grad gut anbietet im Zusammenhang zu meinen anderen Funktionen.
    Die in den Feldern gespeicherten Werte werden später intern weiterverwendet, sind also nicht zur Ausgabe für den Benutzer vorgesehen.

    Ich poste mal den kompletten Kruscht:

    stdafx.h:

    // Matrix switching programs
    #define DEF_MATRIX_FILE_NAME		"matrix_switch_programs.ini"
    #define MATRIX_BANK1_QUANT		4	// Number of switches in Bank1
    #define MATRIX_BANK2_QUANT		8	// Number of switches in Bank2
    #define MATRIX_BANK3_QUANT		12	// Number of switches in Bank3
    
    typedef struct{
    	CString progName;
    	char bank1[MATRIX_BANK1_QUANT];
    	char bank2[MATRIX_BANK2_QUANT];
    	char bank3[MATRIX_BANK3_QUANT];
    }MATRIX_SWITCH;
    
    // Matrix switching programs. Should be expand for more programs.
    char switch_programs[][31] ={"EFF_LOWBAND_GMSK", "HARM_LOWBAND_GMSK", "LEAK_LOWBAND_GMSK", "SSG_CVG_LOWBAND_GMSK", "CURRENT_LOWBAND_GMSK",
    			     "EFF_HIGHBAND_GMSK", "HARM_HIGHBAND_GMSK", "LEAK_HIGHBAND_GMSK", "SSG_CVG_HIGHBAND_GMSK", "CURRENT_HIGHBAND_GMSK",
                                 "EFF_LOWBAND_EDGE", "HARM_LOWBAND_EDGE", "LEAK_LOWBAND_EDGE", "SSG_CVG_LOWBAND_EDGE", "CURRENT_LOWBAND_EDGE",
                                 "EFF_HIGHBAND_EDGE", "HARM_HIGHBAND_EDGE", "LEAK_HIGHBAND_EDGE", "SSG_CVG_HIGHBAND_EDGE", "CURRENT_HIGHBAND_EDGE",
                                 "CARRIER_SW_TIME_LOWBAND_GMSK", "CARRIER_SW_TIME_HIGHBAND_GMSK", "ISOLATION_LOWBAND_GMSK", "ISOLATION_LOWBAND_GMSK",
                                 "GAIN_CONTR_SLOPE_LOWBAND_GMSK", "GAIN_CONTR_SLOPE_HIGHBAND_GMSK", "GAIN_CONTR_SLOPE_LOWBAND_GMSK",
                                 "GAIN_CONTR_SLOPE_HIGHBAND_GMSK", "EVM_LOWBAND_EDGE", "EVM_HIGHBAND_EDGE", "DET_ACC_LOWBAND_GMSK",
    			     "DET_ACC_HIGHBAND_GMSK", "DET_ACC_LOWBAND_EDGE", "DET_ACC_HIGHBAND_EDGE", "YIELD_LOWBAND_GMSK", "YIELD_HIGHBAND_GMSK"};
    

    stdafx.cpp

    bool FillMatrixSwitchPrograms(void)
    {	// Reads the switching file for the pickering matrix
    	// Function needs a global vector object with MATRIX_SWITCH structure
    
    	CString pstrFile = SystemStruct.program_path;
    	pstrFile += DEF_MATRIX_FILE_NAME;
    	CString strRead = "";	
    	bool reading = true;
    	MATRIX_SWITCH	msw_struct;
    	vector<CString> vec_results;
    	int itmp = sizeof(switch_programs[0]);
    	int size = sizeof(switch_programs) / itmp;
    	CString strLine ="";
    
    	try{
    	// Open the file
    	CFile *pFile = new CFile((LPCTSTR)pstrFile, CFile::modeRead);
    	CArchive *ar = new CArchive(pFile, CArchive::load);
    
    	// Read the file and fill the vector object with the MATRIX_SWITCH structure
    	while(reading) {
    		if( !ar->ReadString(strRead) ) { reading = false; }
    
    		// Check for the right SystemNr
    		if( ExtractString(strRead, KEY_SYSTEM_ID, &strLine) ){
    			ValidateSystemID(strLine, pstrFile);
    		}
    
    		for(int i=0; i < size; i++){
    			vec_results.clear();
    			if(ParseLine(strRead, switch_programs[i], &vec_results)){
    				msw_struct.progName = switch_programs[i];
    
    				for(int j=0; j < (int)vec_results.size(); j++){
    					if(j < MATRIX_BANK1_QUANT){ 
    						msw_struct.bank1[j] = vec_results[j][0]; }	
    
    					if((j >= MATRIX_BANK1_QUANT) && (j < (MATRIX_BANK1_QUANT+MATRIX_BANK2_QUANT))){ 
    						msw_struct.bank2[j-MATRIX_BANK1_QUANT] = vec_results[j][0]; }
    
    					if((j >= (MATRIX_BANK1_QUANT+MATRIX_BANK2_QUANT)) && (j < (MATRIX_BANK1_QUANT+MATRIX_BANK2_QUANT+MATRIX_BANK3_QUANT))){ 
    						msw_struct.bank3[j-MATRIX_BANK3_QUANT] = vec_results[j][0]; }	
    				}
    				// Put the results into the switch-programs vector
    				msw_struct.progName = switch_programs[i];
    				vec_MatrixSwitch.push_back(msw_struct);
    				break;
    			}
    		}		
    	}
    
    	// Free the file
    	pFile->Close();
    	}catch(...){ 
    		return false;
    	}
    	return true;
    }
    
    bool ParseLine(CString fullStr, CString strKey, vector<CString>* resultVec)
    {	// Extracts all part strings from a line, between the key and the comment	
    	CString tmp = "";
    	CString afterKey = "";
    	char tmpchar;
    	bool b_switchflag = false;
    
    	// Find Key and extracts its line
    	if(!ExtractString(fullStr, strKey, &afterKey)){ return false; };
    
    	try{
    	// filter all strings between the KEY_IGNORE_LETTERs and the end of line
    	for(int i=0; i < afterKey.GetLength(); i++){
    		tmpchar = afterKey[i];
    
    		if( (tmpchar != KEY_IGNORE_LETTER1) &&  (tmpchar != KEY_IGNORE_LETTER2) ){
    			tmp += tmpchar;
    			b_switchflag = false;
    		}	
    		if(!b_switchflag){
    			resultVec->push_back(tmp);
    			b_switchflag = true;
    			tmp = "";
    		}
    	}
    
    	}catch(...){ return false; }
    
    	return true;
    }
    

    Das meiste davon sollte unwichtig sein für mein Prob.
    Kurze Erläuterung zu der Hauptaufgabe:

    In einem File 'matrix.ini' sind sämtliche Schalterstellungen für verschiedene Programme gespeichert. Das sieht dann ungefähr so aus:

    # | Program |	| Bank 1 |    | Bank2 |         | Bank3|
    # ----------------------------------------------------------
    EFF_LOWBAND_GMSK:  4 2 2 1	      1 1 1 1 0 1 1 1  usw....	
    HARM_LOWBAND_GMSK: 2 2 2 6	      1 1 1 1 0 1 1 1
    LEAK_LOWBAND_GMSK:	 5 2 2 1       0 1 1 1 0 1 1 1 
    usw....
    

    Die Funktion FillMatrixSwitchPrograms soll nun diese Datei einlesen und alle Werte zu den jeweiligen Programmen in nem vector oder sonst wo ablegen. Dafür nutze ich die Struktur MATRIX_SWITCH, die dann so oft im vector abgelegt wird wie es Programme gibt. (Mit Programme meine ich Kombinationen von Schalterstellungen).
    Soweit sogut.
    Die fkt. ParseLine holt aus einem String einzelne Zusahhemhängende Strings und füllt damit einen vector vom Typ CString. Desshalb heißt es bei mir dann, auch wenn etwas unschön: msw_struct.bank2[j-MATRIX_BANK1_QUANT] = vec_results[j][0];
    Ich spreche den String immer mit [0] an, da in diesem Fall immer ein einzelner Wert an Stelle 0 steht. So das wars eigentlich.

    Ich glaug ich stell mich hier irgentwo blöd an, an der Stelle an der ich den vec_results auslese. Habs aber nicht anders hingekriegt. 🙄



  • Dann weiß ich aber nicht, wie du zu dieser Überzeugung kommst:

    feisX schrieb:

    Der so aussieht:
    bank1: abcdefghijklmnpqrs
    bank2: efghijklmnpqrs
    bank3: mnpqrs

    Da hat groovemaster völlig recht: Ein char[4] speichert genau vier Werte - basta. Keinen mehr und keinen weniger.



  • DarthZiu schrieb:

    Dann weiß ich aber nicht, wie du zu dieser Überzeugung kommst:

    feisX schrieb:

    Der so aussieht:
    bank1: abcdefghijklmnpqrs
    bank2: efghijklmnpqrs
    bank3: mnpqrs

    Da hat groovemaster völlig recht: Ein char[4] speichert genau vier Werte - basta. Keinen mehr und keinen weniger.

    Ne ist wirklich so, hab ich doch deschrieben das ich's im debug-mod mitverfolgen kann. bank1 wird trotz der Größe von 4 weitergeschrieben.

    Hab ein Bildchen beim debuggen gemacht: http://www.rz.fh-ulm.de/~arwagner/feld.jpg



  • Ui, dass is wirklich interessant. Leider habe ich keine Ahnung von diesem Debugger , den du benutzt. Vielleicht kann hier nochmal jemand anderes schauen. *in.die.Runde.guckt*



  • @feisX
    Die Anzeige sollte dich nicht weiter interessieren. Imo ist das ein Fehler in der Debugger Anzeige. Ich benutze selbst Visual C++ .NET und werde das mal bei Gelegenheit ausprobieren. Wenn du eine Variable vom Typ char[4] deklarierst, sollte der Debugger auch nur 4 chars anzeigen. Leider interpretiert er das als C-String, da so einer vom gleichen Typ ist, und dann stimmr einfach die Anzeige nicht mehr, da erst bei einem Nullzeichen mit der Ausgabe gestoppt wird.
    Wie bereits gesagt wurde, wenn du eine Variable vom Typ char[4] deklarierst, dann passen da auch nur 4 Zeichen rein. Da bank1, bank2 und bank3 im Speicher hintereinander liegen, entsteht durch die falsche Anzeige der Effekt, dass zB in der bank1-Anzeige noch die Daten von bank2 und bank3 zu sehen sind. Das ist aber ein reines Anzeigeproblem. Beim Durchsteppen der Schleife solltest du ja eigentlich sehen, ob zB in bank1 noch geschrieben wird, wenn j >= MATRIX_BANK1_QUANT. Und das dürfte nicht passieren.



  • Hallo,

    ja das mit der falschen Anzeige im Debugger isr mir bekannt, aber diesmal ist es leider nicht nur ne falsche Anzeige. Hab ein feld testweise mal auf eine EditControl ausgegeben und erhalte dabei auch tatsächlich mehr als 4 Zeichen.

    GetDlgItem(IDC_EDIT1)->SetWindowText((LPCTSTR)vec_MatrixSwitch[0].bank1);
    

    Bildchen: http://www.rz.fh-ulm.de/~arwagner/edit.jpg

    Naja hilft alles nix, dann werd ich wohl meine Datenstruktur überdenken müssen. Aber danke für euer Engagement! 👍



  • Das mit dem Edit-Control ist exakt das gleiche wie mit dem Debugger, da WinAPI Funktionen, die mit Strings arbeiten, ebenfalls auf C-Strings basieren.

    feisX schrieb:

    GetDlgItem(IDC_EDIT1)->SetWindowText((LPCTSTR)vec_MatrixSwitch[0].bank1);
    

    Nur weil man mit Casts den Compiler hier und da dazu bewegen kann, den Code zu akzeptieren, muss das noch lange nicht richtig sein. Wenn du dein Projekt in der UNICODE Version compilierst wirst du hier Probleme bekommen.


Anmelden zum Antworten