Stringcat selber Programmieren



  • Wo genau meinst du denn, den neuen String hinzuschreiben? Bis jetzt schreibst du den irgendwo in Speicher, der dir nicht gehört, da du kein malloc benutzt.



  • Gute frage, ich raff des jetzt alles gar nimmer 😃



  • Speicher am Anfang:
    
    Stack:  Adr:0000| ffff | ffff |      |      |      |      |      |      |      |      |
    
    Heap:   Adr:075f|      |      |      |      |      |      |      |      |      |      |
    

    1:

    char* txt;
    

    Speicher nach 1:

    txt
    Stack:  Adr:0000| ffff | ffff |      |      |      |      |      |      |      |      |
    
    Heap:   Adr:075f|      |      |      |      |      |      |      |      |      |      |
    

    2:

    txt = (char*)malloc(3);
    

    Speicher nach 2:

    txt
    Stack:  Adr:0000| 075f | ffff |      |      |      |      |      |      |      |      |
    
    Heap:   Adr:075f|      |      |      |      |      |      |      |      |      |      |
    

    3:

    txt[0] = 'a';
    txt[1] = 'y';
    

    Speicher nach 3:

    txt
    Stack:  Adr:0000| 075f | ffff |      |      |      |      |      |      |      |      |
    
    Heap:   Adr:075f|  'a' |  'y' |      |      |      |      |      |      |      |      |
    


  • Bildchen, ich weiß nicht, was du mit deinen "Ausführungen" bezwecken willst.

    Die ursprüngliche Aufgabenstellung bedeutete doch, strcat( ) aus <string.h> zu realisieren:

    #include <stdio.h>
    
    size_t string_length( const char *src )
    {
        size_t len = 0;
    
        while( *src ) {
    
            ++src;
            ++len;
        }
    
        return len;
    }
    
    char* string_copy( char *dest, const char *src )
    {
        while( *src ) {
    
            *dest = *src;
            ++dest;
            ++src;
        }
    
        *dest = '\0';
    
        return dest;
    }
    
    char* string_cat( char *dest, const char *src )
    {
        dest += string_length( dest );
    
        return string_copy( dest, src );
    }
    
    int main( )
    {
        char test[ 80 ];
    
        string_copy( test, "Hello" );
    
        printf( "%s\n", test );
        printf( "len: %u\n\n", string_length( test ) );
    
        string_cat( test, ", World!");
    
        printf( "%s\n", test );
        printf( "length: %u\n\n", string_length( test ) );
    }
    

    Greetz, Swordfish



  • size_t string_length(const char *src)
    {
        char *p = src;
        while (*p) ++p;
        return (size_t)(p - src);
    }
    
    char *string_copy(char *dest, const char *src)
    {
        char *p = dest;
        while (*p++ = *src++); // zu finden in K&R C, 1st/2nd edition; kopiert auch \0
        return dest;
    }
    


  • Swordfish schrieb:

    Bildchen, ich weiß nicht, was du mit deinen "Ausführungen" bezwecken willst.

    Zeigen, dass man nur durch das anlegen eines char pointers noch lange keinen Speicher hat in dem die Daten gespeichert werden können.



  • Achso.

    Greetz, Swordfish



  • #include <stdio.h>
    
    int string_laenge(char *);
    
    char * string_cat(char *, char *);
    
    char * string_cat(char *s1Ptr, char *s2Ptr)
    {
    	int lv, x, y;
    	char hstring[20];
    
    	x = string_laenge(s1Ptr);
    	y = string_laenge(s2Ptr);
    
    	for(lv = 0; lv <= x; lv++)
    	{
    		hstring[lv] = *s1Ptr;
    		s1Ptr++;
    	}
    	for(lv = x; lv <= (y+x); lv++)
    	{
    		hstring[lv] = *s2Ptr;
    		s2Ptr++;
    	}
    
    	//printf("\nDie beiden Strings zusammengefuegt ergeben: %s", hstring);
    
    	return hstring;
    }
    
    int string_laenge(char *sPtr)
    {
    	int i = 0;
    
    	while(*sPtr != '\0')
    	{
    		i++;
    		sPtr++;
    	}
    	return i;
    }
    
    int main(void)
    {
    	int x, y;
    	char str1[20+1];
    	char str2[20+1];
    	char *hPtr;
    
    	printf("Bitte geben Sie den ersten String ein: ");
    	gets(str1);
    	printf("\nBitte geben Sie den zweiten String ein: ");
    	gets(str2);
    
    	printf("\nString1: %s, String2: %s", str1, str2);
    
    	hPtr = string_cat(str1, str2);
    
    	printf("\n Die beiden Strings nach zusammenfuegen: %s", *hPtr);
    
    	return 0;
    }
    

    So habs nun nochmal komplett neu versucht, hat alles funktioniert als ich den zusammen gefügten String in der String_cat Funktion ausgedruckt habe.

    In der Aufgabe hieß es jedoch das die Funktion einen Char Pointer zurückliefern soll. Jetzt hab ich ja gelernt 😃 das der Arrayname ein Pointer auf das erste Element des Arrays ist. Dann dachte ich mir halt machste am schluss "return hstring", aber dann geb ich ja den Inhalt des ersten Elements zurück? also den ersten buchstaben vom string oder? muss es dann "return &hstring" heißen?



  • Ich glaub' du hasst nicht verstanden, was strcat() aus string.h des C-Standards macht.
    strcat( dest, src ) hängt src an dest an und gibt src zurück.

    Greetz, Swordfish

    PS: Siehe mein Post 6 Posts darüber.



  • ok hab sie nun umgeschrieben

    #include <stdio.h>
    
    int string_laenge(char *);
    
    char * string_cat(char *, char *);
    
    char * string_cat(char *s1Ptr, char *s2Ptr)
    {
    	int lv, x, y;
    
    	x = string_laenge(s1Ptr);
    	y = string_laenge(s2Ptr);
    
    	for(lv = 0; lv <= x; lv++)
    	{
    		s1Ptr++;
    	}
    	for(lv = x; lv <= (y+x); lv++)
    	{
    		*s1Ptr = *s2Ptr;
    		s1Ptr++;
    		s2Ptr++;
    	}
    
    	//printf("\nDie beiden Strings zusammengefuegt ergeben: %s", *s1Ptr);
    
    	return s1Ptr;
    }
    
    int string_laenge(char *sPtr)
    {
    	int i = 0;
    
    	while(*sPtr != '\0')
    	{
    		i++;
    		sPtr++;
    	}
    	return i;
    }
    
    int main(void)
    {
    	int x, y;
    	char str1[20+1];
    	char str2[20+1];
    	char *hPtr;
    
    	printf("Bitte geben Sie den ersten String ein: ");
    	gets(str1);
    	printf("\nBitte geben Sie den zweiten String ein: ");
    	gets(str2);
    
    	printf("\nString1: %s, String2: %s", str1, str2);
    
    	string_cat(str1, str2);
    
    	printf("\nNeuer String1: %s", str1);
    
    	return 0;
    }
    

    Bringt mir jetzt zumindest keine fehlermeldungmehr, aber er kopiert den zweiten string nicht an den ersten sondern gibt mir nur den ersten aus ????



  • schau dir deine 2 vorschleifen mal an:

    for(lv = 0; lv <= x; lv++)
    

    wenn in s1 zH "Hi" steht, dann liefert strlen(s1) ja 2.

    aber wie oft wird diese schleife nun ausgefuehrt?

    weiters wuerde ich die arrays groesser machen - bedenke dass in str1 ja der komplette inhalt von str2 platz haben muss...



  • ja ok er führt die schleife einmal zuviel aus, aber müsste er nicht trotzdem was hinkopieren? oder eben nicht weil nach dem ersten string nichts mehr initialisiert ist?

    bei meinem Programm oben ist das char * string_cat doch total unnütz und auch der rückgabewert oder? ich mein ich arbeite da ja mit Pointern die den string im main verändern, für was ist dann der char * rückgabewert?



  • mazeli schrieb:

    ja ok er führt die schleife einmal zuviel aus, aber müsste er nicht trotzdem was hinkopieren? oder eben nicht weil nach dem ersten string nichts mehr initialisiert ist?

    das problem dabei ist: jeder string hat ja ein null zeichen am ende.
    wenn du jetzt die string "hi" und "ho" hast, dann macht dein string cat ein
    "Hi\0Ho" daraus. und \0 zeigt ja an dass der string hier endet.

    btw, dein return ist auch noch falsch - worauf zeigt der zeiger denn den du zurueck gibst?

    bei meinem Programm oben ist das char * string_cat doch total unnütz und auch der rückgabewert oder? ich mein ich arbeite da ja mit Pointern die den string im main verändern, für was ist dann der char * rückgabewert?

    im prinzip ist das return von strcat ziemlich unnoetig.

    _aber_ manchmal kann es nett sein wenn man zB
    printf("%s",strcat(s1,s2));
    oder aehnliches machen will.

    deshalb soll strcat einen zeiger auf den target string returnen damit man ab und zu mal solche abkuerzungen schreiben kann.

    von der logik der funktion strcat her, ist das return aber nicht noetig und void return wuerde reichen (es ist quasi nur da um in manchen situationen es etwas bequemer zu haben).



  • wie müsste das return dann richtig heissen?



  • char * string_cat(char *s1Ptr, char *s2Ptr)
    {
        char *original_s1Ptr = s1Ptr;
    
        int lv, x, y;
    
        x = string_laenge(s1Ptr);
        y = string_laenge(s2Ptr);
    
        for(lv = 0; lv <= x; lv++)
        {
            s1Ptr++;
        }
        for(lv = x; lv <= (y+x); lv++)
        {
            *s1Ptr = *s2Ptr;
            s1Ptr++;
            s2Ptr++;
        }
    
        //printf("\nDie beiden Strings zusammengefuegt ergeben: %s", *s1Ptr);
    
        return original_s1Ptr;
    }
    

    Du hast jedoch oben von meiner Wenigkeit in Kooperation mit Shade eine weitaus sauberere Version bekommen.

    ich würd:

    char * string_cat(char *s1Ptr, char *s2Ptr)
    {
        char *p = s1Ptr;
    
        while( *++p );
        while( *p++ = *s2Ptr++ );
    
        return s1Ptr;
    }
    

    Greetz, Swordfish



  • Swordfish schrieb:

    char * string_cat(char *s1Ptr, char *s2Ptr)
    {
        char *p = s1Ptr;
    
        while( *++p );
        while( *p++ = *s2Ptr++ );
    
        return s1Ptr;
    }
    

    wer findet den bug?



  • Wow, den (Bug) hab ich ja gut versteckt - Hätt' ihn fast selbst nicht wiedergefunden 😉

    char * string_cat(char *s1Ptr, char *s2Ptr)
    {
        char *p = s1Ptr;
    
        while( *p ) ++p;
        while( *p++ = *s2Ptr++ );
    
        return s1Ptr;
    }
    

    Greetz, Swordfish



  • #include <stdio.h>
    
    int string_laenge(char *);
    
    char * string_cat(char *, char *);
    
    char * string_cat(char *s1Ptr, char *s2Ptr)
    {
    	int lv, x, y;
    	char *sPointer;
    
    	sPointer = s1Ptr;
    
    	x = string_laenge(s1Ptr);
    	y = string_laenge(s2Ptr);
    
    	for(lv = 0; lv < x; lv++)
    	{
    		s1Ptr++;
    	}
    	for(lv = x; lv < (y+x); lv++)
    	{
    		*s1Ptr = *s2Ptr;
    		s1Ptr++;
    		s2Ptr++;
    	}
    
    	//printf("\nDie beiden Strings zusammengefuegt ergeben: %s", *s1Ptr);
    
    	return sPointer;
    }
    
    int string_laenge(char *sPtr)
    {
    	int i = 0;
    
    	while(*sPtr != '\0')
    	{
    		i++;
    		sPtr++;
    	}
    	return i;
    }
    
    int main(void)
    {
    	int x, y;
    	char str1[40+1];
    	char str2[40+1];
    	char *hPtr;
    
    	printf("Bitte geben Sie den ersten String ein: ");
    	gets(str1);
    	printf("\nBitte geben Sie den zweiten String ein: ");
    	gets(str2);
    
    	printf("\nString1: %s, String2: %s", str1, str2);
    
    	//string_cat(str1, str2);
    
    	printf("\nNeuer String1: %s", string_cat(str1, str2));
    
    	return 0;
    }
    

    So es ist vollbracht 😃 nach den beiden strings gibt der mir zwar noch irgendwelchen müll aus aber egal, man war das ne schwere geburt 😃

    Danke euch allen,

    aber eins versteh ich noch nicht. Wieso kann ich nicht einfach den s1Ptr zurückgeben? Wieso erst noch einen Pointer auf diesen machen?

    PS: Klar ist das oben bei weitem nicht die beste Lösung, aber wenn ich eure genommen hätte, wäre der lerneffekt nicht so groß gewesen denke ich 😃

    Da fällt mir noch was ein, was zur hölle ist size_t? google find ich nix brauchbares und in meinem sogenannten c Buch für einsteiger steht auch keine Erklärung oder Definition oder sonst was.

    EDIT2: Ist ja klar das der mir müll ausgibt wenn ich keine Endekennung setze 😃



  • mazeli schrieb:

    aber eins versteh ich noch nicht. Wieso kann ich nicht einfach den s1Ptr zurückgeben? Wieso erst noch einen Pointer auf diesen machen?

    Weil du s1Ptr in deinen beiden Schleifen erhöhst und dieser logischerweise nicht mehr auf den Anfang deines zusammengestückelten Strings zeigen kann.

    mazeli schrieb:

    Da fällt mir noch was ein, was zur hölle ist size_t? google find ich nix brauchbares und in meinem sogenannten c Buch für einsteiger steht auch keine Erklärung oder Definition oder sonst was.

    size_t ist ein unsigned typ für Speichergrößen. Ist zB. immer das Resultat des sizeof( ) operators.

    Greetz, Swordfish



  • hmm klingt logisch 😃

    Also könnte ich ihn doch benutzen wenn ich den Pointer wieder runterzähle (ist shcwachsinn ok aber nur wegen dem verständniss her)

    Danke 😃


Anmelden zum Antworten