[c++] String Problem

kickerxy123

Erfahrenes Mitglied
Hallo!

Ich habe einige selbstgeschrieben Funktionen gebaut. "Manchmal" (ich kann nicht sagen wann...) geht es auch ;)

also:

ich habe folgenden String
Code:
string readin = "[SOUND]1[VOLUME]100[FULLSCREEN]1[DIFFICULTY]2[PORT]5981[STRG_mx]D[STRG_mnx]A[STRG_my]LSHIFT[STRG_mny]RSHIFT[STRG_mz]W[STRG_mnz]S[STRG_rx]HOCH[STRG_rnx]RUNTER[STRG_ry]LINKS[STRG_rny]RECHTS[STRG_rz]O[STRG_rnz]P[STRG_zoomIn]BILDAUF[STRG_zoomOut]BILDAB[";
nun möchte ich einige der Werte verändern, dafür hab ich mir Funktionen geschrieben:
Code:
int getPosAfterWord(string str, string word)
{
       int durchlauf = 0; //anzahl der Setzungen von Startmarken
       string ergebnis = str;
     for(int i = 0; i < strlen(str.c_str()); i++)
     {
             if (str[i] != word[0]) continue;     //setzt den Startpunkt für die nächste for-Schleife
             
             for(int t = 0; t < strlen(word.c_str()); t++)
             {
                     if( str[(t+i)] != word[(t)] && word[t] != 'ä') 
                     {
                         i = t+i; //Neuen Startpunkt setzen, falls möglich(strlen)
                         durchlauf ++;
                         break;
                         }
              if( t == strlen(word.c_str())-1)
              {
                  //i speichert nun den ersten Buchstaben des Replacements!!
               return (i+strlen(word.c_str()));
            } 
             }
     }
    
return -1;  //ungültiger "a"- String
}
hoffe, dies ist nachvollziehbar... die Funktion soll also die Position in dem String nach dem Suchwort zurückliefern(Integer)
Code:
string getStringAfterWord(string str, string word)
{
     int pos = getPosAfterWord(str,word);
     string res = "";
     if(pos >=0)
     {
            while(str[pos] != '[' && str[pos] != '\0')
            {
            res += str[pos];
            pos++;
            }
            return res;
     }
     else return "-1";
}
soll mir den String nach dem Suchwort bis zur nächsten eckigen Klammer liefern
Code:
string addString(string a, int pos, string add)
{
string p = "";
for(int i = 0; i < pos; i++)
{
p+= a[i];
}
p+= add;
for(int i = pos; i < strlen(a.c_str());i++)
{
p+= a[i];
}
return p;
}
fügt hoffentlich den String add in den String a ein.
Code:
string delChar(string a,int pos)
{
       string ergebnis = "";
       for(int z = 0; z < strlen(a.c_str()); z++)
       {
               if(z != pos)
               ergebnis += a[z];
       }
  return ergebnis;
}
soll einen Char an der angegebenen Position im String löschen

Nun kommt die "eigentliche" Funktion:
Code:
string replace(string str, string rep, string new_rep) 
{

string ergebnis = str;
       int position =   getPosAfterWord(str, rep) - strlen(rep.c_str());
       if(position < 0) return "-1";
for(int i = 0; i < strlen(rep.c_str()); i++)
{
        ergebnis = delChar(ergebnis, position);
    
}
//ergebnis ist jetzt ohne "rep"

ergebnis = addString(ergebnis, position,new_rep);
//neue Passage einfügen
return ergebnis;
}

Der Aufruf erfolgt nun wie folgt:

Code:
readin = (replace(readin,getStringAfterWord(readin,"[SOUND]"),intToString((int)SET.STG_SOUND)));
readin = (replace(readin,getStringAfterWord(readin,"[FULLSCREEN]"),intToString((int)SET.STG_FULLSCREEN)));
readin =  replace(readin,getStringAfterWord(readin,"[VOLUME]"),SET.STG_VOLUME);
readin = (replace(readin,getStringAfterWord(readin,"[PORT]"),NET.NET_PORT));
readin = (replace(readin,getStringAfterWord(readin,"[STRG_mx]"),steuerung.moveX));
readin = (replace(readin,getStringAfterWord(readin,"[STRG_my]"),steuerung.moveY));
//USW....
Das Problem besteht wie gesagt darin, dass manchmal die Werte nicht ausgetauscht werden, beziehungsweise an falschen Stellen.
Ich habe keine Ahnung in welcher Funktion es schief läuft, ich hoffe ihr könnt mir helfen!

Vielen Dank!
kickerxy123



#edit: Bitte keine anderen Funktionen vorschlagen, da ich diese Funktionen auch für andere Dinge benutze, es würde mir auch helfen wenn wir vielleicht die Funktionen Step by Step überprüfen
 
Zuletzt bearbeitet:
Hi.

Ein paar Anmerkungen:

  • verwende bei der Parameterübergabe konstante Referenzen, du kopierst die Strings bei jedem Aufruf unnötigerweise umher.
  • ein std::string besitzt eine Methode size() bzw. length() - da brauchst du nicht jedesmal die Länge mit der strlength() C Funktion berechnen, das ist ja geradezu [...] schlimm

C:
i = t+i; //Neuen Startpunkt setzen, falls möglich(strlen)
Hier überspringst du womöglich einen Startpunkt.

Die Funktion könnte man auch so definieren (bis auf den Spezialfall mit dem 'ä' :confused:):
C++:
int getPosAfterWord(const string& str, const string& word)
{
  string::size_type pos = str.find(word);

  return (pos == string::npos ? -1 : pos);
}
Ähnlich lassen sich die anderen Funktionen vereinfachen. Schau in die C++ Standardbibliothek. Man muss nicht immer ein eckiges Rad erfinden, wenn es bereits ein perfekt rundes Rad gibt.

Gruß

PS: Für das Speichern und Setzen von Einstellungen ist ein String evtl. auch nicht die beste Wahl wie du evlt. gemerkt hast. Oder findest du das in irgendeiner Weise elegant was du dort für Verrenkungen zum Ändern eines Wertes machen mußt? Warum nimmst du nicht eine std::map<std::string, std::string>?
 
Zuletzt bearbeitet:
Hallo! Vielen Dank für deine Antwort! Sie hat mir sehr geholfen.
Zum einen: das mit length() und mit den konstanten Referenzen war mir nicht bewusst, ich werde es ändern.
Zum anderen: nunja.. ich erfinde eben gerne alles neu ;) Mir macht es Spaß "back to the roots" zu gehen. Mal abgesehen von Assembler ;)
Und das mit den maps ist mir völlig neu, ich habe davon noch nie etwas gehört, aber finde dieses Konstrukt gut. Ich wundere mich, warum es scheinbar relativ unbekannt ist (z.B. nicht in Büchern erwähnt wird ...).
Ich werde alles mal neu mit den maps strukturieren. Dennoch habe ich dabei ein Problem, denn ich lese die Dateien aus einer Textdatei aus und kopiere dies in einen String. Das ist dann auch wieder etwas "unschön", gibt es da bessere Methoden der Speicherung, so eine Art Tabelle (wie MySQL..), so far

vielen Dank
kickerxy123


#edit Ok ich glaub cih werde mir einmal SQlite angucken
 
Zuletzt bearbeitet:
hab mal eben zwei einfache Funktionen geschrieben, um so eine std::map zu serialisieren. Es dürfen keine Zeilenumbrüche in Schlüssel + Wert vorkommen. Schlüssel + Wert werden mit einem Doppeltpunkt getrennt, whitespace wird nicht ignoriert.
Das Beispiel ließt die Konfig von std::cin. Man kann natürlich aber einen beliebigen anderen Stream übergen, z.B. ein std::ifstream oder einen std::stringstream, wie man möchte.
Die Ausgabe erfolgt ebenfalls auf einen Stream. Mögliche Eingabe wäre z.B:
Code:
sound:1
volume:100

fullscreen:1
difficulity:2


C++:
#include <map>
#include <fstream>
#include <iostream>

typedef std::map<std::string, std::string> config_t;


/**
    Ließt die Konfiguration aus einem Eingabe-Stream und
    gibt sie zurück.
*/
config_t load( std::istream& in ) {
    config_t result;
    
    std::string line;
    while( !in.eof() ) {
        // Zeile lesen
        std::getline( in, line );
        
        // Doppeltpunkt finden
        unsigned pos = line.find( ":" );
        if( pos == std::string::npos )
            continue;
        
        std::string name = line.substr( 0, pos );
        std::string value = line.substr( pos + 1 );
        result[ name ] = value;
    }
    
    return result;
}


/**
    Schreibt die Konfiguration in einen Ausgabe-Stream
*/
void dump( const config_t& conf, std::ostream& out ) {
    config_t::const_iterator it = conf.begin();
    config_t::const_iterator end = conf.end();
    
    for( ; it != end ; ++it ) {
        out << it->first << ":" << it->second << std::endl;
    }
}



int main() {
    
    config_t conf = load( std::cin );
    
    std::cout << "fullscreen hat den Wert: " << conf[ "fullscreen" ] << std::endl;
    
    std::cout << "Gebe die Konfiguration wieder aus" << std::endl;
    dump( conf, std::cout );
}
 
Okay, danke !
Den Rest kriege ich von alleine hin! (übrigens hab ich mein Problem gelöst; es geht jetzt auch mit meinen Funktionen, es lag am Funktionsaufruf), ich werds aber vermutlich dennoch ändern, danke euch beiden
 
Zurück