backslash in String "umwandeln"



  • hallo!

    Ich habe folgenden String:

    char *str = "\\r\\n\\t\\xBC\\xad"

    und möchte, dass am ende in str folgender string gespeichert ist:

    \r\n\t\xBC\xad

    wie schaffe ich es, dass ich innerhalb des strings \\ durch \ ersetzte?

    Habs schon mit verschieben probiert, aber \\ wird ja als ein zeichen interpretiert.

    danke und lg



  • In dem String sollen also die Steuerzeichen stehen.
    Und du hast keinen Zugriff auf die Definition von str.



  • DirkB schrieb:

    In dem String sollen also die Steuerzeichen stehen.
    Und du hast keinen Zugriff auf die Definition von str.

    Steuerzeichen?

    auf die direkte definition nicht. der string komm so wie oben in die Funktion rein und soll sie wieder in der gewünschten Form verlassen...



  • nero08 schrieb:

    Steuerzeichen?

    https://de.wikipedia.org/wiki/Steuerzeichen

    Wenn du

    char *str = "\\r\\n\\t\\xBC\\xad"
    puts(str);
    

    machst, dann steht in der Konsole

    \r\n\t\xBC\xad
    

    nero08 schrieb:

    ... soll sie wieder in der gewünschten Form verlassen...

    Also, als wenn die Definition

    char rueckgabe[] = "\r\n\t\xBC\xad";
    

    wäre?

    Du möchtest die Escape-Sequenz selber umwandeln.



  • DirkB schrieb:

    nero08 schrieb:

    Steuerzeichen?

    https://de.wikipedia.org/wiki/Steuerzeichen

    Wenn du

    char *str = "\\r\\n\\t\\xBC\\xad"
    puts(str);
    

    machst, dann steht in der Konsole

    \r\n\t\xBC\xad
    

    genau in der Konsle würde es so stehen. aber ich hätte gerne, dass es am ende in einem string welchen die Funktion zurückgibt so drinsteht. Gibt es die möglichkeit, hierfür ein printf zu verwenden? snprintf hab ich versucht ohne erfolg

    DirkB schrieb:

    nero08 schrieb:

    ... soll sie wieder in der gewünschten Form verlassen...

    Also, als wenn die Definition

    char rueckgabe[] = "\r\n\t\xBC\xad";
    

    wäre?

    jap genau, so solls auschaun 🙂

    DirkB schrieb:

    Du möchtest die Escape-Sequenz selber umwandeln.



  • So eine fertige Funktion gibt es in der C-Standard-Library nicht.
    Musst du also suchen oder selber machen.

    Ist aber nicht schwer.
    Du überprüfst jedes Zeichen im String, ob es ein '\' ist.
    Wenn nein, schreibst du es in den neuen String.
    Wenn ja, schaust du nach, ob das nächste Zeichen zu deiner Auswahl r n t x gehört und behandelst es entsprechend. Das geht z.B. mit switch-case.

    Du musst dir nur überlegen, ob du im Originalstring² ändern willst oder in einen neuen String schreiben willst.

    ²Dann geht dein Beispiel nicht, weil du Stringliterale nicht verändern darfst.



  • DirkB schrieb:

    So eine fertige Funktion gibt es in der C-Standard-Library nicht.
    Musst du also suchen oder selber machen.

    Ist aber nicht schwer.
    Du überprüfst jedes Zeichen im String, ob es ein '\' ist.
    Wenn nein, schreibst du es in den neuen String.
    Wenn ja, schaust du nach, ob das nächste Zeichen zu deiner Auswahl r n t x gehört und behandelst es entsprechend. Das geht z.B. mit switch-case.

    Du musst dir nur überlegen, ob du im Originalstring² ändern willst oder in einen neuen String schreiben willst.

    ²Dann geht dein Beispiel nicht, weil du Stringliterale nicht verändern darfst.

    hm, ja an sowas hab ich auch schon gedacht, nur ergibt sich ein Problem bei x.
    Wenn ich z.B. auf \\ treffe und das nächste zeichen ist ein t, so speichere ich im neuen String \t ab, das gleiche gilt für r und n.
    Aber was mach ich, wenn das nächste Zeichen ein x ist?
    wenn ich \x speichern will, erwartet sich der compiler noch ein hex zeichen. Eine möglichkeit, dies zu lösen,wäre das übernächste Zeichen anzuschauen(kann ja nur A,B,C,D,E sein), aber geht des nicht schöner?

    danke und lg


  • Mod

    nero08 schrieb:

    Aber was mach ich, wenn das nächste Zeichen ein x ist?
    wenn ich \x speichern will, erwartet sich der compiler noch ein hex zeichen. Eine möglichkeit, dies zu lösen,wäre das übernächste Zeichen anzuschauen(kann ja nur A,B,C,D,E sein), aber geht des nicht schöner?

    😕 Irgendwie scheinst du der falschen Ansicht zu sein, der Compiler oder irgendeine Art Präprozessor wären zur Laufzeit deines Programms noch aktiv. Das ist nicht der Fall*. Du kannst in deinem Programm alles so machen, wie du es willst.

    *: Kann es sein, dass sich dadurch der ganze Sinn und Zweck deines Programms erledigt? Schreibst du dieses Programm, weil du Schwierigkeiten hast, Stringliteralen den von dir gewünschten Inhalt zu geben?

    PS: Und gültige Zeichen für Hexadezimalsequenzen in C sind übrigens nicht nur 'A', 'B', ... , 'F', sondern alles aus "abcdefABCDEF0123456789"



  • SeppJ schrieb:

    nero08 schrieb:

    Aber was mach ich, wenn das nächste Zeichen ein x ist?
    wenn ich \x speichern will, erwartet sich der compiler noch ein hex zeichen. Eine möglichkeit, dies zu lösen,wäre das übernächste Zeichen anzuschauen(kann ja nur A,B,C,D,E sein), aber geht des nicht schöner?

    😕 Irgendwie scheinst du der falschen Ansicht zu sein, der Compiler oder irgendeine Art Präprozessor wären zur Laufzeit deines Programms noch aktiv. Das ist nicht der Fall*. Du kannst in deinem Programm alles so machen, wie du es willst.

    *: Kann es sein, dass sich dadurch der ganze Sinn und Zweck deines Programms erledigt? Schreibst du dieses Programm, weil du Schwierigkeiten hast, Stringliteralen den von dir gewünschten Inhalt zu geben?

    PS: Und gültige Zeichen für Hexadezimalsequenzen in C sind übrigens nicht nur 'A', 'B', ... , 'F', sondern alles aus "abcdefABCDEF0123456789"

    naja, wenn ich z.B. meinen neuen string '\x' zuweisen möchte bekomme ich folgendes:

    error: \x used with no following hex digits
    back[j] = '\x';

    das ganze hat den sinn, eben einen string umzwandeln, siehe oben 🙂

    Ja danke die Zahlen hab ich im ersten Momen verschwitzt ;).


  • Mod

    nero08 schrieb:

    naja, wenn ich z.B. meinen neuen string '\x' zuweisen möchte bekomme ich folgendes:

    error: \x used with no following hex digits
    back[j] = '\x';

    1. Du versuchst hier, zwei Zeichen in eines zu packen, was an sich schon völliger Quatsch ist.
    2. Während du programmierst, musst du schon noch da drauf achten, dass da während der Übersetzung die Escapesequenzen umgewandelt werden. Eine Zeichenkette mit dem Inhalt "\x" müsstest du in deinem Code also als "\\x" schreiben.



  • also ich glaub wir reden aneinander vorbei, wenn ich:

    char* back = "\\x";

    schreibe und mir beim gdb den inhalt von back anzeigen lasse steht in ihm \\x, aber ich will, dass in ihm \x steht. Sehe das obige als meinen Ausgang.

    Also z.B. wie komme ich von
    char* back = "\\xAB";

    ausgehend auf einen anderen string mit

    "\xAB" als inhalt?

    lg



  • nero08 schrieb:

    naja, wenn ich z.B. meinen neuen string '\x' zuweisen möchte bekomme ich folgendes:

    Du sollst auch nicht '\x' zuweisen, sondern den Wert der sich aus der Hexzahl danach ergibt.

    Die Zahl kannst du z.B. mit strtol umwandeln. Da bekommst du dann auch gleich die Position, wo die Umwandlung gestoppt wurde.
    Oder du machst es selber. Ist ja auch nicht schwer.

    Beispiel:
    char* back = "\\x41";
    Da '\' eine Escapesequenz für \ ist, steht in dem String auch nur ein \

    char* back = "\x41";
    Hier leitet das \x die Escapesequenz für Hexdarstellung ein.
    Du bekommst als das Zeichen mit dem Hexwert 41, welches in ASCII dem 'A' entspricht.
    Daraus folgt, dass das Stringliteral "\x41" letztendlich nur ein Zeichen enthält.



  • DirkB schrieb:

    nero08 schrieb:

    naja, wenn ich z.B. meinen neuen string '\x' zuweisen möchte bekomme ich folgendes:

    Du sollst auch nicht '\x' zuweisen, sondern den Wert der sich aus der Hexzahl danach ergibt.

    Die Zahl kannst du z.B. mit strtol umwandeln. Da bekommst du dann auch gleich die Position, wo die Umwandlung gestoppt wurde.
    Oder du machst es selber. Ist ja auch nicht schwer.

    Beispiel:
    char* back = "\\x41";
    Da '\' eine Escapesequenz für \ ist, steht in dem String auch nur ein \

    char* back = "\x41";
    Hier leitet das \x die Escapesequenz für Hexdarstellung ein.
    Du bekommst als das Zeichen mit dem Hexwert 41, welches in ASCII dem 'A' entspricht.
    Daraus folgt, dass das Stringliteral "\x41" letztendlich nur ein Zeichen enthält.

    ich weiß nicht vl. bin ich auch zu blöd dafür, aber wenn ich mir beim gdb mit print back den inhalt von back anzeigen lasse, so steht dort"\\x41" und nicht "\x41".
    Wenn ich back= "\x41" hab steht wie du sagst A drin....



  • nero08 schrieb:

    ich weiß nicht vl. bin ich auch zu blöd dafür, aber wenn ich mir beim gdb mit print back den inhalt von back anzeigen lasse, so steht dort"\\x41" und nicht "\x41".
    Wenn ich back= "\x41" hab steht wie du sagst A drin....

    Und was davon willst du haben?

    Der gdb zeigt das so an, wie man es auch für den Compiler in Stringliteralen angibt. Das kann der Programmierer halt lesen und sieht so auch die nichtdruckbaren Zeichen sowie diejenigen, die für den Compiler eine besondere Bedeutung haben

    Gib das mal nicht mit dem gdb sondern mit puts(back); oder printf("%s\n", back); in der Konsole aus.
    Da siehst du das Ergebnis.

    Für deine Beispiel:
    Wenn du ein Stringliteral angibst (Text zwischen "), dann gelten für die Antworten hier auch die Escapesequenzen. Das gilt ebenso, bei Zeichen zwischen '
    "\\x41" ergibt den Text \x41.
    "\x41" ergibt den Text A



  • hm ich glaub ich hab mich in was falschem verrannt.

    der string welchen die Funktion liefern soll wird mittels strcmp mit jenem verglichen welcher rauskommen soll im testcase. Wobei der String mit welchem mein Outputverglichen wird so aussieht z.B. "\x41", aber meine Funktion könnte ja auch "A" zurückgeben, was ja kein Problem wäre für strcmp oder?

    wenn ich das recht sehe, kann strtol mit jender form "\\x41\\xAB" nicht umgehen.
    also stehe ich irgendwie stehe noch immer vor dem Problem, wie aus dem obigen string den hex wert auslesen kann. Also so, dass ich \x41 erhalte und dies dann eben umgerechnet wird...



  • nero08 schrieb:

    z.B. "\x41", aber meine Funktion könnte ja auch "A" zurückgeben,

    Das sind nur Darstellungen, damit du als Mensch das lesen kannst, bzw. du dem Compiler das Zeichen übergeben kannst. Im Programm/Speicher ist das dieselbe Darstellung.

    nero08 schrieb:

    wenn ich das recht sehe, kann strtol mit jender form "B\\x41\\xA" nicht umgehen.
    also stehe ich irgendwie stehe noch immer vor dem Problem, wie aus dem obigen string den hex wert auslesen kann. Also so, dass ich \x41 erhalte und dies dann eben umgerechnet wird...

    char *pq = ...; // Zeiger auf die Quelle
    char *pz = ...; // Zeiger auf das Ziel
    
    while (*pq) 
    {
      if (*pq == '\\')                 // ist das Zeichen ein Backslash
      { if (*(pq+1) == 'x')              // Und ist das nächste Zeichen ein x 
        { *(pz++) = strtol(pq+2, &pq, 16); // Dann ab dem übernächsten als Hexzahl wandeln
        } 
        else                             // es ist keine bekannte Escapesequenze
        { *(pz++) = *(pq++);               // dann den Backslash kopieren
          *(pz++) = *(pq++);               // und das nicht 'x' kopieren
        }
      }
      else                             // Es ist kein Backslash
      {  *(pz++) = *(pq++);               // Das Nicht-Backslash-Zeichen kopieren
      }
    }
    *pz = *pq;                         // Die '\0'
    

    ungetestet



  • hey, danke habs umgeschrieben, so dass es bei mir geht.

    aber ich bekomme interessanterweise nur teilweise korrekte resultate. 0x01 wird z.B. richtig umgewandelt. 0xCA nicht, kann es sein, dass strtol, nur für einen bestimmten bereich korrekte resultate liefert?



  • nero08 schrieb:

    kann es sein, dass strtol, nur für einen bestimmten bereich korrekte resultate liefert?

    Nein!

    Aber es kann sein, dass sich 0xca nicht in einem char speichern lässt.
    Da musst Du wohl noch mit CHAR_MIN , bzw. CHAR_MAX aus <limits.h> prüfen, ob das überhaupt ein gültiger Wert ist.



  • Wenn auf deinem System char mit Vorzeichen ( signed [c]) ist, dann ist 0xCA ein negativer Wert.

    Bei der Darstellung als int-Hexwert können da noch ein paar FF davor stehen.
    Bei der Darstellung als signed-Wert wird da -54 stehen.
    Aber das sind alles nur Darstellungen für denselben Wert.

    Welcher Wert wird denn bei dir für "\xCA" angezeigt?



  • -54 wurde gespeichert. hatte noch einen fehler bei der übergabe zum testcase, jetzt funktionierts. VIelen dank für deine Mühe!


Log in to reply