Seltsames Problem mit char Feld *Help*
-
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: mnpqrsDeswegen 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 gekommenmfg
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: mnpqrsDa 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: mnpqrsDa 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.