Stringcat selber Programmieren



  • #include <stdio.h>
    #include <stdlib.h>
    
    char * stringcat(char *, char *);
    
    char * stringcat(char *s1, char * s2)
    {
    	char *string;
    	string = (char *) malloc(sizeof(s1) + sizeof(s2) +1); // siehe Net's post; (char*) ist ein cast, den man in C nicht braucht, wenn man von void* nach irgendwas* castet (malloc returnt void*). lass ihn weg.
    
    	int lv;
    
    	for(lv = 0; lv < sizeof(s1); lv++) // sizeof(s1) ist falsch, du willst strlen(s1) und diesen wert willst du vorher in eine variable speichern, sonst hast du O(n**2) laufzeit
    	{
    		string[lv] = s1[lv];
    	}
    	for(lv = 0; lv < sizeof(s2); lv++) // gleiches problem
    	{
    		string[lv + sizeof(s1)] = s2[lv]; // nochmal gleiches problem
    	}
    	return string; // und wer gibt den spass frei? sehr unpraktisch, wenn man sich auch noch erinnern muss, etwas zu free()n, was man nicht malloc()t hat
    }
    
    int main(void) // prima, endlich mal ein anfaenger, der "int main(void)" richtig hat
    {
    	char *string1;
    	char *string2;
    	char *s3;
    
    	printf("\nString 1 eingeben: ");
    	gets(string1); // falsch! string1 zeigt in die pampa
    	printf("\nString 2 eingeben: ");
    	gets(string2); // pampa die zweite
    
    	s3 = stringcat(&string1, &string2); // omg! die & gehoeren hier nicht hin
    
    	printf("\n\n %s", *string3); // der stern gehoert hier nicht hin
    
            // siehst du? oben habe ich ueber die stringcat funktion etwas von "spass" gesagt... mal sehn ob du drauf kommst, was ich meine
    
    	return 0;
    
    }
    


  • gets()
    ist mal ein problem:

    in C reserviert immer der caller der funktion den speicher und nie der callee (also die gecallte funktion). deshalb: gets() reserviert keinen speicher und nimmt an du haettest das schon getan.

    folglich haben wir hier undefiniertes verhalten weil gets() einfach mal dorthin schreibt wo string1 hinzeigt...

    aus dem selben grund mag ich dein strcat hat, weil eben hier ploetzlich der callee den speicher fuer den caller reserviert... das wirkt unnatuerlich. und vorallem: wann und wo wird der speicher dann wieder freigegeben werden?

    dein stringcat hat noch andere probleme:
    sizeof() liefer die die groesse des datentyps.
    char* s;
    der datentyp von s ist char* und ein char* hat idR 4 byte (haengt von der plattform etc. ab).

    was du hier willst ist strlen() der dir die laenge eines strings liefert.

    am ende musst du dann noch das null byte in den string schreiben (reserviert hast du es ja explizit ;))

    und als kleine anmerkung: mehrmale aufrufe von strlen sind nicht sehr performant...

    nun zumm aufruf deiner funktion:
    string1 und string2 sind doch schon zeiger. mit &string1 machst du einen zeiger auf diesen zeiger. das willst du aber nicht weil du den zeiger doch in stringcat garnicht anruehrst.

    printf("\n\n %s", *string3);
    mal davon abgesehen dass die variable s3 heisst 😉
    *s3 ist das objekt auf das s3 zeigt. in unserem fall nur ein buchstabe. hier wollen wir nicht dereferenzieren...

    alles in allem denke ich, dass du ein starkes verstaendnis problem mit zeigern hast. ueberleg dir am besten alles genau, und gehe noch ein paar beispiele durch. versuch rauszufinden was genau dir unklar ist und frag dann hier im forum nochmal nach. denn eine komplette erklaerung von zeigern wuerde hier jetzt den rahmen sprengen und dir vermutlich nicht weiter helfen, weil du in etwa so eine erklaerung ja schon bekommen haben wirst.

    versuch deshalb zu identifizieren was unklar ist. am besten auch ein bisschen rumspielen. und dann einfach frech fragen warum das das hier oder dort so verhaelt 🙂

    kopf hoch 🙂



  • So Danke für die Antworten,

    Habe mich im Eifer des Gefechtes wohl unklar ausgedrückt, bzw wichtiges weggelassen 😃 sorry,

    Also in der Aufgabe hieß es noch das man nichts nutzen soll was in der string.h definiert ist, damit scheidet wohl strlen aus. Was auch noch soooo unwichtig ist das ich es glatt überlesen hab ist das die beiden Strings vorgegeben sein sollten... Jaja ich weiß die Aufgaben immer genau durchlesen... Sorry mein fehler 🙂

    Jap ich habe ein derbes Problem mit Pointern 😃 damals in der Ausbildung und jetzt im Studium, wobei es jetzt schon besser geworden ist ^^.

    Also im klartext ist das totaler bullshit den ich da Programmiert habe oder?

    Werde jetzt erstmal die Suchfunktion zum Thema Pointer, Arrays und Strings bemühen 😃



  • mazeli schrieb:

    Also in der Aufgabe hieß es noch das man nichts nutzen soll was in der string.h definiert ist, damit scheidet wohl strlen aus.

    es laesst sich leicht selber implementieren.

    Also im klartext ist das totaler bullshit den ich da Programmiert habe oder?

    hart formuliert, aber leider ja.



  • #include <stdio.h>
    
    int main(void)
    {
    	int zahl, *zeiger_zahl;
    	zahl = 3;
    	zeiger_zahl = &zahl;
    
    	printf("Adresse von zeiger_zahl ist %u\n", &zeiger_zahl);
    	printf("Inhalt von zeiger_zahl ist %u\n", zeiger_zahl);
    	printf("Wert von *zeiger_zahl ist %u\n", *zeiger_zahl);
    
    	return 0;
    }
    

    So wenn wir schon bei Pointern sind, weshalb gibt der mir bei Adresse und Inhalt das gleiche aus? ist das richtig? ich mein dann wär der & Operator ja sinnlos wenns auch so geht oder?

    EDIT: Muss mich korrigieren, gibt nicht den selben wert aus aber einen sehr ähnlichen, demnach wird mit & die Adresse des Objekts auf den der Pointer zeigt ausgegeben und im zweiten printf die adresse des pointers selbst? oder?



  • mazeli schrieb:

    Muss mich korrigieren, gibt nicht den selben wert aus aber einen sehr ähnlichen, demnach wird mit & die Adresse des Objekts auf den der Pointer zeigt ausgegeben und im zweiten printf die adresse des pointers selbst? oder?

    umgekehrt.

    ein zeiger ist ein objekt. es hat einen bestimmten wert (naemlich die adresse auf den der zeiger zeigt).

    ein zeiger selber ist somit 4 bytes im speicher - diese 4 bytes beinhalten die adresse des pointee (das objekt auf das gezeigt wird).

    int i;
    int* p=&i;
    

    wenn wir davon jetzt ausgehen:
    wir haben hier also 2 objekte.

    printf("%p", p);
    //fuer adressen verwendet man %p als format specifier nicht %u
    

    das gibt das selbe aus wie

    printf("%p",&i);
    

    naemlich die adresse von dem objekt i.

    aber das 2. objekt das wir haben ist ja unser zeiger selber.
    die 4 bytes die mit der adresse von i belegt sind, muessen ja auch irgendwo im speicher stehen und haben somit selber eine adresse:

    printf("%p",&p);
    

    dies gibt etwas anderes aus als die 2 oberen codes...



  • na jetzt wird mir einiges klar 😃

    Ich danke dir,

    ps: das mit dem %u hab ich aus nem Beispiel welches ich durch google gefunden hab



  • #include <stdio.h>
    
    int strlen(char *);
    void strcat(char *, char *);
    
    void strcat(char *str1, char *str2)
    {
    	int x;
    	char *hStr;
    
    	for(x = 0; x <= strlen(*str1); x++)
    	{
    		*hStr = *str1;
                    *hStr++;
    		*str1++;
    	}
    	for(x = 0; x <= strlen(*str2); x++)
    	{
    		*hStr = *str1;
                    *hStr++;
    		*str2++;
    
    	}
    	printf("\n *str1 = %p, *str2 = %p, *hStr = %p", *str1, *str2, *hStr);
    }
    
    int strlen(char *strptr)
    {
    	int z = 0;
    
    	while(*strptr != '\0')
    	{
    		z++;
    	}
    	return z;
    }
    
    int main(void)
    {
    	char text1[50];
    	char text2[50];
    	//int x, y;
    
    	printf("Bitte zwei Woerter eingeben: ");
    	gets(text1);
    	gets(text2);
    
    	strcat(text1, text2);
    
    	return 0;
    }
    

    So habs nun nochmal neu versucht, natürlich funktioniert es nicht 😃 hoffe es ist wenigstens nicht totaler müll.

    Jetzt stellen sich mir einige Fragen,

    1. Kann ich mit gets() überhaupt ne Eingabe in das Array tätigen?
    2. Habe bei Strcat Fkt. als Übergabewerte ja char Pointer, die erwarten ja eine Adresse, wie kann ich das bei dem Array dann machen? Ein Array ist ja auch ein zeiger.
    3. Die strlen Funktion müsste eigentlich funktionieren.
    4. in der ersten for schleife zähle ich die beiden Zeiger hoch, bleibt die stelle dann bis zur zweiten schlefe gespeichert oder muss ich ihm erst sagen wo er dann weiter machen soll? also praktisch auf das ende des ersten strings ausrichten?

    Danke schonmal 😃



  • auweia...

    "char *str" ist ja ein zeiger (adresse) der auf eine ansammlung von chars zeigt.
    "*str" liefert dann den char der an dieser adresse im speicher steht.
    das gleiche waehre "str[0]".

    "strlen" erwartet einen zeiger. du uebergibst aber nur ein zeichen.
    selbst wenn das richtig waere, schiebst du diese adresse immer einen weiter (was du nicht tust, sondern nur ein zeichen) - der string wuerde damit ein zeichen kuerzer und ergibt keine sinnvolle abbruchbedingung fuer die schleife.
    innerhalb von "strlen" pruefst du mit *strptr immer nur das erste zeichen auf 0, hast also eine endlosschleife.

    du hast noch einiges zu tun 😉



  • hmm ich hab jetzt leider gar nix verstanden, sorry 😞 🙂



  • konkretes beispiel:

    so ist es:

    for(x = 0; x <= strlen(*str1); x++)
        {
            *hStr = *str1;
            *hStr++;
            *str1++;
        }
    

    so muss es:

    int l= strlen(str1);
        for(x = 0; x <= l; x++)
        {
            *hStr = *str1;
            hStr++;
            str1++;
        }
    


  • mhhh jo klingt logisch 😃



  • 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?


Anmelden zum Antworten