c++ *char == '='



  • Hallo Leute,

    ich komme aus Java und bin in Richtung C++ neu.
    Nun habe ich folgendes Problem: Ich möchte aus einer .properties-Datei Werte auslesen und diese als Titel/Tab Titel in einem Fenster ausgeben. Das hat auch geklappt und der Text erschien als Titel in dem Fenster, bis ich angefangen habe, ein key-value-Prinzip zu entwickeln. Ich habe in meine Datei hineingeschrieben: "Appointment Management = Terminverwaltung". Wenn ich das compiliere, bekomme ich folgende Ausgabe:

    "Ausnahme ausgelöst bei 0x54DE73A7 (vcruntime140d.dll) in PersonalOrganizer.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x6F726389."

    Hier mein Code:

    wchar_t *to_wchar_t(char cstring[]) {
    size_t newsize = strlen(cstring) + 1;
    	wchar_t *wchar = new wchar_t[newsize];
    	size_t convertedChars = newsize;
    	mbstowcs_s(&convertedChars, wchar, newsize, cstring, _TRUNCATE);
    	return wchar;
    }
    void translateLine(char* line,char* key, char* value){
    	int i = 0,l = 0;
    	while (!(line[i] == '=')) {
    		key[i] = line[i];
    		i++;
    	}
    	int r = i;
    	for (i < sizeof(line); i++; l++) {
    		if (line[i] == '=')
    			continue;
    		value[l] = line[i];
    	}
    }
    void initTextValues() {
    	int max_length = 256;
    	fstream f;
    	char* key = new char[max_length];
    	char* value = new char[max_length];
    	char* line = new char[max_length];
    	f.open("TextFile1.properties", ios::in);
    	int i = 0;
    	while (!f.eof())
    	{
    		f.getline(line, sizeof(line));
    		translateLine(line,key,value);
    		title = to_wchar_t(value);
    	}
    	f.close();
    	delete[] value;
    }
    

    Ich darf an dieser Stelle erklären, dass ich char* genommen habe, um die Länge in einer Variable speichern zu können. Um einen Wert in meinem Fenster anzuzeigen, muss dieser in wchar_t umgewandelt werden.
    Mir ist aufgefallen, dass die for- und die while-Schleife meiner translateLine-Methode unregelmäßig oft durchlaufen werden, einmal war es bei der Schleife z.B. 327 mal. Ich dachte eigentlich, dass nach ein paar mal der Punkt kommt, wo das char-Array line den Wert "=" hat. Dann ist es wahrscheinlich so, dass der enthaltene Wert noch wesentlich mehr Zeichen enthält?
    Ich steig bei den chars in C++ noch nicht durch. Wer kann mir helfen?

    Edit Arcoth: Code-Tags


  • Mod

    Was bedeutet sizeof(line)? Meintest Du vielleicht strlen(line)? (Sollte lieber vor der Schleife berechnet werden)

    Ich frage mich zudem, weshalb value freigegeben wird, der andere allozierte Speicher jedoch nicht.



  • Warum benutzt du nicht std::string und std::wstring?



  • wchar_t *to_wchar_t(char cstring[]) {
    size_t newsize = strlen(cstring) + 1;
    	wchar_t *wchar = new wchar_t[newsize];
    	size_t convertedChars = newsize;
    	mbstowcs_s(&convertedChars, wchar, newsize, cstring, _TRUNCATE);
    	return wchar;
    }
    

    Das ist aus meiner SIcht einer der größten Fallstricke von C# und Java. Durch den Garbage Collector legen sich einige Entwickler den Stil an, ständig neue Objekte zu allokieren und das alte Objekt durch den Garbage Collector löschen zu lassen.

    C++ ist da komplett anders. Lerne bitte Begriffe wie Stack, Heap, Konstruktor, Destruktor, RAII, Zeiger, Referenzen, L-Values, R-Values, Placement New, Move Semantik,...

    Dann verstehst du auch warum man std::string und std::wstring nutzen sollte.



  • @PCGirl sagte in c++ *char == '=':

    while (!(line[i] == '=')) {
    key[i] = line[i];
    i++;
    }

    Das ist hochgefährlich. Was passiert, wenn line gar kein "="-Zeichen enthält?

    while (!f.eof())
    {
    f.getline(line, sizeof(line));

    Das ist ebenfalls in C++ nicht richtig. Man sollte grundsätzlich erst NACH dem Lesen / Leseversuch testen. Davor hilft nicht. Das bedeutet, dass eine Schleife zum Lesen so aussehen sollte:

    while (versuche_zu_lesen()) { 
        // hier ist man sicher, dass erfolgreich gelesen wurde
        verarbeite_gelesenes();
    }
    

    Das "versuche_zu_lesen" ist dann sowas wie das getline oder der Operator>>. Diese geben den Stream selbst zurück, welcher im Boolean-Kontext true ist, wenn alles in Ordnung ist und false im Fehlerfall liefert. Daher funktioniert die Schleife.

    In deinem Fall:

    while (f.getline(line, max_length-1)) { // nicht: sizeof(line), was die Größe eines Pointers ist
        translateLine(line,key,value);
        ...
    }
    

    Ich möchte aber nochmal den generellen Hinweis bekräftigen, lieber mit std::string / std::wstring zu arbeiten als mit char* - dann brauchst du auch nicht mit Pointern und Längenlimits zu hantieren. Zum zeilenweisen Lesen aus der Datei nimmst du dann std::getline (ist dann keine Member-Funktion von f). Siehe https://en.cppreference.com/w/cpp/string/basic_string/getline

    Edit: Vermutung: dein Fehler kommt daher, dass wegen sizeof(char*) = 8 (typische Größe auf 64-Bit-Systemen, aber nicht im Standard festgelegt, kann z.B. auch 4 sein) wohl kein = im String ist. Wie gesagt, nimm std::(w)string.


  • Mod

    @wob sagte in c++ *char == '=':

    Das ist ebenfalls in C++ nicht richtig. Man sollte grundsätzlich erst NACH dem Lesen / Leseversuch testen. Davor hilft nicht. Das bedeutet, dass eine Schleife zum Lesen so aussehen sollte:

    while (versuche_zu_lesen()) { 
        // hier ist man sicher, dass erfolgreich gelesen wurde
        verarbeite_gelesenes();
    }
    

    while (not eof) ist auch in Java nicht richtig. Und in keiner anderen Sprache, die ich kenne, außer Pascal. Und Pascal ist komisch.



  • @PCGirl sagte in c++ *char == '=':

    Dass in der for-Schleife sizeof(line) nicht ist, was Du suchst, wurde ja schon gesagt. Ausserdem sollte es wohl heißen:

     for (;i<...; i++, l++) {
    


  • @PCGirl
    ... und

    if (line[i] == '=')
                continue;
    

    hat zur Folge, dass l incementiert wird, d.h. value[0] wird nicht überschrieben. Und, aber das hat nix mit deinem Problem zu tun: Vermeide 'l' als Variablennamen. Da muss man immer 2mal hinschauen ('l'? '1'?'|'?)..



  • @PCGirl sagte in c++ *char == '=':

    Edit Arcoth: Code-Tags

    Wo kommt das Arcoth her?



  • @Quiche-Lorraine Was du da sagst, stimmt sicher, obwohl ich da noch keine Ahnung habe, aber dieser Teil des Quellcodes hat anfangs einwandfrei funktioniert, als ich nur ein Wort bzw. ein Zeichen (A) in der Datei hatte und dieses ausgelesen und ins Fenster implementiert habe. Sie wird auch erst nach der Methode translateLine() aufgerufen, und darin sind zwei Schleifen, die beim Debuggen ungewöhnliches Verhalten zeigen. Übrigens, ich weiß nicht, ob das relevant ist, aber ich benutze eine Fensterdatei mit einer WinMain, und auch die drei gezeigten Methoden befinden bis jetzt alle in dieser.



    • für mich ungewöhnlich.


  • @Mittagspause Das mit sizeof() habe ich inzwischen geändert und stattdessen strlen() genommen. Aber der Fehler besteht weiterhin. An den Strichpunkt am Anfang habe ich noch nicht gedacht, werde das dann ändern. Ich frage mich, ob das vielleicht eventuell Auswirkungen auf das Problem hat?



  • @Mechanics Weiß ich selber nicht. Das kommt gar nicht von mir.



  • Ich weiß, das war eine Frage an Columbo.



  • @wob Ich habe bisher char genommen, weil dem Fenster offenbar einen char bzw. wchar_t geben muss. Ich merke, dass es jetzt etwas kompliziert wird. Aber macht ja nichts, ich werde mir das ab morgen mal gründlich angucken, bis ich es genau verstanden habe. Möchte C++ weiterhin lernen, weil einen genauen Einblick in meine GUI haben will, und was den Quellcode meines Fensters angeht, habe ich inzwischen auch schon einiges verstanden.



  • @Mittagspause Wenn ich es richtig in Erinnerung habe, hatte der char key[i] den ganzen Nachmittag den Wert -51'I' -> willst du mir sagen, der int i hätte etwas damit zu tun? Ich muss sagen, wenn ja überrascht mich das, kenn sowas von Java jetzt gar nicht.



  • @Mittagspause Auch, wenn mich das in keiner Weise stresst oder nervt muss ich sagen, ich merke jetzt erst, dass C++ wirklich viel viel schwerer ist als Java. Aber das ist ja in etwa der Grund, weshalb ich es lernen will, weil ich die ganze selber bilden möchte.


  • Mod

    @PCGirl sagte in c++ *char == '=':

    @Mittagspause Auch, wenn mich das in keiner Weise stresst oder nervt muss ich sagen, ich merke jetzt erst, dass C++ wirklich viel viel schwerer ist als Java. Aber das ist ja in etwa der Grund, weshalb ich es lernen will, weil ich die ganze selber bilden möchte.

    Ich weiß ja nicht, womit du lernst, aber auf jeden Fall machst du oder dein Lehrmaterial dir das Leben unnötig schwer. Alles was dir hier im Thread erklärt wurde, was du falsch gemacht hast, wäre eigentlich gar nicht nötig gewesen. Denn das was du da machst ist ein schlechter Mischmasch aus C und Java. Technisch gesehen ist es zwar C++, aber vom Stil her halt ganz anders als vom Erfinder vorgesehen. Das ist selbstverständlich schwer und unhandlich.



  • @PCGirl sagte in c++ *char == '=':

    muss ich sagen, ich merke jetzt erst, dass C++ wirklich viel viel schwerer ist als Java.

    @manni66 sagte in c++ *char == '=':

    Warum benutzt du nicht std::string und std::wstring?



  • @manni66 Dem Fenster muss zumindest ein ein Parameter wchar_t übergeben werden, das Fenster wird hier erzeugt:HWND hwnd = CreateWindowEx(0, // extended styles
    classname.c_str(), // name: wnd 'class'
    title, // wnd title
    WS_OVERLAPPEDWINDOW, // wnd style
    desktopwidth / 4, // position:left
    desktopheight / 4, // position: top
    desktopwidth / 2, // width
    desktopheight / 2, // height
    0, // parent wnd handle
    0, // menu handle/wnd id
    hInst, // app instance
    0); // user defined info
    title ist ein wchar_t. Aber ich denke ich, werde mich mal in string und wstring und die umwandlung in wchar_t einlesen.


Log in to reply