exception bei string = string warum????



  • Hallo,

    wie ich bereits in einem vorheringen Thema sagte, ich arbeite zur zeit an einem kleinen Key verwaltungs tool.

    Leider habe ich ein problem: es speichert immer noch nicht...

    ich habe nochmal debbugt und folgendes Festgestellt:

    Wenn das programm normal läuft, dann ist alles in butter er speichert nur nicht.
    Aber wenn ich das programm mit nem debugger öffne, dann sagt mir der debugger folgendes wenn ich einen Key eingebe:

    Nach Exception angehalten c0000005: access violation at 0x00402412: write of address 0x00923ea5
    

    Die Funktion die mir der debugger als code rausgibt, wo die exeption aftritt liegt in der _string.h:

    void _M_construct_null_aux(_CharT* __p, const __true_type&) {
         *__p = 0;   // genau diesen code hebt der debugger hervor
      }
    

    jetzt zeige ich euch mal die Funktionen und code stellen die aufgerufen werden, von der benutzer eingabe bis zum Fehler:

    // Mit den Beiden funktionen lese ich ein, was der Benutzer schreibt.
    
    void advcin::Read(bool bLower, int iNumArgs)
    {
      Clear();
    
      getline(cin, m_sAll);
    
      if(bLower)
        LowerArg();
    
      Sort(iNumArgs);
    }
    
    void advcin::Sort(int iNumArgs)
    {
      bool bQuote = false;
      int iArg = 0;
      string sTmp = "";
      for(unsigned int i = 0; i < m_sAll.length(); i++)
      {
        if(m_sAll[i] == '\"')
        {
          bQuote = !bQuote;
          if(i == (m_sAll.length() - 1))
          {
            m_saArg[iArg] = sTmp;
            sTmp = "";
            iArg++;
          }
          continue;
        }
    
        if(m_sAll[i] != ' ')
        {
          sTmp += m_sAll[i];
          if(i == (m_sAll.length() - 1))
          {
            m_saArg[iArg] = sTmp;
            sTmp = "";
            iArg++;
          }
        }
        else
        {
          if(!bQuote)
          {
            m_saArg[iArg] = sTmp;
            sTmp = "";
            iArg++;
            if(iNumArgs != 0)
              if(iArg >= iNumArgs)
                break;
    
            if(iArg >= MAX_ARGS)
              break;
          }
          else
          {
            sTmp += m_sAll[i];
            if(i == (m_sAll.length() - 1))
            {
              m_saArg[iArg] = sTmp;
              sTmp = "";
              iArg++;
            }
          }
        }
      }
    }
    
    // Das wird gemacht, wenn der Benutzer den befehl add aufruft um einen key hinzuzufügen
    
            if(CIN.GetArgError(1) != ADVCIN_ERROR_NO_ARG && CIN.GetArgError(2) != ADVCIN_ERROR_NO_ARG)
            {
              if(add(CIN.GetArgString(1), CIN.GetArgString(2)) == ERROR_EXISTS)
                cout << "FEHLER: Der Key " << CIN.GetArgString(1) << " Existiert bereits!\n\n";
              else
                cout << "Der Key wurde erfolgreich hinzugefuegt.\n\n";
    
              if(save() == ERROR_WRITE)
                cout << "FEHLER: Es konnte nicht in die Datei data\\Keys.dat geschrieben werden!\n\n";
            }
            else
              cout << "FEHLER: Falsche Parameter!\n\n";
    
    // die oben aufgerufene Funktion add
    
    int add(string sName, string sKey)
    {
      int iFree;
      bool bExist = false;
    
      for(int i = 0; i < MAX_KEYS; i++)
      {
        if(g_Keys[i] == true)
          if(g_Keys[i].IsName(sName))
          {
            bExist = true;
            break;
          }
      }
    
      if(bExist) return ERROR_EXISTS;
    
      for(int i = 0; i < MAX_KEYS; i++)
      {
        if(!g_Keys[i])
        {
          g_Keys[i].SetName(sName);    // in dieser Funktion crashd es
          g_Keys[i].SetKey(sKey);
          break;
        }
      }
    
      return OK;
    }
    
    // Die Kritische Funktion
    
    void Key::SetName(string sName)
    {
      m_bExist = true;
      m_sName = sName;// <---------- Genau hier nach/drin kommt die oben genannte exception
    }
    

    ich hoffe ich habe euch nicht mit zuviel code erschlagen.
    Ich hoffe ihr könnt mir helfen.

    schonma thx im vorraus.

    Mfg Yazoo



  • Yazoo schrieb:

    ich hoffe ich habe euch nicht mit zuviel code erschlagen.

    Im Grunde schon...
    Versuch den Code mal wirklich so weit zu reduzieren, dass nur das nötigste drinsteht. Der Code sollte compilieren und den gleichen Fehler aufweisen. Wenn man seinen Code soweit eidampft kommt man oft selbst drauf was schief läuft...

    /edit:
    soweit ich das bisher überblicken kann hast du da unten die Zuweisung innerhalb einer Methode von Key. Da die Variable an die zugewiesen wird nicht vorher deklariert wurde nehm ich an, dass es sich um ein Member von Key handelt. Leider hast du vergessen, die Definition von Key mitzugeben. Interessant wären an der Stelle die Klassendefinition und Methodendefinition von Key (also vermutlich Key.h und Key.cpp).



  • also ich habe den relewanten code sehr gekürzt indem ich die eingabe vereinfacht habe und jegliche Fehler abfang codes rausgenommen habe und das problem ist das gleiche, leider bin ich nicht auf die lösung gekommen.

    Hier der gekürzte code:

    // Das wird getan wenn der befehl add aufgerufen wird
    
    cin >> sDebugInp;
    cin >> sDebugInp2;
    add(sDebugInp, sDebugInp2);
    
    // Die FUnktion add
    
    int add(string sName, string sKey)
    {
      for(int i = 0; i < MAX_KEYS; i++)
      {
        if(!g_Keys[i])
        {
          g_Keys[i].SetName(sName);
          g_Keys[i].SetKey(sKey);
          break;
        }
      }
    
      return OK;
    }
    
    // und SetName
    
    void Key::SetName(string sName)
    {
      m_bExist = true;
      m_sName = sName;// <------ Hier crashd es immer noch
    }
    

    Ich hab keinen blasssen schimmer woran es liegen könnte 😕 😕 😕

    /edit:

    sry deinen edit habe ich zu spät gesehen

    hier Key.h:

    #ifndef KEY
    #define KEY
    
    #include <string>
    #include <fstream>
    
    using namespace std; 
    
    class Key
    {
      public:
      Key();
      Key(string, string);
      ~Key();
    
      void Delete();
    
      void SetName(string);
      void SetKey(string);
    
      string GetName() const;
      string GetKey() const;
    
      bool IsName(string);
      bool IsKey(string);
    
      bool Save(string sFile = "Keys.dat");
      bool Load(string sFile = "Keys.dat");
    
      bool operator!();
      bool operator==(bool);
      bool operator!=(bool);
    
      private:
      bool m_bExist;
      string m_sName;
      string m_sKey;
    };
    
    #endif
    

    Hier Key.cpp

    #include "key.h"
    
    Key::Key()
    {
      Delete();
    }
    
    Key::Key(string sName, string sKey)
    {
      m_bExist = true;
      m_sName = sName;
      m_sKey = sKey;
    }
    
    Key::~Key()
    {}
    
    void Key::Delete()
    {
      m_bExist = false;
      m_sName = "";
      m_sKey = "";
    }
    
    void Key::SetName(string sName)
    {
      m_bExist = true;
      m_sName = sName;
    }
    
    void Key::SetKey(string sKey)
    {
      m_bExist = true;
      m_sKey = sKey;
    }
    
    string Key::GetName() const
    {
      return m_sName;
    }
    
    string Key::GetKey() const
    {
      return m_sKey;
    }
    
    bool Key::IsName(string sName)
    {
      return m_sName == sName;
    }
    
    bool Key::IsKey(string sKey)
    {
      return m_sKey == sKey;
    }
    
    bool Key::Save(string sFile)
    {
      bool bGood;
      ofstream ofDatei(sFile.c_str(), ios::binary | ios::trunc);
    
      ofDatei.write((char *) &m_bExist, sizeof(m_bExist));
      ofDatei.write((char *) &m_sName, sizeof(m_sName));
      ofDatei.write((char *) &m_sKey, sizeof(m_sKey));
    
      bGood = ofDatei.good();
    
      ofDatei.close();
      ofDatei.clear();
    
      return bGood;
    }
    
    bool Key::Load(string sFile)
    {
      bool bGood;
      ifstream ifDatei(sFile.c_str(), ios::binary);
    
      ifDatei.read((char *) &m_bExist, sizeof(m_bExist));
      ifDatei.read((char *) &m_sName, sizeof(m_sName));
      ifDatei.read((char *) &m_sKey, sizeof(m_sKey));
    
      bGood = ifDatei.good();
    
      ifDatei.close();
      ifDatei.clear();
    
      return bGood;
    }
    
    bool Key::operator!()
    {
      return !m_bExist;
    }
    
    bool Key::operator==(bool b)
    {
      return m_bExist == b;
    }
    
    bool Key::operator!=(bool b)
    {
      return m_bExist != b;
    }
    


  • Er crasht bei einer normalen Zuweisung eines strings an an einen anderen?!

    Schau mal mit dem Debuger kurz bevor das passiert, was die beiden für Werte haben. Ich kann mir das nur schwer vorstellen.. - Probier das ganze noch ein wenig zu kürzen und ein voll lauffähiges Programm davon zu erstellen, wo der Fehler immernoch auftritt.

    Ich denke mal, dass du das auf add + eine struktur mit dem Schlüssel/Wert reduzieren kannst.



  • Hast du auch MAX_KEYS g_keys?
    Sonst könnte es sein, dass in der Add-Funktion ein Überlauf passiert.
    Du aber erst mit der Auslagerung des Strings im Heap einen Fehler bekommst!

    Gruß
    tHOMY



  • Hm ich kann im Moment nichts erkennen was auf den ersten Blick den Fehler auslösen könnte. Allerdings gibts doch einige Anmerkungen zu machen:

    1. Du hast ein using namespace std im Header stehen. Merke: Benutze NIE ein using namespace xy in einem Header. Denn jede Datei die diesen Header einbindet bindet damit die using-Direktive ein, was unter Umständen die Semantik des Codes ändern kann. Using namespace in .cpp-Dateien ist ok, wenn die using-Direktive nach allen includes steht.

    2. Viele deiner Funktionen haben einen std::string als Argument. Wenn du dieses Argument in der Funktion noch veränderst ist das evtl. ok, aber meistens vergleicht man es ja nur oder gibts an ander Funktionen weiter (die damit auch nichts anstellen), und in dem Fall nimmt mann eine const Referenz auf den String und spart somit beim Funktionsaufruf die Kopie des Strings.

    Key::Key(string const& sName, string const& sKey)
    
    1. Das Interface deiner Key-Klasse ist leicht überladen. Zum Beispiel hat sie neben den Gettern noch eine Vergleichsmethode für die einzelnen Elemente, die eigentlich unnötig ist. Folgendes ist äquivalent:
    std::string xy;
    Key k;
    k.IsName(xy); //ist der name des Keys gleich xy?
    k.GetName() == xy; //macht das selbe ohne die zusätzliche Methode
    

    Man muss immer abwägen zwischen einem zu fetten Interface und der Bequemlichekeit bei der Benutzung.
    Ein weiteres Beispiel sind der operator! und die beiden Vergleichsoperatoren mit bool. Alle drei machen im Grunde das selbe. Da wäre es evtl. angebracht, eine konvertierung nach bool zu implementieren, die die gesamte Funktionalität auf einen Griff liefert. Google evtl. mal nach "safe bool idiom"



  • Also deine Art und Weise, die std::strings zu speichern und zu laden ist bestimmt nicht im Sinne des Herren:

    ofDatei.write((char *) &m_sName, sizeof(m_sName));
    ofDatei.write((char *) &m_sKey, sizeof(m_sKey));
    
    ifDatei.read((char *) &m_sName, sizeof(m_sName));
    ifDatei.read((char *) &m_sKey, sizeof(m_sKey));
    

    Was auch immer da passiert, evtl. stürzt es nicht direkt ab, aber du hast dir da ein riesen Problem eingehandelt.
    An der Addresse von einem std::string wird erstmal nur ein int mit der Länge des Strings und ein Pointer auf den wahren String zu finden sein und evtl. halt noch mehr organisatorische Daten, der String selber auf jeden Fall nicht. Mit sizeof(std::string) wirst du damit dann auch nur die Größe der organisatorischen Daten bekommen. Wenn du strings in binärer Form rausschreiben willst (also auch nicht-lesbare Zeichen und mehrere 0's), musst du schon etwas mehr aufwand treiben.

    zB:

    void writestring_binary( std::ostream& o, std::string str ) {
        std::size_t temp = str.size();
        o.write( (const char*) &temp, sizeof( std::size_t ) );
        o.write( str.data(), str.size() );
    }
    
    void readstring_binary( std::istream& i, std::string str ) {
        std::size_t s;
        buf.read( (char*)&s, sizeof( std::size_t ) );
    
        str.clear();
        str.reserve( s );
        char c;
        for( std::size_t i=0; i<size; ++i ) {
            i.get( c );
            str += c;
        }
    }
    

    PS: Da dynamisch Speicher allozieren war bestimmt nicht die beste Idee, hab das mal ge-updatet.
    PPS: Das int kann man natürlich in dem binären fall auch nicht mit operator<< bzw. >> schreiben, weil der ja auf leerzeichen hofft.



  • Ist das so korrekt?

    o.write( (const char*) &str.size(), sizeof( std::size_t ) );
    

    Was liefert denn &str.size() eigentlich? Einen Zeiger auf die Funktion, einen Zeiger auf eine temporäre Variable oder (falls inline) einen Zeiger auf eine interne Membervariable von string?
    Mal abgesehen davon, dass string::size() den Typ std::string::size_type zurückliefert (sollte aber identisch mit size_t sein).



  • Ich hatte jetzt gehofft, dass er die addresse der temporären (rvalue)-Variable nimmt, hab das aber nicht kompiliert. Schließlich kann man doch auch const-Referenzen so übergeben, wenn ich mich recht entsinne?
    Edit: Okay, geht nicht (Wird lvalue benötigt), warum auch immer, der Wert ist doch zumindest da? Ich habe es im Code oben korrigiert.



  • Braunstein schrieb:

    Ist das so korrekt?

    o.write( (const char*) &str.size(), sizeof( std::size_t ) );
    

    Was liefert denn &str.size() eigentlich? Einen Zeiger auf die Funktion, einen Zeiger auf eine temporäre Variable oder (falls inline) einen Zeiger auf eine interne Membervariable von string?
    Mal abgesehen davon, dass string::size() den Typ std::string::size_type zurückliefert (sollte aber identisch mit size_t sein).

    Sofern std::basic_string<>::size() nicht eine Referenz auf irgendwas Internes zurückgibt (und das tut es nicht), liefert es Dir undefiniertes Verhalten. Egal, ob inline oder nicht.



  • Decimad schrieb:

    Schließlich kann man doch auch const-Referenzen so übergeben, wenn ich mich recht entsinne?

    Jein. Der einzige trick, ein temporäres Objekt etwas länger am Leben zu halten ist, es an eine const Referenz zu binden:

    Foo bar();
    
    Foo const& f = bar(); //das temporäre Ergebnis von bar wird an f gebunden
    Foo & f2 = bar(); //undefiniert, da f2 keine const Referenz ist.
    


  • pumuckl schrieb:

    Foo f2 = bar(); //undefiniert, da f2 keine const Referenz ist.
    

    Da fehlt ein '&'.



  • jup, danke, erledigt 🙂



  • Erstmal vielen dank für alle eure Verbesserungsvorschläge!!!

    Ich habe den Code etwas verändert, und der Fehler ist weg, das einzige was ich gemacht habe war dass ich die save und load funktion verändert habe und der fehler ist weg...

    also das war ein sehr seltsamer fehler.

    Leider bleibt ein Fehler: Wenn ich einen Key eingebe und speichere, dann das Prog neu starte, dann ist der Key weg, also wurde er nicht gespeichert... warum????

    hier nochmal der aktuelle code:

    Key.h:

    #ifndef KEY
    #define KEY
    
    #include <string>
    #include <fstream> 
    
    class Key
    {
      public:
      Key() {Delete();}
      Key(std::string const& sName, std::string const& sKey) : m_bExist(false), m_sName(sName), m_sKey(sKey) {}
      ~Key() {}
    
      void Delete();
    
      void SetName(std::string const& sName = "");
      void SetKey(std::string const& sKey = "");
    
      std::string GetName() const;
      std::string GetKey() const;
    
      bool IsName(std::string const&);
      bool IsKey(std::string const&);
    
      bool Save(std::string const& sFile = "Keys.dat");
      bool Load(std::string const& sFile = "Keys.dat");
    
      operator bool();
    
      private:
      void readstring_binary(std::istream&,std::string);
      void writestring_binary(std::ostream&,std::string);
    
      bool m_bExist;
      std::string m_sName;
      std::string m_sKey;
    };
    
    #endif
    

    Key.cpp

    #include "key.h"
    
    using namespace std;
    
    void Key::Delete()
    {
      m_bExist = false;
      m_sName = "";
      m_sKey = "";
    }
    
    void Key::SetName(string const& sName)
    {
      m_bExist = true;
      m_sName = sName;
    }
    
    void Key::SetKey(string const& sKey)
    {
      m_bExist = true;
      m_sKey = sKey;
    }
    
    string Key::GetName() const
    {
      return m_sName;
    }
    
    string Key::GetKey() const
    {
      return m_sKey;
    }
    
    bool Key::IsName(string const& sName)
    {
      return m_sName == sName;
    }
    
    bool Key::IsKey(string const& sKey)
    {
      return m_sKey == sKey;
    }
    
    bool Key::Save(string const& sFile)
    {
      bool bGood;
      ofstream ofDatei(sFile.c_str(), ios::binary | ios::trunc);
    
      ofDatei.write((char *) &m_bExist, sizeof(bool));
      writestring_binary(ofDatei, m_sName);
      writestring_binary(ofDatei, m_sKey);
    
      bGood = ofDatei.good();
    
      ofDatei.close();
      ofDatei.clear();
    
      return bGood;
    }
    
    bool Key::Load(string const& sFile)
    {
      bool bGood;
      ifstream ifDatei(sFile.c_str(), ios::binary);
    
      ifDatei.read((char *) &m_bExist, sizeof(bool));
      readstring_binary(ifDatei, m_sName);
      readstring_binary(ifDatei, m_sKey);
    
      bGood = ifDatei.good();
    
      ifDatei.close();
      ifDatei.clear();
    
      return bGood;
    }
    
    Key::operator bool()
    {
      return m_bExist;
    }
    
    void Key::writestring_binary( std::ostream& o, std::string str )
    {
        std::size_t temp = str.size();
        o.write( (const char*) &temp, sizeof( std::size_t ) );
        o.write( str.data(), str.size() );
    }
    
    void Key::readstring_binary( std::istream& i, std::string str )
    {
        std::size_t s;
        i.read( (char*)&s, sizeof( std::size_t ) );
    
        str.clear();
        str.reserve( s );
        char c;
        for( std::size_t n = 0; n < s; ++n )
        {
            i.get( c );
            str += c;
        }
    }
    

    und die funktion, die ich zum speichern/laden aufrufe + die relewanten deklarationen

    // Globale variablen
    Key      g_Keys[MAX_KEYS];    // MAX_KEYS ist zur zeit 126
    
    // die funktionen
    int load()
    {
      for(int i = 0; i < MAX_KEYS; i++)
      {
        if(!g_Keys[i].Load("data\\Keys.dat"))
          return ERROR_READ;
      }
    
      return OK;
    }
    
    int save()
    {
      for(int i = 0; i < MAX_KEYS; i++)
      {
        if(!g_Keys[i].Save("data\\Keys.dat"))
          return ERROR_WRITE;
      }
    
      return OK;
    }
    

    achja und ne kleine frage am rande was ist foo und was ist bar über das ihr hier redet?



  • Yazoo schrieb:

    also das war ein sehr seltsamer fehler.

    Eigentlich nicht. Ein std::string allokiert dynamisch Speicher für die Zeichenkette, die er repräsentiert. Wenn du nur das Objekt selbst so wie gehabt in seiner Binärdarstellung in eine Datei schreibst, schreibst du nur den Pointer den der String intern benutzt in die Datei, nicht aber den Inhalt des dynamisch allokierten Speichers. Beim Lesen aus der Datei bastelst du dann die binäre Repräsentation eines Strings zusammen, der schon lang nichtmehr existiert und der vor allem schon seinen Speicher freigegeben hat. Damit gehört dieser Speicher längst jemand anderem, und trotzdem hat der string-Zombie aus der Datei noch einen Pointer auf den Speicher. Sobald er drauf zugreift krachts.

    Was deinen aktuellen Code angeht: wieder etwas zu viel des Guten (die getter, setter, vergleiche usw. hätten wir nicht nochmal gebraucht), dafür fehlt das wichtigste, nämlich die main()-Funktion



  • die main ist ganz schön groß aber nagut:

    #include "key verwalter.h"
    
    Key      g_Keys[MAX_KEYS];
    bool     g_baHits[MAX_KEYS];
    
    int main()
    {
      bool bError = false;
      string sInput;
      string sChildInput;
    
      if(load() == ERROR_READ)
        cout << "FEHLER: Die Datei data\\Keys.dat konnte nicht gelesen werden!\n\n";
    
      string valid_inputs[]={"exit", "e", "add", "delete", "del", "search", "mod", "cls", "help", "h"};
      enum valid_inputs_words{exit, e, addd, delee, del, searchh, modd, clss, helpp, h};
    
      int valid_count = sizeof(valid_inputs)/sizeof(string);
    
      while(sInput != "exit" && sInput != "e")
      {
        anfang:
        do
        {
          cout << "Befehl> ";
          CIN.Read(); 
    
          if(CIN.GetArgError(0) != ADVCIN_OK)
          {
            bError = true;
            cout << "FEHLER: Fehlerhafte Eingabe!\n\n";
          }
          else
          {
            CIN.LowerArg(0);
            sInput = CIN.GetArgString(0);
            bError = false;
          }
        }while(bError == true);
    
        switch (find(valid_inputs, valid_inputs + valid_count, sInput) - valid_inputs)
        {
          case addd:
          {
            if(CIN.GetArgError(1) != ADVCIN_ERROR_NO_ARG && CIN.GetArgError(2) != ADVCIN_ERROR_NO_ARG)
            {
              if(add(CIN.GetArgString(1), CIN.GetArgString(2)) == ERROR_EXISTS)
                cout << "FEHLER: Der Key " << CIN.GetArgString(1) << " Existiert bereits!\n\n";
              else
                cout << "Der Key wurde erfolgreich hinzugefuegt.\n\n";
    
              if(save() == ERROR_WRITE)
                cout << "FEHLER: Es konnte nicht in die Datei data\\Keys.dat geschrieben werden!\n\n";
            }
            else
              cout << "FEHLER: Falsche Parameter!\n\n";
    
            break;
          }
    
          case delee:
          case del:
          {
            if(CIN.GetArgError(1) != ADVCIN_ERROR_NO_ARG)
            {
              cout << "WARNUNG: Sind sie sicher, dass sie den Key " << CIN.GetArgString(1) << " loeschen wollen? (J/N) > ";
              cin >> sChildInput;
    
              for(unsigned int i = 0; i < sChildInput.length(); ++i)
                sChildInput[i] = tolower(sChildInput[i]);
    
              if(sChildInput == "j" || sChildInput == "ja")
                if(dele(CIN.GetArgString(1)) == ERROR_NOT_FOUND)
                  cout << "FEHLER: Der Key " << CIN.GetArgString(1) << " existiert nicht!\n\n";
                else
                  cout << "Der Key wurde erfolgreich geloescht.\n\n";
    
              if(save() == ERROR_WRITE)
                cout << "FEHLER: Es konnte nicht in die Datei data\\Keys.dat geschrieben werden!\n\n";
            }
            else
              cout << "FEHLER: Falscher Parameter!\n\n";
    
            break;
          }
    
          case searchh:
          {
            if(CIN.GetArgError(1) != ADVCIN_ERROR_NO_ARG)
            {
              search(CIN.GetArgString(1));
              if(!found(g_baHits))
              {
                cout << "FEHLER: Der Key " << CIN.GetArgString(1) << " ist nicht vorhanden!\n\n";
              }
              else
              {
                for(int i = 0; i < MAX_KEYS; i++)
                {
                  if(g_baHits[i] == true)
                  {
                    cout << "Name:  " << g_Keys[i].GetName() << "\n";
                    cout << "Key:   " << g_Keys[i].GetKey() << "\n\n";
                  }
                }
              }
            }
            else
              cout << "FEHLER: Falscher Parameter!\n\n";
    
            break;
          }
    
          case clss:
          {
            cls();
            break;
          }
    
          case modd:
          {
            if(CIN.GetArgError(1) != ADVCIN_ERROR_NO_ARG && CIN.GetArgError(2) != ADVCIN_ERROR_NO_ARG && CIN.GetArgError(3) != ADVCIN_ERROR_NO_ARG)
            {
              if(mod(CIN.GetArgString(1), CIN.GetArgString(2), CIN.GetArgString(3)) == ERROR_NOT_FOUND)
                cout << "FEHLER: Der Key " << CIN.GetArgString(1) << " ist nicht vorhanden!\n\n";
              else
                cout << "Der Key wurde erfolgreich geaendert.\n\n";
    
              if(save() == ERROR_WRITE)
                cout << "FEHLER: Es konnte nicht in die Datei data\\Keys.dat geschrieben werden!\n\n";
            }
            else
              cout << "FEHLER: Falsche Parameter!\n\n";
    
            break;
          }
    
          case helpp:
          case h:
          {
            help();
            break;
          }
    
          case exit:
          case e:
          {
            break;
          }
    
          default:
          {
            cout << "\nFEHLER: Unbekannter Befehl: " << sInput << "\n\n";
          }
        }
      }
    
      if(save() == ERROR_WRITE)
      {
        cout << "FEHLER: Es konnte nicht in die Datei data\\Keys.dat geschrieben werden!\n";
        cout << "Wollen sie trotzdem beenden? (J/N) > ";
    
        cin >> sInput;
    
        if(sInput != "j" || sInput == "ja")
          goto anfang;                           // sry für die eine Spaghetti ich war zu faul noch ne schleife einzubauen
      }  
    
      return 0;
    }
    

    ich denke dann sollte ich euch auch mal über meine advcin klasse invormieren.

    Ich denke die Definition reicht:

    class advcin
    {
      public:
      advcin();
      ~advcin();
    
      void Read(bool bLower = false, int iNumArgs = 0);   // Bei iNumArgs = 0 gibt es keine beschränkung außer die Länge der m_saArg
    
      std::string GetArgString(int) const;
      int GetArgError(int) const;
    
      void LowerArg(int iArg = -1);
    
      private:
      void Sort(int);
      void Clear();
    
      std::string m_sAll;
      std::string m_saArg[MAX_ARGS];
    };
    


  • Alter Verwalter! Lesbar ist etwas anderes. Lösche doch am besten die Teile, die mit dem Problem nix zu tun haben aus deinen Code(riesen)schnipseln. Gibt es das Wort "Schnips"? hehe
    Das letzte Posting mag ich mir echt nicht durchlesen... Aber in dem davor sah es so aus, dass du in der Schleife immer die gleiche Datei öffnest, das erste Key-Value paar ausliest, die Datei schließt, wieder aufmachst, das erste Key-Value paar ausliest usw. usf. Das wolltest du so bestimmt nicht.



  • Decimad schrieb:

    Alter Verwalter! Lesbar ist etwas anderes. Lösche doch am besten die Teile, die mit dem Problem nix zu tun haben aus deinen Code(riesen)schnipseln. Gibt es das Wort "Schnips"? hehe
    Das letzte Posting mag ich mir echt nicht durchlesen... Aber in dem davor sah es so aus, dass du in der Schleife immer die gleiche Datei öffnest, das erste Key-Value paar ausliest, die Datei schließt, wieder aufmachst, das erste Key-Value paar ausliest usw. usf. Das wolltest du so bestimmt nicht.

    ............................................................ leider gibts hier keinen smilie der sich den kopf vor die wand haut!! also *BUUUMMM Kopf vordie Wand hau BBBBUUUUMMM*

    danke!!!

    ich bin echt ein idiot!!!!!!!!!!



  • so hab die sachen geändert und jetzt funktioniert es auch!!!

    thx an alle die sich die mühe gemacht haben und sich durch meinen code gewühlt haben!!!!!!

    /edit und hier nochmal die geänderten stellen:

    int load()
    {
      ifstream fI("data\\Keys.dat", ios::binary);
    
      for(int i = 0; i < MAX_KEYS; i++)
      {
        if(!g_Keys[i].Load(fI))
          return ERROR_READ;
      }
    
      fI.close();
      fI.clear();
    
      return OK;
    }
    
    int save()
    {
      ofstream fO("data\\Keys.dat", ios::binary | ios::trunc);
    
      for(int i = 0; i < MAX_KEYS; i++)
      {
        if(!g_Keys[i].Save(fO))
          return ERROR_WRITE;
      }
    
      fO.close();
      fO.clear();
    
      return OK;
    }
    
    bool Key::Save(std::ostream const& o)
    {
      bool bGood;
    
      o.write((char *) &m_bExist, sizeof(bool));
      writestring_binary(o, m_sName);
      writestring_binary(o, m_sKey);
    
      bGood = o.good();
    
      return bGood;
    }
    
    bool Key::Load(std::istream const& i)
    {
      bool bGood;
    
      i.read((char *) &m_bExist, sizeof(bool));
      readstring_binary(i, m_sName);
      readstring_binary(i, m_sKey);
    
      bGood = i.good();
    
      return bGood;
    }
    
    void Key::writestring_binary( std::ostream const& o, std::string const& str )
    {
        std::size_t temp = str.size();
        o.write( (const char*) &temp, sizeof( std::size_t ) );
        o.write( str.data(), str.size() );
    }
    
    void Key::readstring_binary( std::istream const& i, std::string& str )
    {
        std::size_t s;
        i.read( (char*)&s, sizeof( std::size_t ) );
    
        str.clear();
        str.reserve( s );
        char c;
        for( std::size_t n = 0; n < s; ++n )
        {
            i.get( c );
            str += c;
        }
    }
    


  • Freut mich 😉
    Achso - zum Thema Foo und Bar:
    http://en.wikipedia.org/wiki/Foo



  • thx


Anmelden zum Antworten