Zum Inhalt springen

dynamische Speicherverwaltung von Arrays


bAdVamp

Empfohlene Beiträge

Hallo, ich hab leider ein Problem.

Ich muss aus einer Textdatei zeilenweise Datensätze auslesen und in ein zweidimensionales Array ablegen (zur späteren Sortierung und Auswertung). Da es sich immer um andere Textdateien handelt, kann ich voerher nicht angeben, wie groß das Array wird, weiss aber dass eine Zeichenkette ca 150 Stellen hat.

Beim Aufruf in der Sortierung brauch ich allerdings beide Indizes -> datensatz[j]

Frage: Wie muss ich den Arraypointer deklarieren?

char *datensatz[150] ? :confused:

Einleseschleife:

while((datensatz=fgets(fplesen))!=EOF)

{

...

datensatz++;

}

Kann ich dann auf datensatz[5][100] zugreifen?

Oder bin ich da komplett auf'm Holzweg? :eek:

Gibt's 'ne FAQ, in der ich sowas finde. Die Beispiel-Listings arbeiten immer mit festgelegten Arrays... :(

Link zu diesem Kommentar
Auf anderen Seiten teilen

Der Zeiger soll auf ein zweidimensionales Array zeigen von dem ich den ersten Index nicht festlegen kann, nur den zweiten...Ein Datensatz soll dann mit datensatz[j] angesprochen werden können.

bis jetzt hab ich mir des so gedacht:

main (int argc, char **argv)

{

int i, x;

char *datensatz[150];

FILE *fplesen;

FILE *fpschreib;

if((fplesen=fopen(argv[1],"r"))==NULL) //Öffnen der zu lesenden Datei

{

printf("Fehler beim Oeffnen der Datei %s \n\n", argv[1]);

getche();

goto Ende; //Abbruch

}

else

{

if((fpschreib=fopen(argv[2],"a"))==NULL) //Öffnen der Ausgabedatei

{

printf("Fehler beim Oeffnen der Zieldatei %s \n\n", argv[2]);

getche();

goto Ende; //Abbruch

}

else

{

if((datensatz=malloc(104857600))==NULL)

{

printf("Fehler: mangelnder Speicherplatz!\n\n");

getche();

goto Ende; //Abbruch

}

else

{

//----------AUSLESEN UND AUSGEBEN DER DATEIEN-----------------------------------------------//

while((datensatz=fgets(fplesen))!=EOF)

{

...

if(datensatz[j]='\t')

{

}

}

}

}

}

fcloseall();

Ende:;

}

Kann ich das Array so als zweidimensionales ansprechen? Erkennt "C" was ich will?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Also besser gesagt, soll der Zeiger eigentlich nur helfen, die Datensätze(Strings) die aus einer Textdatei zeilenweise ausgelesen werden, in ein Array zu stopfen, wobei der erste Index den Datensatz angibt und der zweite das Zeichen des eingelesenen Strings. Damit ich in jeden beliebigen Datensatz jedes beliebige Zeichen zur weiteren Verarbeitung aussuchen kann...

Das Problem ist halt nur, dass ich nie weiss, wie viele Datensätze(=Zeilen in der Textdatei) ich auslesen und als Zeichenkette speichern muss.

Link zu diesem Kommentar
Auf anderen Seiten teilen

ich würde als zeiger so ein kontrukt verwenden:

char** pArray = new [50][150];

später mit

delete [] pArray;

wieder löschen

Dann kannst du damit wie mit einem normalen Array arbeiten. Also z.B.: pArray[0][15] = 'h';

Dafür musst dir bloß bekannt sein, wieviele Zeilen die Datei hat um das Array in der entsprechenden Größe zu erstellen. Dagegen helfen zwei Wege. 1.) Vorhereinmal die Zeilen in der Datei 'durchzählen' oder 2.) mit malloc und realloc arbeiten. Davon kenne ich aber die genau Syntax nicht. Hilft wahrscheinlich ein Blick in die MSDN.

ps: Wenns ein wenig C++ sein darf hilft dir vielleich auch ein std::vector<char*> weiter. Beispiel:


#include <vector>
#include <fstream.h>

main()
{
std::vector<char*> vDaten;
fstream fIn("text.txt", ios::in);
while (!fIn.eof())
{
char* szTmp = new char[201];
fIn.getline(szTmp, 200);
vDaten.insert(vDaten.end(), szTmp); // Syntax: ???
}
// ...
}
[/PHP]

Der Vector bietet einem dann glaube ich auch noch ein paar Methoden zum sortieren an.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Was sit eigentlich gegen folgende Lösung einzuwenden:

char** pCharArray = NULL;

pCharArray = (char**)malloc(sizeof(char*));

Das ganze kannst du dann wie gewohnt füllen ( pCharArray[0] = "String"; )

und du bist völlig ungebunden was die Länge eines Strings sowie die Anzahl der Datensätze angeht.

:rolleyes:

Link zu diesem Kommentar
Auf anderen Seiten teilen

sowas ähnliches hab ich versucht:

#define MAX_ZEILENLAENGE 150

typedef char datensatz[MAX_ZEILENLAENGE + 1];

datensatz *zeilen = NULL;

int anzmaxzeilen = 1;

int anzzeilen = 0;

char *c;

zeilen = malloc(anzmaxzeilen * sizeof(datensatz));

das hatte aber einen Speicherzugriffsfehler zur Folge, da das mit der Typdef mit Array wohl so nicht geht, konnte der Speicher nicht berechnet werden

Das mit dem Füllen ist wieder so eine Sache. Ich lese aus einer Textdatei zeilenweise aus. Eine Zeile hat ca. 150 Zeichen, nur die Anzahl der Zeilen ist immer verschieden und es muss nach bestimmten Spalten der Zeile (durch Tabs getrennt) sortiert werden, daher brauch ich unbedingt die dynamische Speicherverwaltung. Und ich muss das Array mit beiden Indizes ansprechen können -> blabla[j]

Link zu diesem Kommentar
Auf anderen Seiten teilen

Kannsts ja mal so in der Art probieren.....musst das natuerlich n bissl umbasteln und entsprechende Funktionen schreiben, sonst ists ne Menge schreibarbeit denk ich :D

char** pCharArray = NULL; 

pCharArray = (char**)malloc(sizeof(char*));
pCharArray[0] = (char*) malloc(150 * sizeof(char));
pCharArray[0][0]= 'a'; //mal so zum Test


pCharArray = (char**)realloc(pCharArray, _msize(pCharArray) + sizeof(char*)); //erweitern um eins
pCharArray[1] = (char*) malloc(150 * sizeof(char));
pCharArray[1][0]= 'b'; //mal so zum Test


printf("%c", pCharArray[0][0]);
printf("\n%c", pCharArray[1][0]);

free(pCharArray[0]);
free(pCharArray[1]);
free(pCharArray);[/PHP]

Goos

Link zu diesem Kommentar
Auf anderen Seiten teilen

Naja mit malloc haettest von der Sytntax her malloc(150 * sizeof(char)) und bei calloc waers denn calloc(150, sizeof(char)) *g* :OD

Der wirkliche Unterschied ist, aber dass bei calloc alle 150 Elemente mit 0 initialisiert werden, bei malloc muesstest das dann noch von hand machen, dass nicht irgendein ******* drinsteht.

Goos

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hi,

die Speicherzugriffsverletzung resultiert vielleicht aus einem fehlendem cast. Da die Funktion 'malloc' eine Zeiger vom Typ void zurückgibt, muß man diesen in den benötigten Datentyp umwandeln. Bsp.:

zeilen = (datensatz*)malloc(anzmaxzeilen * sizeof(datensatz));

Dann sollte es klappen.

Und das mit dem einlesen sollte eigentlich auch klappen. Bsp.:

( Quasi Pseudo Code; kein Anspruch auf syntaktische Fehlerfreiheit; dient nur der Anschauung :)) )

int i = 0;

while( !EOF )

{

pCharArray = file.ReadString();

i++;

}

Der Zugriff auf die einzelnen Zeichen funktioniert dann reibungslos mit: char cAnything = pCharArray[m][k];

(m gibt dann denn jeweiligen DS an und k das jeweilige Zeichen)

Wie das mit dem Sortieren vor sich gehen soll hab ich allerding noch nicht aus deinen Ausführungen entnehmen können. Soll nach dem Einlesen aller DS sortiert werden oder sofort während des einlesens? Gibt es dazu eine GUI oder ist das ganze Teil einer Bibliothek?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Die Sortierung muss ich leider auch selbst schreiben, k.A. ob's da schon was Fertiges gibt...

Eine Zeile besteht aus 9 durch Tabs getrennte Spalten (d.h. die Spalten entstehen eben, wenn man die ~100.000 Zeilen untereinanderstehen hat). Dann soll nach der 3. Spalte sortiert werden und die jeweils dazugehörige 7. Spalte mit erfasst werden zwecks späteren Aufaddierens. Genauso muss nochmal die 5. Spalte sortiert werden und wieder die 7. mit extrahiert werden. Also werd ich erst sortieren können, wenn alle Zeilen erstmal irgendwo abgelegt sind, oder geht das auch einfacher?

Für jeden Hinweis, der mir großartiges Schleifengepopel erspart, bin ich dankbar...

Eigentlich brauch ich von jeder Zeile nur den Abschnitt nach dem 2. Tab, dem 4. Tab und dem 6. Tab.

Ich denk mir schon, dass ich die Sache ziemlich kompliziert angehe, aber ich soll ja schliesslich was lernen bei, ne :confused:

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dann solltest meiner Meinung nach wohl beim einlesen auch wirklich nur die 3 Teile rausholen und die dann vielleicht in dein 3D Array schreiben. So in der Art pCharArray[Zeile][Tab-Abschnitt][inhalt] .

Ansonsten muesstest ja beim sortieren alles tausendmal nach Tabs durchsuchen :)

Goos

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich hab auch schon überlegt, ob ich nicht einfach die Datei VOR dem Einlesen in die drei Teile zerhacke, bzw. alles andere rausschmeisse und dann mit nem Bash-Befehl mir die Anzahl der Zeilen ausgeben lasse, die ich dann wiederum im Kommandozeilenaufruf als Parameter mitgeb...

und mir damit mein Array festlege:

datensatz[argv[4]][150]

Is halt net so elegant aber wohl funktional...

Allerdings hab ich überhaupt keinen Blassen wie ich beim Einlesen bereits die drei Abschnitte herausfiltern kann. Ich dachte, dazu müsste ich die gesamte Textdatei eben erst mal irgendwohin einlesen und nach Tabs druchsuchen, dann wieder durchkämmen und auslesen dann nochmal zum sortieren *arghl*

Wie muss das denn aussehen, wenn ich z.B. mit:

while((datensatz=fgets(fplesen))!=NULL)

{

...

}

die Textdatei auslesen will? Oder empfiehlst Du mir von vorneherein eine andere Einleseroutine?

Link zu diesem Kommentar
Auf anderen Seiten teilen

also mit

while(!feof( fplesen ) )
{
fgets(datensatz, 150, fplesen);
test = strchr( datensatz, '\t' );
result = test - datensatz + 1;[/PHP]

haettest dann z.B. die position des ersten Tabs ermittelt.

Das brauchst dann ja nur entsprechend fuer die weiteren Tabs machen und dann kannst den Text zwischen den Tabs gleich in die richtigen Arrays kopieren.

Goos

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hi, gaaaaaaaaanz dickes Danke erstmal für die C-Schulung, die ich hier fleissig in Anspruch nehme :) !!!

Leider gips noch'n kleines Problem :rolleyes: :

Ich muss das auf einer Linux-Kiste zum Laufen kriegen, da funktioniert die

_msize()

leider nicht. Gibt's eine Funktion, speziell für Linux, mit der man dasselbe erreicht?

Gruß, ]bAd[Vamp

Link zu diesem Kommentar
Auf anderen Seiten teilen

Brauchen tust das da wirklich nicht.

msize ist ja wie der name schon halbwegs sagt die Groesse des bisher allokierten Speichers....da du das aber zuvor eh selbst gemacht hast, weisst du ja wieviel das ist :)

D.h. du kannst auch vom malloc angefangen und dann bei jedem realloc einfach nen zaehler mitlaufen lassen.

Am obigen Beispiel waer das dann sowas in der Art

char** pCharArray = NULL; 
int zaehl = 1;

pCharArray = (char**)malloc(sizeof(char*));
pCharArray[0] = (char*) malloc(150 * sizeof(char));
pCharArray[0][0]= 'a'; //mal so zum Test
zaehl++;

pCharArray = (char**)realloc(pCharArray, zaehl * sizeof(char*)); //erweitern um eins
zaehl ++;
pCharArray[1] = (char*) malloc(150 * sizeof(char));
pCharArray[1][0]= 'b'; //mal so zum Test


printf("%c", pCharArray[0][0]);
printf("\n%c", pCharArray[1][0]);

free(pCharArray[0]);
free(pCharArray[1]);
free(pCharArray);[/PHP]

Goos

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...