Array einen Wert zuweisen!!
-
char eingabe[25];
char arr[9][25];
.
.
.
for(i = 0; i < 10; i++ )
{
printf("Eingabe:\n");
printf("Wort # %d \t:",i+1);
scanf("%s", eingabe);if (eingabe == 'q')
{
break;
}
else
{
eingabe = arr[i][];
}
}So ich habe das mal geändert aller dinge funktioniert das speichern im Array immer noch nicht. Ich habe ein bisschen Probleme bei der Durchführung
-
Zum einen schrieb ich etwas von strcmp.
Achte dabei auch suf due "Zuweisen von Arrays geht in C nicht mit dem =
Selbst wenn, wäre bei dir die Reihenfolge vertauscht. (es wäre Ziel=Quelle)
Für Strings ist dafür strcpy vorgesehen.
-
if (eingabe[0] == 'q') wäre korrekt um das 1. Zeichen der Eingabe zu prüfen.
Damit das wort quark auch geht
if ((eingabe[0] == 'q') && (eingabe[1] == '\n')) ...
ansonsten die daten mit strcopy ins array und
das gnu c-programming tutorial durcharbeiten so wie ich das mache..
-
Als ebenfalls C-Neuling nutze ich die Aufgabenstellung mal als Übung und als Möglichkeit, meine Lösung von den Cracks hier korrigieren lassen.
#include <stdio.h> #include <stdlib.h> #include <string.h> #define LIMIT 20 int main() { // declarations char **str = malloc(0); if (NULL == str) return EXIT_FAILURE; char tmp[LIMIT]; short i = 0, j; size_t cTmp; // read do { // read into tmp fgets(tmp, LIMIT, stdin); cTmp = strlen(tmp) - 1; // - \n // copy to str str = realloc(str, (i + 1) * sizeof(*str)); if (NULL == str) return EXIT_FAILURE; str[i] = malloc(cTmp + 1); /* + \0 */ if (NULL == str[i]) return EXIT_FAILURE; strncpy(str[i], tmp, cTmp); i++; } while (strcmp(tmp, "q\n")); // write printf("---\n"); for (j = 0; j < i; j++) printf("%s\n", str[j]); return EXIT_SUCCESS; }
-
malloc(0) ist nicht nötig.
char **str = NULL;
ist ausreichend, da realloc sich wie malloc verhält, wenn der erste Paramter NULL ist.
(str ist übrigens ein blöder Name dafür)Das -1 beim strlen ist überflüssig, da du es beim malloc wieder dazu packst.
Zudem ist kein '\n' im String, wenn du mehr als LIMIT-2 Zeichen eingibst.Das größte Problem ist aber das
strncpy
.
Du kopierst weniger Zeichen als in tmp drin sind (da ist noch das '\n' am Ende)
In diesem Fall hängt strcpy keine '\0' an den String.Eine Lösung: Mit strrchr nach dem '\n' suchen und die Fundstelle durch das '\0' ersetzen.
Ach ja, das "q" sollte wohl nicht mit abgespeichert werden.
-
Vorsicht es kann auch immer gelten (kommt auf die Implementierung an)
malloc(0) == NULL
-
Dirk, danke für den Tipp, dass realloc sich bei NULL wie malloc verhält, so wie ich das hatte, hat mir das auch nicht gefallen.
Der Nul-Byte-Fehler ist allerdings erschreckend.
Ist das ok, wenn ich einfach folgendes mache, oder ist das ein schlechter Stil oder sogar falsch?*strrchr(tmp, '\n') = '\0';
-
DirkB schrieb:
Zudem ist kein '\n' im String, wenn du mehr als LIMIT-2 Zeichen eingibst.
strrchr schrieb:
Return Value
A pointer to the last occurrence of character in str.
If the character is not found, the function returns a null pointer.Dann kannst du auch gleich
gets
nehmenNein, lass das sein. Das war ein schlechter Scherz.
-
Danke für deine Zeit und Mühe.
-
...und alle Zeichen, die ich mehr als LIMIT - 2 eingebe bleiben im Stream hängen und füllen automatisch den nächsten Wert des Arrays auf. Jürgen Wolf empfiehlt mir folgendes:
fgets(tmp, LIMIT, stdin); while (fgetc(stdin) != '\n');
Wie löst ihr sowas?
-
rednaZ schrieb:
Jürgen Wolf empfiehlt mir folgendes:
...und ich empfehle dir, dir ein anderes Buch zuzulegen. Von jemandem, der C kann. Der Code, den du da hast, wird, wenn die Zeile kurz genug ist, um vollständig in den Buffer zu gehen (also im Normalfall), die nächste Zeile ignorieren.
Was die Problemstellung angeht, so gibt es da verschiedene Herangehensweisen, abhängig davon, was für ein Verhalten du willst und wie wichtig Performance/Speicher sind. Wenn du den Rest der Zeile ignorieren willst und Performance keine Rolle spielt (das ist bei Benutzereingaben der Fall -- es steht nicht zu erwarten, dass man dir da gigabyteweise Daten in einem Tempo unterschiebt, dass du nicht mehr hinterherkommst), ist
if(fgets(buf, BUFSIZE, stdin) && buf[strlen(buf - 1)] != '\n') { while(fgetc(stdin) != '\n') ; }
eine Möglichkeit. Wobei du dann in einem Fall einen String hast, der auf '\n' endet und einmal nicht, und wobei du natürlich Benutzereingaben teilweise verlierst. Performancemäßig ist das vor allem deshalb nicht so prall, weil fgetc jedes mal den Stream lockt, aber das dürfte in deinem speziellen Fall nicht so das Problem sein.
Wenn du GNU-Funktionen verwenden kannst, gibt es in der glibc eine Funktion getline, die das Problem ziemlich hübsch mit dynamischem Speicher löst. Das sieht etwa so aus:
#include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { char *line = NULL; size_t buflen = 0; while(getline(&line, &buflen, stdin) && 0 != strcmp(line, "exit")) { puts(line); } free(line); }
getline fordert ausreichend Speicher an, um die Zeile aufzunehmen, und verwendet bei zukünftigen Durchläufen den Buffer wieder bzw. realloct sich einen größeren. Wenn du unter Linux unterwegs bist und dein Code vorläufig nicht anderswo laufen muss, ist das der bequemste Ansatz.
Ansonsten hab ich hier noch etwas alten Code rumliegen, der für den Zweck auch gehen sollte:
#include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> char *get_line(FILE *stream) { size_t const CHUNKSIZE = 128; size_t n = 0; char *buf = NULL, *pos = NULL; if(feof(stream)) return NULL; do { char *p; n += CHUNKSIZE; p = realloc(buf, n + 1); if(p == NULL) { free(buf); return NULL; } buf = p; pos = buf + n - CHUNKSIZE; if(fgets(pos, CHUNKSIZE + 1, stream) == NULL) { if(n > CHUNKSIZE && feof(stream)) { return buf; } else { free(buf); return NULL; } } } while(pos[strlen(pos) - 1] != '\n'); return buf; }
Diese Funktion erhöht nach und nach die Länge des Buffers, bis die Zeile in ihn hineinpasst. Im Gegensatz zu getline benutzt sie einen alten Buffer aber nicht wieder und lässt (wie fgets) das \n am Ende des Strings, so dass die benutzende Schleife in dem Fall beispielsweise so aussähe:
char *line; int keep_going = 1; while(keep_going && (line = get_line(stdin)) != NULL) { if(strcmp(line, "exit\n") == 0) { keep_going = 0; } else { puts(line); } free(line); // jede Zeile muss freigegeben werden, nicht nur einmal // der dauernd wiederbenutzte Buffer. }
Das ist im Vergleich zu getline suboptimal, aber wenn du keinen Zugriff auf GNU hast vertretbar.