Springen naar inhoud

[c] regeltje uit tekstbestand lezen


  • Log in om te kunnen reageren

#1

Jeroen

    Jeroen


  • >250 berichten
  • 351 berichten
  • Ervaren gebruiker

Geplaatst op 13 januari 2009 - 14:18

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.):

[codebox]

FILE* lijst;
char *regel;

fgets(regel, 100, lijst);

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

[/codebox]

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

Dit forum kan gratis blijven vanwege banners als deze. Door te registeren zal de onderstaande banner overigens verdwijnen.

#2

Rogier

    Rogier


  • >5k berichten
  • 5679 berichten
  • VIP

Geplaatst op 13 januari 2009 - 14:37

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.

#3

Jeroen

    Jeroen


  • >250 berichten
  • 351 berichten
  • Ervaren gebruiker

Geplaatst op 13 januari 2009 - 14:42

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...

#4

Rogier

    Rogier


  • >5k berichten
  • 5679 berichten
  • VIP

Geplaatst op 13 januari 2009 - 15:06

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.

#5

Jeroen

    Jeroen


  • >250 berichten
  • 351 berichten
  • Ervaren gebruiker

Geplaatst op 13 januari 2009 - 15:20

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:

[codebox]
FILE* lijst;

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


char *regel;
fgets(regel, Linelength, lijst);



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



fclose(lijst);[/codebox]
Nothing to see here, move along...

#6

Jeroen

    Jeroen


  • >250 berichten
  • 351 berichten
  • Ervaren gebruiker

Geplaatst op 13 januari 2009 - 15:45

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...

#7

Jeroen

    Jeroen


  • >250 berichten
  • 351 berichten
  • Ervaren gebruiker

Geplaatst op 13 januari 2009 - 16:03

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...

#8

Jeroen

    Jeroen


  • >250 berichten
  • 351 berichten
  • Ervaren gebruiker

Geplaatst op 13 januari 2009 - 16:58

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...

#9

Rogier

    Rogier


  • >5k berichten
  • 5679 berichten
  • VIP

Geplaatst op 13 januari 2009 - 17:41

Even terzijde, wellicht doe je het alloceren van "regel" ergens anders in je programma, maar enkel dit:
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.

#10

Jeroen

    Jeroen


  • >250 berichten
  • 351 berichten
  • Ervaren gebruiker

Geplaatst op 13 januari 2009 - 18:00

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...

#11

Rogier

    Rogier


  • >5k berichten
  • 5679 berichten
  • VIP

Geplaatst op 13 januari 2009 - 19:36

Met
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.

#12

Jeroen

    Jeroen


  • >250 berichten
  • 351 berichten
  • Ervaren gebruiker

Geplaatst op 13 januari 2009 - 21:18

Mijn tekstbestand heeft veel teveel regels en mijn arrays worden te groot.
Hoe kan ik ervoor zorgen dat fgets(regel[i], 90, lijst); alleen iets opslaat in regel[i] als het aan een bepaalde voorwaarde voor i voldoet, bijvoorbeeld elke 3e regel.
Ik heb nu dit:

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...

#13

Rogier

    Rogier


  • >5k berichten
  • 5679 berichten
  • VIP

Geplaatst op 13 januari 2009 - 21:56

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[i], 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[i]. 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.

#14

Jeroen

    Jeroen


  • >250 berichten
  • 351 berichten
  • Ervaren gebruiker

Geplaatst op 13 januari 2009 - 22:08

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.

Veranderd door Jeroen, 13 januari 2009 - 22:09

Nothing to see here, move along...

#15

Jeroen

    Jeroen


  • >250 berichten
  • 351 berichten
  • Ervaren gebruiker

Geplaatst op 13 januari 2009 - 22:23

Nu heb ik het zo:

char regel[(aantal_regels/3) ] [100];char dummy[((aantal_regels*2)/3) ] [100];char str0[(aantal_regels/3) + 1] [10]; //idchar str4[(aantal_regels/3) + 1] [10]; //type1char str7[(aantal_regels/3) + 1] [10]; //type2int 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.

Veranderd door Jeroen, 13 januari 2009 - 22:24

Nothing to see here, move along...





0 gebruiker(s) lezen dit onderwerp

0 leden, 0 bezoekers, 0 anonieme gebruikers

Ook adverteren op onze website? Lees hier meer!

Gesponsorde vacatures

Vacatures