C: Problem beim Verbinden von Strings

henso

Grünschnabel
Hallo. Ich lese gerade über die Kommandozeile Wörter wie folgt ein.

Herberts-Der-Gerät:einlesekram herbert$ ./main test1 test2 test3 test4

Als Ergebnis sieht wie folgt aus.

Du hast '?t?!ßtest1test2test3test4' eingegeben

An sich genau das, was ich auch erwartet hatte. Allerdings mit einem kleinen Schönheitsfehler. Wie zum Henker bekomme ich die "?t?!ß" aus dem text weg.

Mein Code sieht wie folgt aus:

Code:
char *failureString;

...


failureCounter = 1;
failureString = malloc(strlen(argv[1]));

for( ; failureCounter < argc;  failureCounter++) {
	realloc(failureString, strlen(failureString) + strlen(argv[failureCounter]) + 1);

	strcat(failureString, argv[failureCounter]);
}

Kompiliert wird das Ganze mit:

gcc -m32 -Wall -ansi -pedantic -o ...

Kann mir jemand erklären, wie ich diesen ungewünschten Teilstring entfernen kann?

Gruß
 
strcat() ist zum Aneinanderhängen von strings.
Dein Problem tritt auf, wenn das Programm die for-Schleife betritt: failureString zeigt bereits auf reservierten Speicher und du reservierst mit realloc() noch einmal. Wieviel jedoch genau ist nicht sicher, da du strlen (failureString) beim 2.Parameter angibst, obwohl failureString auf undefinierten Speicherbereich zeigt! Für strlen() könntest du jetzt alle möglichen Werte zurückbekommen.
Außerdem willst du dann mit strcat etwas aneinanderhängen, obwohl du ja noch nichts in den Speicher geschrieben hast.
Dein Code ist sonst an sich ok, also ruf noch vor der for-Schleife strcpy() auf und KOPIER den Inhalt von argv[1] in den String (nicht strcat() beim 1.Mal verwenden!). Dann setztest du failureCounter auf 2 und kannst ganz normal mit deiner for-Schleife weitermachen:

C++:
failureCounter = 2;
failureString = malloc (strlen (argv[1]);
strcpy (failureString, argv[1]);

for (...)


Lg
 
Mir würde nur eines einfallen: Du hast deinen Speicherbereich aus Zeile 7 nicht initialisiert. Was auch immer zuvor im Speicher steht, wird als String angenommen und dein neuer String einfach hinten angehängt (Zeile 13). Dass dein Programm nicht gecrasht ist, dürfte Zufall sein, weil sich immer mal wieder irgendwo ein \0-Terminator befindet, mit dem ein String abgeschlossen wird.

Also gibt es drei Möglichkeiten dein Problem zu beheben:

a) In Zeile 8 ein
Code:
memset(failureString, 0, strlen(argv[1]))
b) (was für deinen Fall ausreichend wäre): In Zeile 8
Code:
*failureString = 0
c) in Zeile 8
Code:
strcpy(failureString, argv[1]);
und dann mit argv[2] in der Schleife weiter machen

Ich würde aber ganz anders an die Sache ran gehen: Summiere zuerst allen Längen deiner Strings auf. Hole dir dann mit malloc einen Speicherblock von sumStringLength+1 und kopiere in einer weiteren Schleife deine einzelnen String darüber (je nach gewählten Funktionen denk an die Initialisierung!). Das dürfte auch von der Performance her besser sein, als in einer Schleife realloc aufzurufen.
 
Zuletzt bearbeitet:
Edit. Funktioniert alles wie gewünscht. Hab es nun so gemacht wie du es vorgeschlagen hast. Besten dank.

Code:
for(inputCounter = 0; inputCounter < argc; inputCounter++) {
        argvLength += (strlen(argv[inputCounter]) + 2);
}

failureString = malloc(argvLength);

for(failureCounter = 0 ; failureCounter < argc;  failureCounter++) {
	strcat(failureString, argv[failureCounter]);
	strcat(failureString, " ");
}

Danke nochmal. :)
 
Zuletzt bearbeitet:
Das kann nicht funktionieren. Du setzt in Zeile 5 den Speicherblock auf eine Größe von 1. In Zeile 8 ist zudem das +1 an der falschen Stelle.

Ohne realloc:
Code:
int len = 0;
char *failureString;

for(int i = 1; i < argc; ++i)
   len += strlen(argv[i]) + 1; // +1 für jedes Element in argv. So sind Leerzeichen und das terminierende \0 mit einkalkuliert.

failureString = malloc(len);
strcpy(failureString, argv[1]);

for(int i = 2; i < argc; ++i)
{
   strcat(failureString, " ");
   strcat(failureString, argv[i]);
}

Mit realloc:
Code:
char *failureString = malloc(strlen(argv[1]) + 1);
strcpy(failureString, argv[1]);

for(int i = 0; i < argc; ++i)
{
   failureString = realloc(failureString, strlen(failureString) + 1 + strlen(argv[i]) + 1); // 1. +1 für Leerzeichen, 2. +1 für \0
   strcat(failureString, " ");
   strcat(failureString, argv[i]);
}

Hab es jetzt nicht getestet, sondern einfach nur schnell runtergeschrieben. Aber es sollte passen.

€dit: Zu langsam :D Dann ists gut, wenn es nun funktioniert ;)

€dit 2: Du hast wieder einen Fehler drin. Du hast nach malloc nicht initialisiert. Wenn direkt am Anfang deines Speicherblocks nicht \0 drin steht, dann ist das Verhalten von strcat() nicht vorhersehbar. Zudem holst du dir mehr Speicher, als du benötigst ;) +1 sollte reichen, statt +2 (wenn ich keinen Denkfehler habe)
 
Zuletzt bearbeitet:
Also momentan sieht der Kram so aus.

Code:
for(inputCounter = 0; inputCounter < argc; inputCounter++) {
	argvLength += (strlen(argv[inputCounter]) + 1);
}

failureMessage = malloc(argvLength);

{
	strcpy(failureMessage, argv[0]);
	strcat(failureMessage, " ");
}

for(failureCounter = 1 ; failureCounter < argc;  failureCounter++) {
	strcat(failureMessage, argv[failureCounter]);
	strcat(failureMessage, " ");
}

Läuft eigentlich ganz takko. Die +2 in Zeile zwei habe ich wegen dem Leerzeichen was ich am ende eines Durchlaufs noch dran tütel.
Also mit der Speicherresservierung läuft es eigentlich auch problem. Also rechne ich quasi Eingabe + Leerzeichen + .... Ne Moment. Hast recht -.-
 
Zuletzt bearbeitet:
So sollte dein Programm jetzt eigentlich funktionieren, dir fehlt nur noch eines, wenn man ganz genau geht: Du addierst die Größen der Strings zusammen und addierst immer 1 für das Leerzeichen nach den Strings beim anhängen (für das \0 brauchst du ja nichts reservieren das gehört nur an das Ende des gesamten Strings).
Dann beim reservieren müsstest du korrekterweise schreiben: malloc (argvLength +1). +1 für das abschließende \0 des gesamten Strings.

Lg
 
Oder Zeile 9 löschen und 13 mit 14 vertauschen ;)
Ansonsten muss ich ibafluss zustimmen. Aktuell hast du einen netten Buffer-Overflow drin.
 

Neue Beiträge

Zurück