Char-Array nach bestimmtem Zeichen dursuchen usw.



  • Hallo alle,

    ich habe folgendes Problem:
    Ich habe eine Eingabe wie zum Beispiel

    hallo irgendwas%40anderes welt
    

    mittels sscanf haue ich mir die drei strings in jeweils ein char-array.
    Das Problem besteht nun darin, das mittlere Char-Array (nennen wir es arg2) nach dem Vorkommen eines "%"-Zeichens zu durchsuchen, die zwei darauf folgenden Zahlen (hexadezimal kodiertes Ascii-Zeichen, hier z.B. %40 = @) in einen Integer zu hauen (hier also zum Beispiel 40) und diesen Integer dann wiederum in ein Zeichen zu verwandeln (Ascii-Zeichen). Dieses Zeichen soll dann im Char-Array arg2 die drei Zeichen %40 ersetzen, so dass arg2 also am Ende lautet:

    irgendwas@anderes
    

    Hat jemand einen Vorschlag, wie ich da am geschicktesten Vorgehen könnte? Bieten sich Strings für so etwas eher an? Falls ja, gibt es für Strings auch eine entsprechende Funktion wie strcasecmp?

    Vielen Dank für jeglichen Hilfsansatz im Voraus,

    TheBrain.



  • entweder du verwendest std::find() oder Strings und deren Member find() zum suchen deiner Wunschposition, danach kannst du die nachfolgenden Zeichen ausfiltern und in der FAQ nach einer geeigneten Umwandlungsfunktion String->int suchen 😉

    (zum Ersetzen des %40 durch @ haben Strings auch ein replace()-Member)



  • Hallo, danke für die flotte Antwort.

    Wenn ich ein char Array habe

    char arg2[128];
    

    Wie kann ich nun aus zwei aufeinanderfolgenden Elementen dieses Arrays einen String bilden? Meine Versuche mittels

    116: for ... {
    117:   if(arg2[i] == '%'){
    118:     string str = arg2[i+1] + arg2[i+2];
    119:     printf("String = %s\n", str);
           }
         }
    

    scheiterten bisher klanglos:

    test.cpp:118: Fehler: ungültige Umwandlung von »int« in »const char*«
    test.cpp:118: Fehler: Argument 1 von »std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]« wird initialisiert
    test.cpp:119: Warnung: Objekte des Nicht-POD-Typs »struct std::string« können nicht über »...« übergeben werden; Aufruf wird zur Laufzeit abbrechen

    Und wie kann ich eigentlich ein Char-Array in einen String umwandeln?

    Viele Grüße,
    TheBrain



  • nimm lieber

    string arg;
    
    ... string sub=arg.substr(i+1,2);
    

    (dein Problem ist, daß erst die beiden Zeichen summiert und das Ergebnis im String gespeichert wird)

    Und für die Übergabe an printf() benötigst du sub.c_str()



  • Wenn ich deine Absicht richtig verstanden habe, wäre es eigentlich sinnvoller ( bzw. einfacher ) die ganze Eingabe mit getline() in einen String einzulesen.
    @CStoll: Hatte deinen Beitrag noch nicht gelesen...



  • Was macht denn dieses c_str() eigentlich, ich finde beim Googlen keine deutliche Erklärung oO

    Übrigens bin ich jetzt soweit:

    char str[2];
    1: str[0] = uri[i+1];
    2: str[1] = uri[i+2];
    3: // String in Integer umwandeln
    4: int hexa = atoi(str);
    5: // von hexadezimal nach dezimal umwandeln
    6: int dez = (hexa/10) * 16 + (hexa - (hexa/10)*10);
    7: printf("Hexawert = %i\n", hexa);
    

    und ich stehe schon wieder vor einem mir nicht erklärlichen Phänomen: Wenn ich Zeile 6 auskommentiere, dann ist die Ausgabe wunderbar, also z.B.

    Eingabe: hallo welt%20undso bye
    Ausgabe: Hexawert = 20

    Aber wenn ich Zeile 6 stehen lasse, dann gibt er mir aufeinmal

    Hexawert = 208

    aus, wieso? Woher kommt die 8?

    Viele Grüße,
    TheBrain



  • TheBrain schrieb:

    Was macht denn dieses c_str() eigentlich, ich finde beim Googlen keine deutliche Erklärung oO

    c_str() gibt einen (konstanten) Pointer auf die Zeichendaten des Strings zurück - damit du sie z.B. an C Bibliotheksfunktionen weitergeben kannst.

    btw, atoi berechnet einen Dezimalwert, für dich wäre wohl int "wert=strtol(str,0,16)" die richtige Umwandlung



  • Jetzt habe ich es übrigens mal mit arg2 als String versucht:

    0:  string arg2;
        ...
    1:  for(int i = 0; i <= arg2.size(); i++){
    2:    if(arg2[i] == '%'){
    3:      string str = arg2.substr(i+1,2);
    4:      i = arg2.size()+1;
    5:      stringstream strstream;
    6:      strstream << str;
    7:      int hex;
    8:      strstream >> hex;
    9:      printf("Hex = %i\n", hex);           
    10:   }            
    11: }
    

    Das Ergebnis ist ein Speicherzugriffsfehler 😞



  • Was soll denn das "i=arg2.size()+1;" bewirken?
    Zweitens liest du immer noch dezimal ein (daran ändert der Name der Variablen überhaupt nichts) - für streams mußt du vor dem Auslesen noch strstream.setf(ios::hex); aufrufen.
    Und drittens steht der Stream nach dem Einlesen am Ende des Puffers, so daß die Ausgabe bestenfalls ein eof liefern dürfte.

    Lies dir mal die FAQ zum Thema "einmal Zahl nach String und zurück" durch.



  • das i = arg2.size()+1 soll bewirken, dass die for-Schleife nach dem ersten Finden eines "%"-Zeichens nicht mehr weiterlaufen muss.

    Das mit den Strings ist mir ehrlich gesagt ein wenig zu umständlich, ich bin jetzt doch wieder auf der Char-Array-Schiene und es klappt soweit auch ganz gut:

    for(int i = 0; i <= ARG_SIZE; i++){
      if(arg2[i] == '%'){
        char str[2];
        str[0] = arg2[i+1];
        str[1] = arg2[i+2];
        int ascii = strtol(str,0,16);
        printf("Ascii-Wert = %i\n", ascii);
        i = ARG_SIZE+1;
      }            
    }
    

    Ausgabe ist dann der Dezimalwert der Ascii-Zeichen.

    So weit, so gut. Nun müsste ich diesen Dezimalwert in sein entsprechendes Ascii-Zeichen umwandeln (z.B. 97 --> 'a') und anschließend im Char-Array die Zeichen "%xx" durch dieses eine Zeichen ersetzen. Vor Letzterem graut es mir schon, da wären Strings jetzt halt echt toll. Kann ich denn ein Char-Array evtl. irgendwie in einen String konvertieren? Und gibts es in C++ bereits built-in oder bibliotheksabhängige Funktionen für das Ascii-Code-Umwandeln?
    Also mit

    printf("Ascii-Wert = %i\nAscii-Zeichen: %s\n", ascii, static_cast<char>(ascii));
    

    bekomme ich mal wieder einen Speicherzugriffsfehler ...



  • Die Schleife kannst du viel einfacher mit break beenden 😉

    Zur Ausgabe: fprintf("%c",val); gibt die ASCII-Darstellung des Zeichens aus. Und zum Zusammenbasteln bleiben dir entweder String::replace() oder du bastelst den neuen String mit strcpy und strcat zusammen.



  • Mit break kanns ja jeder *g*

    fprintf gibt es also aus, ok, danke. Und wie kann ich mir es in eine Variable ausgeben lassen?

    Kann ich strcpy bzw. strcat auf char-arrays anwenden?

    Edit:
    Habe das dekodierte Zeichen nun:

    char zeichen[1];
    sprintf(zeichen, "%c", ascii);
    printf("Ascii-Zeichen = %s\n", zeichen);
    


  • Kann ich strcpy bzw. strcat auf char-arrays anwenden?

    Klar kannst du - genau dafür wurden sie ja entwickelt 😉

    strncpy(buff,arg2,i-1);//alle Zeichen vor '%' eintragen
    // - deshalb solltest du lieber break verwenden, um aus der Schleife zu gehen
    strcat(buff,zeichen);//konvertiertes Zeichen anhängen
    strcat(buff,arg2+i+3);//alle Zeichen hinter '%xx' eintragen
    


  • Was hat das C Frickelzeug im C++ Forum zu suchen?



  • CStoll schrieb:

    strncpy(buff,arg2,i-1);//alle Zeichen vor '%' eintragen
    // - deshalb solltest du lieber break verwenden, um aus der Schleife zu gehen
    strcat(buff,zeichen);//konvertiertes Zeichen anhängen
    strcat(buff,arg2+i+3);//alle Zeichen hinter '%xx' eintragen
    

    Danke, so ist es natürlich einfacher, ich habe das mit zwei for-Schleifen gelöst gehabt ...

    Wie kann ich denn den Inhalt eines char-arrays wieder löschen, denn wenn ich mehrere EIngaben hintereinander mache, kommen immer noch Fragmente der letzten EIngabe mit dazu ... ?



  • Am einfachsten ist es wohl, hinter das Array ein '\0' einzutragen, dann stören irgendwelche Zeichen danach nicht für die weitere Verarbeitung (aber afaik machen die str..-Funktionen das sogar selber). Wenn es wirklich dringend ist, daß dort gar nichts mehr steht, füllt man: memset deinen Zeichenbereich mit Nullwerten auf.



  • Ich habe einfach ein leeres dummy-Char-Array gleicher Größe erstellt und kopiere "dessen Inhalt" dann bei jedem Neuaufruf immer erst in das arg2-array ... scheint zu klappen, ist aber sicher bad style 😉


Anmelden zum Antworten