Fragen zu String-Funktionen



  • Hallo,

    ich hätte mal ein paar Fragen zu String-Funktionen bzw. Funktion bekommt ein char Array und wandelt diesen in etwas anderem um.
    z.B.: (String soll in umgekehrter Reihenfolge ausgegeben werden aus abcd werde dcba)

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void stringReverse(char *string){
        int length = strlen(string), int_tmp;
        int_tmp = length;
        char *tmp = malloc(sizeof(length + 1));
    
        int i = 0;
        for(i = 0; i < length; i++){
            tmp[i] = string[int_tmp--];
    
            printf("%s", *tmp); //Test
        }
        tmp[length + 1] = '\0';
        strcpy(string, tmp);
        free(tmp);
    }
    
    int main()
    {
            char test[] = "abcd";
            printf("%s\n", test);
            stringReverse(test);
            printf("%s\n", test);
    
            return 0;
    }
    

    1. Warum genau wird

    tmp[i] = string[int_tmp--];
    

    nicht ausgeführt? Oder übersehe ich was?
    2. Wie löst man sowas am geschicktesten, wenn man einen String bekommt aber nichts zurückgeben darf? Also nur den Inhalt vom String verändern darf?
    Denn z.B. strcpy

    char* strcpy(char * dest_ptr, const char * src_ptr)
      	 {
      	   char* strresult = dest_ptr;
      	   if((NULL != dest_ptr) && (NULL != src_ptr))
      	   {
      	     /* Start copy src to dest */
      	     while (NULL != *src_ptr)
      	     {
      	       *dest_ptr++ = *src_ptr++;
      	     }
      	     /* put NULL termination */
      	     *dest_ptr = NULL;
      	   }
      	   return strresult;
    

    Da wird der kopierte String zurückgegeben. Aber ich darf nichts zurückgeben?

    Vielen Dank.

    werdas34



  • Deine Funktion ist viel zu kompliziert! Du brauchst hier kein malloc.

    Nachdem du die Stringlänge ermittelt hast, kannst du einfach einzelne Zeichen vertauschen: das erste mit dem letzten, das zweite mit dem vorletzten usw., solange wie das "hintere" Zeichen noch wirklich "hinter" dem vorderen liegt. Fertig.

    Was meinst du mit "wird nicht ausgeführt"?

    Dein printf ist falsch (der *).

    Achtung: bei deinem ersten tmp[i] = string[int_tmp--]; wird string[length], also '\0', ans erste Zeichen kopiert, daher sind all deine tmp-Teststrings leer.

    Aber wie gesagt, du brauchst diesen temporären Speicher nicht.



  • werdas34 schrieb:

    tmp[length + 1] = '\0';
    

    Du musst dir unbedingt nochmal den Rückgabewert von strlen und die Indizes sowie die Position von der '\0' anschauen.
    Nimm dafür mal den Leerstring "" (kein Zeichen) und ein Zeichen "a".

    werdas34 schrieb:

    Da wird der kopierte String zurückgegeben.

    Nein.
    Da wird die Adresse vom ersten Zeichen des Zielstring zurückgegeben.
    Das ist nur eine Kopie von dest_ptr (wie man auch am Code sehen kann)

    Das wird gemacht, damit man die Funktion als Paramter einer weiteren Funktion angeben kann.



  • Danke für die Antworten.

    Deine Funktion ist viel zu kompliziert! Du brauchst hier kein malloc.

    Ja, das stimmt. Ist mir auch dann aufgefallen. Jedoch üben wir zurseit malloc bei Strings zu benutzen, deshalb war es eine gute Übung. Bei mir ist es momentan egal wie effizient ein Programm ist, der Fokus liegt auf der Richtigkeit der Aufgaben.

    Was meinst du mit "wird nicht ausgeführt"?

    Das was du unten beschreibst das die Binäre Null mit reinkopiert wird. Habe nicht drangedacht, dass die binäre Null in dem Beispiel das vierte Element ist.

    Dein printf ist falsch (der *).

    Irgendetwas mit Zeigern verstehe ich nicht. Vielleciht könnt ihr mir Eselsbrücken oder so nennen, wie man sich das am besten merken kann.

    int *ptr; //Zeiger ptr zeigt auf Datentyp int
    int zahl = 7;
    ptr = &zahl; //Speicher die Adresse von zahl, so das ptr auf 7 zeigt
    *ptr = 4; //ptr wird überschrieben auf 4
    printf("%d\n", ptr); //gibt die Adresse des Pointers als Ganzzahl zurück
    printf("%d\n", *ptr); //gibt 4 aus
    printf("%p\n", ptr); //gibt Adresse in Hex aus
    

    Warum ist es dann nicht printf("%s\n", *tmp); sondern ohne dem *? Ich möchte eigentlich ja das ausgeben auf was tmp zeigt und nicht die Adresse? Oder verstehe ich da was vollkommen falsch?

    Könntet ihr mir vielleicht Tippps geben oder häufige Fehlerquellen bei String-Funktion und verkette Listen.(schreibe am Freitag einen Test)
    Mit verkette Listen meine ich:

    struct list{
       int val;
       struct list* next;
    };
    

    z.B.: Wie mir passiert ist das man sehr darunter unterscheiden muss, ob es sich um die Länge eines Strings geht oder um die Indizen eines Strings.
    Oder bei Listen, wenn man auf das drittletzte Element zugreifen möchte, dass man sich einen zweiten Pointer macht und den drei Schritte nach vorne geht.
    Oder nach free immer den Pointer auf NULL setzen.

    Wäre sehr dankbar wenn ihr mir typische (Anfänger) Fehler zu Strings und Listen mit mir teilt oder auch Tipps.



  • werdas34 schrieb:

    Warum ist es dann nicht printf("%s\n", *tmp); sondern ohne dem *? Ich möchte eigentlich ja das ausgeben auf was tmp zeigt und nicht die Adresse? Oder verstehe ich da was vollkommen falsch?

    Bei %s im Formatstring erwartet printf() einen Zeiger auf den Beginn eines C-Strings. Also

    char const * str = "Hello, World!";
    printf("%s\n", str);
    // oder:
    puts(str);
    


  • werdas34 schrieb:

    Wäre sehr dankbar wenn ihr mir typische (Anfänger) Fehler zu Strings

    In Speicherbereiche zu schreiben, deren Größe unbekannt ist.
    Ja, strcpy macht auch diesen Fehler.

    werdas34 schrieb:

    printf("%d\n", ptr); //gibt die Adresse des Pointers als Ganzzahl zurück
    

    Es wird nichts zurückgegeben, sonderen ausgegeben und auch nur der Teil des Ponters, der in einem int Platz hat. (Z.B. int 32-Bit, Pointer 64-Bit, wobei Pointer meist auch noch unsigned sind)

    Eine Eselsbrücke:

    int wert  // wert ist ein int
    int *ptr; // *ptr ist ein int (also so wie es da steht), ptr ist der Zeiger (egal ob da int* ptr; steht)
    

    werdas34 schrieb:

    Ich möchte eigentlich ja das ausgeben auf was tmp zeigt und nicht die Adresse?

    *tmp ist das erste Zeichen von tmp.
    Das ist keine Adresse mehr sondern ein char . Ein einzelnes Zeichen.



  • Da ist schon ziemlich viel falsch...
    Mal abgesehen davon, dass wie schon zuvor geschrieben, kein Speicher dynamisch angefordert werden sollte, schau dir mal dein malloc an.

    sizeof(length + 1)
    

    Welcher Wert kommt dabei heraus? Tipp: Es hat mit der Länge der Zeichenkette nichts zu tun.

    int_tmp = length;
    ...
    tmp[i] = string[int_tmp--]
    

    Wie von wob beschrieben ist der Index falsch.

    int_tmp = length;
    ...
    tmp[i] = string[--int_tmp]
    

    Ebenso bei der Nullterminierung:

    tmp[length] = '\0'; // nicht length+1
    

    Bei dem printf-Aufruf

    printf("%s", *tmp);
    

    zeigt tmp nicht auf eine nulltermierte Zeichenkette (das geschieht erst nach der Schleife). Wenn du tmp nicht dereferenzieren würdest, wäre es daher immer noch nicht richtig.
    Außerdem möchtest du nur das aktuelle Zeichen ausgeben:

    printf("%c", tmp[i]);
    // oder
    putchar(tmp[i]);
    


  • werdas34 schrieb:

    z.B.: (String soll in umgekehrter Reihenfolge ausgegeben werden aus abcd werde dcba)

    It's quite simple using recursion ...

    #include <stdio.h>
    
    void rev (char *str)
    {
        if (*str)
            rev (str+1);
        putchar (*str);
    }
    
    int main ()
    {
        rev ("abcd");
    }
    


  • Ich spendier noch Klammern ...

    #include <stdio.h>
    
    void rev (char const *str)
    {
        if (*str) {
            rev (str+1);
            putchar (*str);
        }
    }
    
    int main ()
    {
        rev ("abcd");
    }
    

Log in to reply