komische Zeichen im String bei Verwendung von memcpy, strcat, strncat, strcpy und strncpy
-
Schock schrieb:
rüdiger schrieb:
Und strncpy ist eine sinnlose Wurstfunktion, die man einfach nicht nehmen sollte.
Diese Aussage hilft Menschen wie mir nur halb weiter - was mir hier im Forum schon öfters aufgfallen ist... Dass strncpy eine sinnlose Wurstfunktion ist, glaube ich einfach mal, viele von Euch haben deutlich mehr Erfahrung; aber wie sieht eine sinnvolle(re) Alternative aus?
Stimmt. Ich sollte das ein bisschen besser ausführen. strncpy kopiert in den meisten Fällen zu viel oder zu wenig \0en. Wenn die Größe des Zielstrings nicht ausreicht, dann wird der Zielstring nicht(!) nulterminiert! Wenn die Größe mehr als ausreicht, wird der Rest des Zielstrings unnötigerweise mit \0 aufgefüllt. Was die Implementierung unnötig langsam macht.
In C11 gibt es endlich strcpy_s. Das ist die sinnvollere Variante.
-
rüdiger schrieb:
Wenn die Größe mehr als ausreicht, wird der Rest des Zielstrings unnötigerweise mit \0 aufgefüllt. Was die Implementierung unnötig langsam macht.
Das ist wohl das schwächste Argument gegen strncpy.
Wichtiger ist zu wissen, dass bei Speicherbereichsüberlappung das Verhalten undefiniert ist und dass die Verwendung von Funktionen, die zusätzliche Abhängigkeiten schaffen (hier die Eventualität ob im Ergebnis nun ein gültiger (nullterminierter) String vorliegt oder nicht) nur zu Problemen führt und den Code fehleranfällig machen.
-
Wutz schrieb:
rüdiger schrieb:
Wenn die Größe mehr als ausreicht, wird der Rest des Zielstrings unnötigerweise mit \0 aufgefüllt. Was die Implementierung unnötig langsam macht.
Das ist wohl das schwächste Argument gegen strncpy.
Wichtiger ist zu wissen, dass bei Speicherbereichsüberlappung das Verhalten undefiniert ist und dass die Verwendung von Funktionen, die zusätzliche Abhängigkeiten schaffen (hier die Eventualität ob im Ergebnis nun ein gültiger (nullterminierter) String vorliegt oder nicht) nur zu Problemen führt und den Code fehleranfällig machen.Was ich erwähnt habe
-
Danke für die Erläuterungen.
-
Hallo alle miteinander,
also ich habe jetzt einmal das ganze "einfacher" versucht und es sieht sehr gut aus. Habe die Rekursion auf anraten vieler Kommentare jetzt fallen lassen und erstelle den String jetzt direkt über eine for Schleife. Das sieht folgender Maßen aus:
for (i = Min; i <= Max; i++) { char* string = malloc(sizeof(char) * (i + 1)); int j; // für meinen ersten Test habe ich einfach immer nur den 1. Buchstaben des // charSets reingeschrieben. Außerdem war das für die Fragestellung unerheblich for (j = 0; j < i; j++) string[j] = charSet[0]; string[i] = '\0'; printf("string:\t%s\n", string); free(string); }
Dies ergibt auch für Min = 2 und Max = 12 den gewünschten Ausdruck:
22
222
2222
22222
222222
2222222
22222222
222222222
2222222222
22222222222
222222222222Vieleicht könnt ihr ja nochmal drüber schauen, ob noch Fehler vorhanden sind. Ansonsten bedanke ich mich bei allen Mitwirkenden und Kommentatoren für ihre Teilnahme an meinem Problem.
Vielen Dank
mirrowwinger[Edit1] Fehler korrigiert (SeppJ)[/Edit1]
-
- sizeof(char) ist per Definition immer 1.
- Wenn du ganz paranoid bist, könntest du prüfen, ob das malloc überhaupt erfolgreich war.
string[i] ) '\0';
Bitte Code immer per Copy&Paste, nicht abtippen. Sonst finden wir nur Fehler, die gar nicht da sind und übersehen die echten Fehler.
-
Danke SeppJ,
Fehler war wirklich nur Abtippfehler (sitze an 2 Rechnern Linux und Windows). Einer mit Internet und der andere mit Linux halt
-
mirrowwinger schrieb:
Einer mit Internet und der andere mit Linux halt
Komisch, hätte ich genau anders herum erwartet
Und die Linuxkiste hat kein Netzwerk?
-
for (i = Min; i <= Max; i++) { char* string = calloc( 1, i+1 ); /* calloc = malloc + 0-Initialisierung */ int j; // für meinen ersten Test habe ich einfach immer nur den 1. Buchstaben des // charSets reingeschrieben. Außerdem war das für die Fragestellung unerheblich for (j = 0; j < i; j++) string[j] = charSet[0]; /* string[i] = '\0'; kann jetzt entfallen, weil oben calloc schon alle Zeichen mit '\0' initialisiert hat */ printf("string:\t%s\n", string); free(string); }
-
Aber warum alles mit 0 initialisieren, wenn man hinterher alle bis auf eine wieder überschreibt? Gerade bei einem so kurzem Codestück kann man sich ja sicher sein, dass hier die Nullterminierung tatsächlich richtig gesetzt wird. Und falls doch ein Programmierfehler im Code ist, dann bekommt man sowohl bei malloc als auch bei calloc einen Fehler/undefiniertes Verhalten, bloß die Art des Fehlers ist anders.
-
Zwischen malloc-Definition und 0-Terminierung läuft irgendwelcher mehr oder weniger übersichtlicher Code ab, der abstürzen oder sonstwie indifferent reagieren kann, dabei ist der String noch kein "String" was z.B. für eine Fehlerbehandlung wichtig wäre. Auch ist es sehr viel übersichtlicher, wenn man die Zusicherung der Stringeigenschaft nicht auf spätere Codeteile verschiebt, ebenso kann man im "Setting"-Codeteil von der Stringeigenschaft profitieren und vorgefertigte Funktionen benutzen, z.B. strncat statt strncpy.