Stringcat selber Programmieren
-
Servus, bin gerade im Prüfungsstress und mach alte Prüfungen
aufgabe ist eine Stringcat funktion zu schreiben.
#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); // Reserviert Speicher mit der Größe von S1 + S2 + 1 Byte für Endekennung \0 int lv; for(lv = 0; lv < sizeof(s1); lv++) { string[lv] = s1[lv]; } for(lv = 0; lv < sizeof(s2); lv++) { string[lv + sizeof(s1)] = s2[lv]; } return string; } int main(void) { char *string1; char *string2; char *s3; printf("\nString 1 eingeben: "); gets(string1); printf("\nString 2 eingeben: "); gets(string2); s3 = stringcat(&string1, &string2); printf("\n\n %s", *string3); return 0; }
Die Stringcat Funktion haben wir bereits in der Vorlesung entwickelt, ist vielleicht etwas umständlich aber egal, irgendwie funktioniert da was nicht.
Also zum verständnis, die malloc funktion Reserviert (oder nicht?) Speicher in der Größe von S1 + S2 und noch 1 Byte für \0? was genau bedeutet (char*) vor malloc. Liefert malloc einen Pointer zurük der auf den String zeigt oder zeigt der String Pointer auf den reservierten Speicher? Ich check das nicht.
Pointer sind sowas von verwirrend
bei der Stringcat funktion wird ein Pointer zurückgegeben der auf den String in der Stringcat Funktion zeigt oder? zumindest soll das Laut Aufgabenstellung so sein. Aber was genau wird bei "return string" zurückgegeben? Die Adresse vom String? aber dann müsste es doch "return &string" heissen oder? und was genau ist jetzt der Fehler? laut visual studio ist der in der Zeile in welcher ich die Funktion stringcat aufrufe?
Need Backup
Hoffe es kann mir noch jemand helfen
-
mazeli schrieb:
... string = (char *) malloc(sizeof(s1) + sizeof(s2) +1); // Reserviert Speicher mit der Größe von S1 + S2 + 1 Byte für Endekennung \0 ...
sizeof() liefert die grössee eines char*, nicht die länge der strings. nimm 'strlen()'
btw: sizeof wird vom compiler ausgewertet, geht also nur bei sachen die beim compilieren schon feststehen...
-
#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.