(C): Grundsatzfrage zu Zeichenketten in einem Zeiger-Array
*Markus
- sonstiges
0 Edgar Ehritt0 *Markus
Hallo,
da ich beruflich bald mit C zu tun haben werde, ich aber nicht mehr so wirklich sattelfest bin, da ich lange damit nicht mehr zu tun hatte, versuche ich, meine letzten Unklarheiten zu beseitigen.
Ich habe folgendes Mini-Programm:
#define MAXLINES 10
#define MAXLENGTH 1000
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void writeLines(char *ptrarr[], int linecount);
int readLines(char *ptrarr[], int maxlines);
int getLine(char line[], int limit);
int main(void) {
int c;
int geleseneZeilen;
//Array von Zeigern auf char.
char *pointerarray[MAXLINES];
if ( (geleseneZeilen = readLines(pointerarray, MAXLINES)) > 0) {
writeLines(pointerarray, geleseneZeilen);
}
return 0;
}
void writeLines(char *ptrarr[], int linecount) {
for (int i = 0; i < linecount; i++) {
printf("%s\n", ptrarr[i]);
}
}
int readLines(char *ptrarr[], int maxlines) {
int localmax = 0;
int countedLines = 0;
char line[MAXLENGTH];
char *p;
while ( (countedLines = getLine(line, MAXLENGTH)) > 0 && localmax < MAXLINES) {
if ( (p = malloc(sizeof(line))) == NULL) {
printf("Nicht genug Speicher um den String aufzunehmen!\n");
return -1;
}
else {
strcpy(p, line);
//Hätte ich hier "line" direkt zugewiesen, wäre nichts passiert, wieso?
ptrarr[localmax++] = p;
}
}
return localmax;
}
int getLine(char line[], int limit) {
int c, i;
for (i = 0; i < limit && (c = getchar()) != EOF && c != '\n'; i++) {
line[i] = c;
}
line[i] = '\0';
return i;
}
Das Programm liest einfach Zeichenketten ein und speichert sie in einem Array von Zeiger auf char ab. In der Funktion readLines habe ich einen Vermerk gemacht. Ich wies anfangs dem Zeigerarray die einzelnen Zeilen mit ptrarr[localmax++] = line zu. Dies klappte aber nicht. Solange ich mich in der while-Schleife befand, konnte ich mir die einzelnen Zeilen in *ptarr[] ausgeben lassen. Sobald ich mich nicht mehr in der Schleife befand, wurde gar nichts mehr ausgegeben. Wieso ist das so? Ich habe nun mit malloc Platz reserviert und die Zeile zu kopieren, einen Zeiger darauf zu verweisen, und diesen Zeiger dem Zeigerarray zu übergeben. Aber wieso muss ich so vorgehen? Meiner Ansicht nach müsste es doch genügen, die Adresse der Zeile (also "line") dem Zeigerarray zu übergeben, wodurch der aktuelle Zeiger aus dem Array weiß, wo der "String" zu finden ist. Aber das ist offensichtlich nicht so. Welche Erklärung gibt es dafür?
Danke im Voraus,
Markus
Hallo Markus,
while ( (countedLines = getLine(line, MAXLENGTH)) > 0 && localmax < MAXLINES) {
genau umgedreht, macht es mehr Sinn. ;)
Meiner Ansicht nach müsste es doch genügen, die Adresse der Zeile (also "line") dem Zeigerarray zu übergeben, wodurch der aktuelle Zeiger aus dem Array weiß, wo der "String" zu finden ist. Aber das ist offensichtlich nicht so. Welche Erklärung gibt es dafür?
Ist eine Funktion abgearbeitet, werden alle Variablen, die in deren lokalen Bereich definiert wurden, gelöscht und der Speicher wird wieder freigegeben. Außerhalb von readLine() führt also ein Zugriff auf die (ehemalige) Adresse von "line" zu einem Speicherzugriffsfehler.
Aber selbst wenn Du Variable "line" global deklarierst, was machte das? Die Speicheradresse wäre dann zwar noch zur Laufzeit von writeLines() erreichbar. In Deinem Beispiel jedoch wäre nur die letzte eingegebene Zeile erreichbar, weil "line" in getLine() mit jedem erneuten Aufruf überschrieben wird. Es würde also 10 mal die Selbe Zeile ausgegeben werden.
Gruß aus Berlin!
eddi
Hallo,
Ist eine Funktion abgearbeitet, werden alle Variablen, die in deren lokalen Bereich definiert wurden, gelöscht und der Speicher wird wieder freigegeben. Außerhalb von readLine() führt also ein Zugriff auf die (ehemalige) Adresse von "line" zu einem Speicherzugriffsfehler.
Aber selbst wenn Du Variable "line" global deklarierst, was machte das? Die Speicheradresse wäre dann zwar noch zur Laufzeit von writeLines() erreichbar. In Deinem Beispiel jedoch wäre nur die letzte eingegebene Zeile erreichbar, weil "line" in getLine() mit jedem erneuten Aufruf überschrieben wird. Es würde also 10 mal die Selbe Zeile ausgegeben werden.
Vielen Dank. Da sah ich gestern wohl den Wald vor lauter Bäume nicht mehr. :)
Viele Grüße,
Markus
Rr:
Vielen Dank. Da sah ich gestern wohl den Wald vor lauter Bäume nicht mehr. :)
Ich leider auch, weil ich halb Blödsinn schrieb und mit den Gedanken noch bei PHP war. Faktisch müsstest Du immer die letzte eingegebene Zeile sehen; und den Rest mit den lokalen und globalen Deklarationen vergiss bitte wieder. ;)
Gruß aus Berlin!
eddi