If Anweisung wird übersprungen



  • #pragma warning(disable : 4996)
    #include <cstring>
    #include <string>
    #include <iostream>
    using namespace std;

    int main() {
    char sender[100] = "... .- __. . .. .. . __. .- ...";
    char* ptr_sender = sender;
    //cin.getline(sender, sizeof(sender));

    char a[] = ".-"; 
    char e[] = ".";
    char g[] = "__.";
    char l[] = "._..";
    char r[] = "._.";
    char delimiter[] = " ";
    char* ptr;
    
    ptr = strtok(sender,delimiter);
    while (ptr != '\0') {
    	if (ptr == a) {
    		cout << 'a';
    	}
    	else if (ptr == e) {
    		cout << 'e'; 
    	}
    	else if (ptr == g) {
    		cout << 'g';
    	}
    	else if (ptr == l) {
    		cout << 'l';
    
    	}
    	else if (ptr == r) {
    		cout << 'r';
    
    	}ptr_sender++;
    	ptr = strtok(NULL, delimiter);
    }
    
    
    
    
    return 0;
    

    }

    Konkret geht es darum Morsezeichen in Buchstaben zu übersetzen und auszugeben.
    Wenn ich den De-bugger verwende, um nach Fehlern zu suchen, merke ich, dass bis zu den If-Anweisungen alles in Ordnung ist, aber die If-Anweisungen selbst dann einfach übersprungen werden.

    Diese Fehlermeldung bekomme ich außerdem:tester.cpp:20:16: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]
    while (ptr != '\0') {
    Ich habe schon im Internet gesucht, aber irgendwie bekomme ich das Problem einfach nicht gelöst. Vielleicht kann mir ja hier einer helfen. 🙂


  • Mod

    Du machst C++, nicht C. Vergiss alles mit char, cstring und Arrays. Mach alles mit std::string und iostreams. Dann löst sich dein Problem ganz von alleine.

    Außerdem ist dein Ansatz mit einzelnen Variablen für verschiedene Zeichen ja offensichtlich nicht haltbar. Wenn du ein Zeichen hinzu fügen willst, dann müsstest du eine neue Variable und eine neue if-Anweisung hinzu fügen, und dabei auch noch aufpassen, dass alles konsistent ist (also dass z.B. die Variable e auch zum Zeichen 'e' führt). Umständlich, fehleranfällig. Was du brauchst, ist eine Abbildung von Morsezeichen auf alphabetische Zeichen. Oder wie der engländer sagen würde: Eine map.



  • @Master_Su Die if-Anweisungen werden nicht übersprungen, sie sind schlicht immer unwahr.

    '\0' ist ein Zeichen und somit ein int.
    ptr ist ein Pointer auf char. Das ist etwas anderes als ìntoderchar`

    Deine Arrays a, e, g, l, r zerfallen in einen Pointer Adresse auf char und zeigen auf die Speicherstelle von dem ersten Element in dem Array.

    Beim if (ptr == a) wird jetzt geschaut, ob die Adresse auf die ptr zeigt dieselbe Adresse ist, auf die a zeigt.

    Du möchtest aber den Inhalt vegleichen. Das geht in C (denn das machst du gerade bzw. C mit cout) mit strcmp

    Achtung: strtok verändert den Inhalt von sender



  • @Master_Su sagte in If Anweisung wird übersprungen:

    Diese Fehlermeldung bekomme ich außerdem:tester.cpp:20:16: error: ISO C++ forbids comparison between pointer and integer

    Wie kannst du dann das Programm mit dem Debugger ausführen?


  • Mod

    Am Ende braucht man dann gar keine if-Anweisungen mehr, und hat eine einfach erweiterbare Tabelle von Codes, die automatisch übernommen werden.

    #include <iostream>
    #include <map>
    #include <sstream>
    #include <string>
    
    using namespace std;
    
    int main()
    {
      map<string, char> code_to_char =  // Abbildung von Morsecode zu Zeichen
        {
         {".-", 'a'},
         {".", 'e'},
         {"__.", 'g'},
         {"._..", 'l'},
         {"._.", 'r'},
        };
      char delimiter = ' ';
      stringstream input("... .- __. . .. .. . __. .- ...");  // Ein istream, wie cin, aber für vorgefertigte strings anstatt Nutzereingaben
      string current_code;
      while(getline(input, current_code, delimiter))  // Zerlege input an delimiter
        {
          cout << code_to_char[current_code];
        }
    }
    

    Derzeit noch unschön: Unbekannte Codes werden einfach ignoriert. Aber da dies bei dir im Code genauso gemacht wird, habe ich dies erst einmal übernommen. Normalerweise würde man erst versuchen, den Code in der Map zu finden (code_to_char.find(current_code)) und dann halt abhängig vom Ergebnis irgendwie sinnvoll auf nicht-vorhandene Codes reagieren.



  • @SeppJ sagte in If Anweisung wird übersprungen:

    cout << code_to_char[current_code];

    Also in 1. Näherung sowas:

    auto it = code_to_char.find(current_code);
    if (it != end(code_to_char)) 
        cout << it->second;
    else
        cout << "\nDer Morsecode " << current_code << " ist unbekannt!\n";
    


  • @wob sagte in If Anweisung wird übersprungen:

    @SeppJ sagte in If Anweisung wird übersprungen:

    cout << code_to_char[current_code];

    Also in 1. Näherung sowas:

    auto it = code_to_char.find(current_code);
    if (it != end(code_to_char)) 
        cout << it->second;
    else
        cout << "\nDer Morsecode " << current_code << " ist unbekannt!\n";
    

    mein vorschlag:

            char c = code_to_char[current_code];
            cout << (c==0 ? '?' : c);
    
    


  • @Bushmaster sagte in If Anweisung wird übersprungen:

    mein vorschlag:

            char c = code_to_char[current_code];
            cout << (c==0 ? '?' : c);
    
    

    Finde ich allgemein nicht so gut, weil der operator[] die Ursprungsmap modifiziert, wenn es den Key nicht gibt. Die Map wird mit jedem Falscheintrag unnötig größer. Das muss nicht sein.



  • Genau. Besser das alles in einen Morse en-/decoder wegkapseln.



  • @wob sagte in If Anweisung wird übersprungen:

    Finde ich allgemein nicht so gut, weil der operator[] die Ursprungsmap modifiziert, wenn es den Key nicht gibt. Die Map wird mit jedem Falscheintrag unnötig größer.

    das kapiere ich nicht. warum passiert das?



  • @Bushmaster Weil es so spezifiziert ist daß operator[]() einen key einfügt und defaultvalue-initialisiert wenn er nicht existiert? Deswegen funktioniert auch Dein c==0.

    map.access
    map.modifiers/4
    pairs.pair/16



  • @Swordfish sagte in If Anweisung wird übersprungen:

    Weil es so spezifiziert ist daß operator einen key einfügt und defaultvalue-initialisiert wenn er nicht existiert?

    bloß welcher sinn mag dahinter stecken?


  • Mod

    @Bushmaster sagte in If Anweisung wird übersprungen:

    @Swordfish sagte in If Anweisung wird übersprungen:

    Weil es so spezifiziert ist daß operator einen key einfügt und defaultvalue-initialisiert wenn er nicht existiert?

    bloß welcher sinn mag dahinter stecken?

    Damit du Zuweisungen my_map[y] = z machen kannst, ohne dass dir ein Fehler um die Ohren knallt, wenn y noch nicht drin ist.



  • @SeppJ wieso keine exception werfen? dafür sind die doch da.


  • Mod

    @Bushmaster sagte in If Anweisung wird übersprungen:

    @SeppJ wieso keine exception werfen? dafür sind die doch da.

    Liest du überhaupt?

    Damit du Zuweisungen my_map[y] = z machen kannst … wenn y noch nicht drin ist.

    !



  • @SeppJ sagte in If Anweisung wird übersprungen:

    Damit du Zuweisungen my_map[y] = z machen kannst … wenn y noch nicht drin ist.

    der nachteil ist aber, dass man bei 'falschen' lesezugriffen die map sinnlos aufbläht. so ein verhalten finde ich suboptimal. was lernen wir daraus? besser finger weg von operator[] einer std:map. es gibt ja ersatz: https://en.cppreference.com/w/cpp/container/map/at



  • @Bushmaster Deswegen gibt es bei Containern generell at() UND operator[](). at() ist immer checked, [] ohne Rücksicht auf Verluste. Ich weiß nicht was da jetzt wo ein Nachteil sein soll wenn man freie Wahl hat.



  • @Swordfish sagte in If Anweisung wird übersprungen:

    @Bushmaster Deswegen gibt es bei Containern generell at() UND operator[](). at() ist immer checked, [] ohne Rücksicht auf Verluste. Ich weiß nicht was da jetzt wo ein Nachteil sein soll wenn man freie Wahl hat.

    man kann schnell auf die nase fliegen, wenn man die dokumentation nicht aufmerksam liest. ich z.b. weiß erst seit gestern, welche nebeneffekte der [] einer map hat.

    gut, dass es dieses forum gibt.
    ich hätte [] einfach verwendet und mich gefreut. mein programm würde ein paar stunden laufen und plötzlich hätte ich dumm geguckt, wenn es wegen 'out of memory' aussteigt.



  • @Bushmaster sagte in If Anweisung wird übersprungen:

    man kann schnell auf die nase fliegen, wenn man die dokumentation nicht aufmerksam liest

    Ja. Immer.



  • @Bushmaster sagte in If Anweisung wird übersprungen:

    ich hätte [] einfach verwendet und mich gefreut

    Wahrscheinlich hättest du eher einen Complierfehler bekommen, da du mit [] lesen wolltest und dieses lesen natürlich in einer const-Funktion passiert und es keine const-Version von [] gibt. Spätestens da hättest du dann wohl die Doku gelesen.



  • @Jockelx sagte in If Anweisung wird übersprungen:

    Wahrscheinlich hättest du eher einen Complierfehler bekommen, da du mit [] lesen wolltest und dieses lesen natürlich in einer const-Funktion passiert

    ich bin keiner der sehr auf const-correctness achtet. ich hätte [] einfach 'irgendwo' lesend verwendet, unter der annahme, dass es sich wie das [] eines primitiven arrays verhält.

    insofern wäre es gut, wenn der compiler bei jedem lesenden map-zugriff mit [] eine warnung ausgibt 'possibly inflates your map - use at() instead'

    solche warnungen kenne ich von intellij-idea für java.


Anmelden zum Antworten