Denkfehler?? -> ignorieren von zeichen



  • Hallo Leute
    ich sitze hier schon seit 4 Stunden daran um nur diese Problem zu finden (bis jetzt kein erfolg -.-)

    #define NICHTS '#'
    #define FUELLZEICHEN ' '
    #define MAUER_HORIZONTAL '|'
    #define MAUER_VERTIKAL '-'
    #define KISTE_AUSSEHEN 'o'
    #define MARKE_AUSSEHEN '~'
    #define MARKE_AUSSEHEN_BELEGT 'O'
    #define SPIELER_AUSSEHEN '*'
    
    ...
    ifstream leseDatei(KARTE_DATEI,ios::binary);
    
     string   lvl="",
              sBreite="",
              sHoehe="",
              sWelt="",
              tmp="",
              zeile="";
    
     int breiteZaehler=0,
         hoeheZaehler=-1, // damit er die erste Zeile(leerzeile) korrekt überspringt
         nummerKiste=0,
         nummerMarke=0;
    
     Kiste* _kiste=NULL;
     Marke* _marke=NULL; 
    
     vector<string> sMarkePosX,
                    sMarkePosY;
    
     leseDatei.seekg(offset);
    
     getline(leseDatei,lvl,FELDTRENNER);
     getline(leseDatei,tmp,FELDTRENNER);
     getline(leseDatei,sBreite,FELDTRENNER);
     getline(leseDatei,sHoehe,FELDTRENNER);
     getline(leseDatei,sWelt,FELDTRENNER); 
    
     breite=stringToInt(sBreite);
     hoehe =stringToInt(sHoehe);
    
     tmp="";
    
     for(unsigned int i=0;i<sWelt.size();i++)
     {
      if(!(breiteZaehler%breite)) //Zeile beendet
      {
       welt.push_back(tmp);
       tmp="";
       hoeheZaehler++;
       breiteZaehler=0;                   
      }
      switch(sWelt[i])
      {
        case FUELLZEICHEN:
        case NICHTS:   
        case MAUER_VERTIKAL:
        case MAUER_HORIZONTAL: 
             tmp+=sWelt[i];
             break;
        case SPIELER_AUSSEHEN:
             spieler= new Spieler(breiteZaehler,hoeheZaehler);
             tmp+=sWelt[i];
             break;
        case KISTE_AUSSEHEN:
             _kiste=new Kiste(breiteZaehler,hoeheZaehler,nummerKiste);
             kisten.push_back(_kiste);
             tmp+=sWelt[i];
             nummerKiste++;
             break;  
        case MARKE_AUSSEHEN:
             _marke=new Marke(breiteZaehler,hoeheZaehler,nummerMarke);
             marken.push_back(_marke);
             tmp+=sWelt[i];
             nummerMarke++;
             break;    
        case MARKE_AUSSEHEN_BELEGT: 
             _kiste=new Kiste(breiteZaehler,hoeheZaehler,nummerKiste);
             kisten.push_back(_kiste);
             _marke=new Marke(breiteZaehler,hoeheZaehler,nummerMarke);
             marken.push_back(_marke);
             tmp+=sWelt[i];
             nummerKiste++;
             nummerMarke++;
             break;
        default: breiteZaehler--;  
                 break;              
       }
       breiteZaehler++;          
     }
     welt.push_back(tmp);
    
     vector<string>::iterator it = welt.begin();
     welt.erase(it); // erste zeile entfernen -> Leerzeile
     ...
    

    KARTE_DATEI:

    1;def;8;8;
      ##### 
    ###   # 
    # o # ##
    # #  ~ #
    #    # #
    ##     #
     #*  ###
     #####  ;
    

    mein Problem -> er will einfach nicht die Newline's ignorieren -.- und ich habe keinen plassen warum -> hab schon gebrüft -> bei anderen zeichen GEHT er in den DEFAULT zweig.

    MFg



  • Hast du denn mal im Debugger nachgesehen, wohin er bei einem '\n' in der Eingabe geht? (so wie der switch() gerade aussieht, gilt es als sonstiges Zeichen)



  • ja -> wie gesagt bei sonderzeichen also wie bei windows 2 zeichen: CR/LF geht er in den default-zweig. Das merkwürdige ist aber auch das er diese 2 zeichennochmal extra in den vector "pusht" -> das heist CR und LF sind jeweils in EIN Feld.

    aber genau DIES will ich nicht begreifen -> es war bewiesen, dass er in den default zweig geht -> und trozdem scheint er es in "tmp" zu schreiben. Ich hab in den default-zweig eine ausgabe geschrieben "DEFAULT" -> und da kam wirklich bei den beiden immer default raus.



  • Rainu schrieb:

    ja -> wie gesagt bei sonderzeichen also wie bei windows 2 zeichen: CR/LF geht er in den default-zweig.

    Wenn dich das stört, solltest du einen eigenen case '\n': Zweig anlegen, der sich um die Zeilenenden kümmert.

    Das merkwürdige ist aber auch das er diese 2 zeichennochmal extra in den vector "pusht" -> das heist CR und LF sind jeweils in EIN Feld.

    Das ist nicht merkwürdig - das liegt daran, daß du die Datei als 'ios::binary' geöffnet hast (damit schaltest du die Übersetzung der systemspezifischen Zeilenumbrüche (unter Windows \r\n) in einfache C++-Umbrüche (\n) aus).



  • Wenn dich das stört, solltest du einen eigenen case '\n': Zweig anlegen, der sich um die Zeilenenden kümmert.

    ne der default zweig sollte wirklich schon alle anderen zeichen übernehmen -> da ich mit dem '\n' genau das selbe machen würde wie mit allen anderen ungewollten zeichen.

    Das ist nicht merkwürdig - das liegt daran, daß du die Datei als 'ios::binary' geöffnet hast (damit schaltest du die Übersetzung der systemspezifischen Zeilenumbrüche (unter Windows \r\n) in einfache C++-Umbrüche (\n) aus).

    mmm wenn ich aber ios::binary nicht anstelle, dann liest er die datei nicht richtig. -> anderes Thema von mir ^^

    Aber wie kann ich das nun lösen -> muss ich ein extrazweig für '\n' nehmen oder wie?

    achja -> die ist nur eine leicht veränderte vaariante zu dem was ich vorher hatte -> hab eine funktion eingebaut. Und da ging es komischer weise -.-

    ... 
     byte zeichen='-';
     string zeile="";
     byte breiteZaehler=0,
          hoeheZaehler=0;
    
     int nummerKiste=0,
         nummerMarke=0,
         _breite=0,
         _hoehe=0,
         zeichenZaehler=0;
    
     unsigned int level;
    
     Kiste* _kiste;
     Marke* _marke;
     Karte* _karte;
    
     string   lvl="",
              sBreite="",
              sHoehe="",
              sWelt="",
              tmp="";
    
     ifstream leseDatei(KARTE_DATEI,ios::binary);
     leseDatei.seekg(offset);
    
     getline(leseDatei,lvl,FELDTRENNER);
     getline(leseDatei,tmp,FELDTRENNER);
     getline(leseDatei,sBreite,FELDTRENNER);
     getline(leseDatei,sHoehe,FELDTRENNER);
     getline(leseDatei,sWelt,FELDTRENNER);
    
     _breite = stringToInt(sBreite);
     _hoehe  = stringToInt(sHoehe);
     level   = (unsigned)stringToInt(lvl); 
     breite = _breite;
     hoehe  = _hoehe;
    
     for(short int i=0;i<_hoehe;i++)
     {
      welt.push_back("");         
     }
    
     int wiederholungen= _breite * _hoehe;
    
     for(int i=0; i<wiederholungen;i++)
     {
       zeichen = sWelt[zeichenZaehler];
       if(zeichen==FUELLZEICHEN     ||
          zeichen==NICHTS           ||
          zeichen==MAUER_VERTIKAL   ||
          zeichen==MAUER_HORIZONTAL ||
          zeichen==SPIELER_AUSSEHEN ||
          zeichen==KISTE_AUSSEHEN   ||
          zeichen==MARKE_AUSSEHEN)
       {
         breiteZaehler++;
         if(!(i%_breite)) // Für jede Zeile
         {
           breiteZaehler=0;
           welt[(_hoehe-1)-hoeheZaehler]=zeile;
           hoeheZaehler++;
           zeile="";
         }
         switch(zeichen)
         {
           case FUELLZEICHEN:
           case NICHTS:   
           case MAUER_VERTIKAL:
           case MAUER_HORIZONTAL: 
                zeile+=zeichen;
                break;
           case SPIELER_AUSSEHEN:
                spieler= new Spieler(breiteZaehler,(_hoehe-1)-hoeheZaehler);
                zeile+=zeichen;
                break;
           case KISTE_AUSSEHEN:
                _kiste=new Kiste(breiteZaehler,(_hoehe-1)-hoeheZaehler,nummerKiste);
                kisten.push_back(_kiste);
                zeile+=zeichen;
                nummerKiste++;
                break; 
           case MARKE_AUSSEHEN:
                _marke = new Marke(breiteZaehler,(_hoehe-1)-hoeheZaehler,nummerMarke);
                marken.push_back(_marke);
                zeile+=zeichen;
                nummerMarke++;
                break;
          }
        }else i--;
        zeichenZaehler++;
     }
      ...
    

    diese komischen berchnungen wie ",(_hoehe-1)-hoeheZaehler" sollten euch nicht stören, ich habe diese funktion unter anderem deswegen neu geschrieben 😃



  • Rainu schrieb:

    Wenn dich das stört, solltest du einen eigenen case '\n': Zweig anlegen, der sich um die Zeilenenden kümmert.

    ne der default zweig sollte wirklich schon alle anderen zeichen übernehmen -> da ich mit dem '\n' genau das selbe machen würde wie mit allen anderen ungewollten zeichen.

    Und wo ist jetzt das Problem? Willst du nun Zeilenwechsel wie jedes andere unbekannte Zeichen verarbeiten (aka überlesen) oder willst du sie speziell behandeln?

    (*nochmal den Code überfliegt* dir ist klar, daß du bei der Bedingung "if(i%breite)..." die überlesenen Zeichen mit einbeziehst?)



  • Und wo ist jetzt das Problem? Willst du nun Zeilenwechsel wie jedes andere unbekannte Zeichen verarbeiten (aka überlesen) oder willst du sie speziell behandeln?

    überlesen will ich es

    (*nochmal den Code überfliegt* dir ist klar, daß du bei der Bedingung "if(i%breite)..." die überlesenen Zeichen mit einbeziehst?)

    ka kann sein das dieser Ablauf nicht richtig war -> wo ich diese Funktion geschrieben hatte, hatte ich schon ein paar stunden programmieren hinter mir ^^ -> das heist meine konsentration ist warscheinlich dahin geweht wurden ^^



  • Rainu schrieb:

    Und wo ist jetzt das Problem? Willst du nun Zeilenwechsel wie jedes andere unbekannte Zeichen verarbeiten (aka überlesen) oder willst du sie speziell behandeln?

    überlesen will ich es

    Das hast du doch schon hinbekommen - also wo ist das Problem?



  • ja im letzten code -> den ich nicht mehr verwende -> aber wenn ich mir das so vergleiche sehe ich bei meinem neuen code (den ich as erstes gepostet habe) keinen fehler -> das ist mein problem 😞



  • Ich glaube, so langsam durchschaue ich dein Problem:

    Rainu schrieb:

    breiteZaehler++
    if(!(breiteZaehler%breite)) //Zeile beendet 
    { 
      welt.push_back(tmp); 
      tmp=""; 
      hoeheZaehler++; 
      breiteZaehler=0;                   
    } 
    switch(zeichen)
    {
      ...
    default: breiteZaehler--;  
      break;
    }
    

    Wenn direkt nach dem letzten normalen Zeichen der Zeile ein ungültiges kam, wird breiteZaehler auf -1 dekrementiert und am Anfang des nächsten Schleifendurchlaufs wieder auf 0 erhöht - im Endeffekt greift sofort wieder die if()-Bedingung und packt dir einen leeren Eintrag in die Welt.

    Lösungsidee: Ersetzt mal die if()-Bedingung durch if(breiteZaehler==breite) , dann greift sie nur bei einer "vollen" Zeile.

    PS: Übrigens brauchst du die Variablen breiteZaehler und hoeheZaehler vermutlich nicht - du hast doch die nötigen Informationen in tmp.size() bzw. welt.size().



  • klasse -> vielen dank -> ich glaube ich hätte ohne dich noch weiter 4 stunden damit verbringen müssen xD


Anmelden zum Antworten