[c] regeltje uit tekstbestand lezen

Moderators: jkien, Xilvo

Gebruikersavatar
Berichten: 351

[c] regeltje uit tekstbestand lezen

Ik weet niet of dit beter in het huiswerkforum past of hier, maar dit is mijn probleempje:

Ik heb een bestand met hele hoop regels(~300000) met elk 10 kolommen. Elk setje van drie regels hoort bijelkaar en ik wil hiervan steeds de tweede regel lezen en informatie uithalen.

Eerst zou ik willen weten hoe ik een regel als deze:

9 5584.54 0.0512014 0 13 0.368034 1e+06 12 0.679332 0.0116594

Inlees en converteer naar 10 floats en integers.

Ik heb het zo geprobeerd, maar dat werkt niet (nu moet ik ook toegeven dat ik er weinig van snap, ik heb het uit een oude opdracht van mij gehaald en aangepast.):

Code: Selecteer alles


 

   FILE* lijst;

   char *regel;                                 

     fgets(regel, 100, lijst);

     printf("Line 0: %s\n\n",regel);

Waarom werkt dit zo niet, en waar is die 100 eigenlijk voor?
Nothing to see here, move along...

Gebruikersavatar
Berichten: 5.679

Re: [c] regeltje uit tekstbestand lezen

Ik heb het zo geprobeerd, maar dat werkt niet
Dit leest alleen een regel en print hem uit, hoe had je zelf verwacht dat dit iets zou converteren naar integers en floats?
waar is die 100 eigenlijk voor?
Dat heb je toch sneller gegoogled dan het duurde om die vraag hier te posten?

Hint voor wat jij wil: kijk eens naar de sscanf functie (fgets en sscanf kan eventueel ook in één keer met fscanf).
In theory, there's no difference between theory and practice. In practice, there is.

Gebruikersavatar
Berichten: 351

Re: [c] regeltje uit tekstbestand lezen

Ohja dat het ik een beetje verwarrend neergezet. Het was niet mijn intentie met dit stukje code de regel om te zetten naar vanalles en nog wat. Het enige wat ik hiermee wilde bereiken is kijken of hij de eerste regel van mijn bestand goed leest. Het probleem is dus dat hij dat al niet doet. Het enige wat ik te zien krijg is wat gekke tekentjes of niets.

Ik heb gegoogled naar dit geval, die fgets, maar wordt niet veel wijzer van de dingen die ik vond. Ik wil voorbeelden, maar die kan ik niet vinden (geen nuttige voor mij). Vandaar dat ik de vraag nu hier post, in de hoop wat meer doelgerichte hulp te krijgen :D .

Ik zal eens kijken naar die sscanf functie.
Nothing to see here, move along...

Gebruikersavatar
Berichten: 5.679

Re: [c] regeltje uit tekstbestand lezen

In je voorbeeld staat alleen de declaratie van "lijst" en "regel", hoe open respectievelijk alloceer je die precies? (Dat eerste kan bijvoorbeeld met fopen)
In theory, there's no difference between theory and practice. In practice, there is.

Gebruikersavatar
Berichten: 351

Re: [c] regeltje uit tekstbestand lezen

Oh sorry dat was ook vergeten erbij te stoppen, het staat wel in mijn programma, maar om mijn probleem overzichtelijk te houden laat ik de rest even weg en daarmee was ik ook het openen van het tekstbestand vergeten hierbij te zetten. Zo het ik het in het programma:

Code: Selecteer alles


FILE* lijst;

lijst = fopen("mergers.dat","r");

char *regel;

fgets(regel, Linelength, lijst);

printf("Line 0: %s\n\n",regel);

fclose(lijst);
Nothing to see here, move along...

Gebruikersavatar
Berichten: 351

Re: [c] regeltje uit tekstbestand lezen

Ah, ik heb via zo'n voorbeeldfiletje van fscanf iets gevonden wat werkt.

Als ik de functie "rewind" gebruik komt het wel goed.

Dan was het blijkbaar toch belangrijk om ook hier te vermelden dat ik al wel eerder al iets uit het bestand had gelezen, een paar programma regels terug. Ik had niet gedacht dat dat invloed zou hebben.

Dus ik kan nu een regel goed uitlezen en printen, ik heb een begin.
Nothing to see here, move along...

Gebruikersavatar
Berichten: 351

Re: [c] regeltje uit tekstbestand lezen

Ik begrijp sscanf niet. Ik lees:

Whitespace character: the function will read and ignore any whitespace characters (this includes blank spaces and the newline and tab characters) which are encountered before the next non-whitespace character. This includes any quantity of whitespace characters, or none.

Dat klinkt erg handig, want ik wil die whitespace ook overslaan en de hoeveelheid whitespace in de regel wisselt steeds. Maar hoe doe ik dit dan??
Nothing to see here, move along...

Gebruikersavatar
Berichten: 351

Re: [c] regeltje uit tekstbestand lezen

Ok, niet dat er nu vanuit gegaan moet worden dat ik overal vanzelf wel een keer uit kom, maar heel toevallig ben ik nu toch uit mijn vorige probleempje gekomen. Ik kan de regel nu dus omzetten in losse strings en die strings heb ik ook geconverteert naar floats met atof().
Nothing to see here, move along...

Gebruikersavatar
Berichten: 5.679

Re: [c] regeltje uit tekstbestand lezen

Even terzijde, wellicht doe je het alloceren van "regel" ergens anders in je programma, maar enkel dit:

Code: Selecteer alles

char *regel;

fgets(regel, Linelength, lijst);
is erg fout, vooral omdat dat mogelijk soms (puur toevallig) goed lijkt gaan.

Voor de duidelijkheid: die "regel" buffer moet je wel ergens alloceren. Daar komt ook Linelength vandaan als 't goed is (dat bepaalt hoeveel bytes fgets maximaal in regel mag schrijven).
In theory, there's no difference between theory and practice. In practice, there is.

Gebruikersavatar
Berichten: 351

Re: [c] regeltje uit tekstbestand lezen

Maar zo alloceer je toch iets? Eerst zeggen wat het voor iets is "char" en dan hoe het heet "regel" en dat sterretje is dan iets van een pointer wat dan weer net zoiets werkte als een array, dat snap ik nog steeds niet goed.

Nu heb ik het iig zo gedaan:

char regel [80];
Nothing to see here, move along...

Gebruikersavatar
Berichten: 5.679

Re: [c] regeltje uit tekstbestand lezen

Met

Code: Selecteer alles

char *regel;
definieer je alleen iets, er staat dat regel een char pointer is. Maar niet waar hij heen point, noch maak je buffer aan.

Met char regel[80]; gebeurt dat wel, dus dat is in orde. Voor grote buffers gebruik je beter = new char[...] (naderhand weer deleten).
In theory, there's no difference between theory and practice. In practice, there is.

Gebruikersavatar
Berichten: 351

Re: [c] regeltje uit tekstbestand lezen

Mijn tekstbestand heeft veel teveel regels en mijn arrays worden te groot.

Hoe kan ik ervoor zorgen dat fgets(regel, 90, lijst); alleen iets opslaat in regel als het aan een bepaalde voorwaarde voor i voldoet, bijvoorbeeld elke 3e regel.

Ik heb nu dit:

Code: Selecteer alles

for (i=0;i<aantal_regels;i++){

   

   if ( (i-1)%3 == 0 | i==1){

   fgets(regel[i], 90, lijst); // lees elke 2e regel in een groepje van 3.

   

   //printf("regelnummer gelezen = %d\n\n", i);

   

   sscanf (regel[i],"%s %*s %*s %*s %s %*s %*s %s %*s %*s",str0[i],str4[i],str7[i]);

   

   id[i]

 = atoi(str0[i]);

   type1[i]		  = atoi(str4[i]);

   type2[i]		  = atoi(str7[i]);

   

   printf("Ingelezen info uit regel %d:\n\n", i);

   printf("id	  = %d\n",id[i]);  

   printf("type1   = %d\n",type1[i]);  

   printf("type2   = %d\n",type2[i]);

   

   n+=1; //tel de regels met info

   //printf("namelijk:\n  %s\n\n", regel[i]);

   //printf("n = %d\n\n", n);

   } else {

  //printf("regel %d overgeslagen\n\n", i);

  }

   }
Zo nummert hij de regels wel leuk 1,4 en 7, maar hij leest toch alleen maar de 1e drie regels.

Ik heb gemerkt als ik na "else" ook een fgets functie doe, dat hij dan wel de juiste regels leest, maar dan heb ik nog steeds het probleem dat hij met die fgets functie ook een hele hoop regels in het geheugen opslaat die ik niet nodig heb.

Hoe los ik dit op?
Nothing to see here, move along...

Gebruikersavatar
Berichten: 5.679

Re: [c] regeltje uit tekstbestand lezen

Jeroen schreef:Zo nummert hij de regels wel leuk 1,4 en 7, maar hij leest toch alleen maar de 1e drie regels.

Ik heb gemerkt als ik na "else" ook een fgets functie doe, dat hij dan wel de juiste regels leest,
Op het moment dat je een fgets doet, wordt er een regel gelezen. Op het moment dat jij in de else alleen printf("regel overgeslagen") doet, slaat dat natuurlijk niet echt een regel over. Aan de status van dat bestand (en diens interne filepointer e.d.) verandert niets.

De eerstvolgende keer dat er een fgets gedaan wordt krijg je gewoon de eerstvolgende regel na degene die als laatste gelezen was. Jouw hele for loop en of je daar nu 2 van 3 de drie keer iets in else doet maakt daarvoor geen enkel verschil.

Wat je bijvoorbeeld kunt doen is in het else gedeelte fgets(dummy,100,lijst) waarbij dummy een loze buffer is waar fgets de ongebruikte regels mag dumpen.
maar dan heb ik nog steeds het probleem dat hij met die fgets functie ook een hele hoop regels in het geheugen opslaat die ik niet nodig heb.
Logisch, jij schrijft naar regel, waarbij i een counter is die alle regels van het bestand representeert (ook degene die je overslaat). In plaats daarvan heb je een counter nodig van alle feitelijk opgeslagen regels. En die heb je al: n.

Dus gebruik gewoon regel[n] in plaats van regel. Idem voor type[n] enzo.

Heb je naderhand trouwens die regels uberhaupt wel nodig, aangezien je de type en id informatie ook al los opslaat?
In theory, there's no difference between theory and practice. In practice, there is.

Gebruikersavatar
Berichten: 351

Re: [c] regeltje uit tekstbestand lezen

Maar zoals jij het zegt, heeft dit programma toch nog steeds een array nodig waarin hij de overige 2/3 van het bestand opslaat? Ik wil gewoon dat hij alleen regel 1,4,7,10 etc leest, types en id uithaald en opslaat en alle overige regels doen er niet toe.

Uiteindelijk zal ik de rest van die "belangrijke" regels ook nog een keer moeten gebruiken ja, maar ik wil eerst alleen type1,type2 en id van deze regels opslaan.
Nothing to see here, move along...

Gebruikersavatar
Berichten: 351

Re: [c] regeltje uit tekstbestand lezen

Nu heb ik het zo:

Code: Selecteer alles


char regel[(aantal_regels/3) ] [100];

char dummy[((aantal_regels*2)/3) ] [100];

char str0[(aantal_regels/3) + 1] [10]; //id

char str4[(aantal_regels/3) + 1] [10]; //type1

char str7[(aantal_regels/3) + 1] [10]; //type2

int id[(aantal_regels/3) + 1];

int type1[(aantal_regels/3) + 1];

int type2[(aantal_regels/3) + 1]; 

for (i=0;i<aantal_regels;i++){

if ( (i-1)%3 == 0 | i==1){ //

n+=1;

fgets(regel[n], 90, lijst); // lees elke 2e regel in een groep van 3.

//printf("regelnummer gelezen = %d\n\n", i);

sscanf (regel[n],"%s %*s %*s %*s %s %*s %*s %s %*s %*s",str0[n],str4[n],str7[n]);

id[n] = atoi(str0[n]);

type1[n] = atoi(str4[n]);

type2[n] = atoi(str7[n]);

printf("Ingelezen info uit regel %d:\n\n", i);

printf("id = %d\n",id[n]); 

printf("type1 = %d\n",type1[n]); 

printf("type2 = %d\n",type2[n]);

//tel de regels met info

//printf("namelijk:\n %s\n\n", regel[i]);

//printf("n = %d\n\n", n);

} else {

fgets(dummy[m], 90, lijst);

m+=1;

} 

}

Het werkt nu wel, maar ik heb dan nog steeds die dummy die onnodig veel geheugen in beslag neemt.

Dit programma crashed als ik mijn grote bestand erbij pak.
Nothing to see here, move along...

Reageer