Archief - [PROG][C] Probs met structures(LINUX)

Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.

yannick

Legacy Member
Ik heb dus een oefening waar ik structures moet in verwerken, maar spijtig gng pakt linux dit niet :s.

Ik werk met BuilderX van borland en dit is de code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struc {
int pnt,voor,tegen;
char *naam;
}PLOEG;

int main()
{
PLOEG* puit[20];
int nr =0,i=0,pnt,voor,tegen;
FILE *f;
char nm[20];

f =fopen("//home/yannick/Desktop/bes8.txt","r");
fscanf(f,"%2d",pnt);
fscanf(f,"%2d",voor);
fscanf(f,"%2d",tegen);
fscanf(f,"%15c",nm);
while(!feof(f))
{
pnt.pnt =pnt;
voor.voor=voor;
tegen.tegen=tegen;
puit->naam=(char*)calloc(naam,strlen(nm)+1);
strcpy(puit->naam,nm);
fscanf(f,"%2d",pnt);
fscanf(f,"%2d",voor);
fscanf(f,"%2d",tegen);
fscanf(f,"%15c",nm);

}
return 0;
}


Wanneer ik probeer te compilen krijg ik ne hoop errors die er eigenlijk allemaal gewoon willen zeggen dat hij typedef struc en dus ook alle declaraties niet begrijpt :(.

Vich

Legacy Member
Ok, dat kan door verschillende redenen komen. Eerst en vooral is het belangrijk dat je code tussen code-tags plaatst ipv quote-tags.

Verder:

Je includes zijn niet ANSI C++, die moeten zijn:
#include <cstdio>
#include <cstdlib>
#include <string>

"typedef struc" moet zijn:
typedef struct


[edit] Spuit11

yannick

Legacy Member
ma tis wel C dak in aant programmeren ben, dus die headers zijn goed.

Ja gvd, kwas een T vergeten :p. Bedankt he!
Ma nu heb ik ng een pak fouten, der is grandioos mis met mijn toewijzingen wrs :s.

Want dit:
pnt.pnt =pnt;
voor.voor=voor;
tegen.tegen=tegen;
puit->naam=(char*)calloc(naam,strlen(nm)+1);
strcpy(puit->naam,nm);

is een en al error :).

grtz
*EDIT*
Ok, die pnt.pnt en voor.voor en tegen.tegen kloppen zeker niet.
Zoveel is duidelijk :D

Vich

Legacy Member
@ C/C++ -> Ik moet beter leren lezen
bonk.gif

wlibaers

Legacy Member
yannick zei:
ma tis wel C dak in aant programmeren ben, dus die headers zijn goed.

Ja gvd, kwas een T vergeten :p. Bedankt he!
Ma nu heb ik ng een pak fouten, der is grandioos mis met mijn toewijzingen wrs :s.

Want dit:
pnt.pnt =pnt;
voor.voor=voor;
tegen.tegen=tegen;
puit->naam=(char*)calloc(naam,strlen(nm)+1);
strcpy(puit->naam,nm);

is een en al error :).

grtz
*EDIT*
Ok, die pnt.pnt en voor.voor en tegen.tegen kloppen zeker niet.
Zoveel is duidelijk :D


De goede vorm is (iets van type PLOEG).pnt enz...

En verder:
PLOEG* puit[20];
OK, puit is een array van 20 pointers naar PLOEG structures. Nergens wordt voor de ploegen plaats toegewezen. Het zou misschien eenvoudiger zijn gewoon een array van structures te gebruiken. Indien pointers toch nodig zijn, zorg dan dat ze ook naar PLOEG structures verwijzen.

puit is zelf dus ook geen PLOEG structure. Dus puit->naam is ook niet in orde (in die uitdrukking is, volgens standaard conversieregels, puit van type "pointer naar pointer naar ploeg", wat ongetwijfeld niet is wat je wil). Puit[ index ] ->naam zou wel OK zijn als de pointers ook naar effectief bestaande structures verwijzen.

Er wordt ingelezen tot het einde van het bestand, terwijl er maar voor 20 PLOEGen plaats is. Onveilig, maar als je er zeker van bent dat er nooit meer invoer komt wel OK. Zorg er ook best voor dat de ploegnaam altijd exact 15 letters telt.

Waarom trouwens allemaal hoofdletters in PLOEG? De conventie in C is dat namen met alleen hoofdletters voor macro's zijn. Niet verplicht, maar het maakt de boel iets duidelijker.

char nm[20]; geen initializer, inhoud dus niet gedefinieerd.
gevaarlijk in combinatie met
fscanf(f,"%15c",nm);
want dit plaatst geen nul aan het einde van de ingelezen reeks chars. De waarde van strlen is dus onbetrouwbaar. En ik hoop dat je bestand altijd exact 15 chars bevat, of er kunnen nog andere interessante dingen gebeuren.

killgore

Legacy Member
opmerking: hoofdletters wordt in zowat elke programmeertaal gebruikt voor constanten (en macro's zoals hierboven gezegd). Is misschien muggenziften, maar ge leert u da best aan zoda ge later nie zwaar in de war geraakt :p (zeker nie wnnr ze u verplichten op u werk om het zo te gebruiken, welke kans vrij groot is).
Verder is ook de logica rond uw while lus verkeerd, ge zou alle scans binnen de while moeten kunnen doen (tenzij dit 1 of andere vreemde c-construct is :p?

wlibaers

Legacy Member
killgore zei:
Verder is ook de logica rond uw while lus verkeerd, ge zou alle scans binnen de while moeten kunnen doen (tenzij dit 1 of andere vreemde c-construct is :p?

De logica is niet verkeerd maar ik zou ook een andere structuur gebruiken die alles binnen de while plaatst.
Code:
while (1)
{
  // invoer hier
  if (feof(f)) break;
  // struct opvullen
}

killgore

Legacy Member
wlibaers zei:
De logica is niet verkeerd maar ik zou ook een andere structuur gebruiken die alles binnen de while plaatst.
Code:
while (1)
{
  // invoer hier
  if (feof(f)) break;
  // struct opvullen
}
ooit van do while gehoord :s?

wlibaers

Legacy Member
killgore zei:
ooit van do while gehoord :s?

O ja, maar dat zou hier niet beter zijn. Je moet namelijk een keer meer invoer proberen te krijgen (de laatste keer, die moet falen) dan dat je invoer naar een struct schrijft. feof geeft namelijk geen eof melding als je aan het einde van een bestand zit, maar pas als er al eens invoer gefaald is doordat je aan het einde van een bestand zit. Subtiel verschil. Daarom dat die break in het midden uit de loop springt. Wat je ook kan doen is een do-while toepassen en met een goto naar het midden van de loop springen voor de eerste iteratie, maar die stijl is niet beter denk ik. ;)

De foutenbehandeling is niet volledig (fouten door verkeerd formaat van het bestand worden niet gedetecteerd) maar wat er staat klopt wel.

killgore

Legacy Member
sentinels ...

dus, helemaal hetzelfde als jouw laatste zaak eigenlijk, ma ik break niet (aangezien dat slechts in enkele gevallen echt aan te raden is, zoals zoek-algoritmen).

Code:
bool einde = false;
do
{
  // invoer hier
  if (feof(f)) einde=true;
  else
  {
      // struct opvullen
  }
} while(!einde)

Kan zijn dat het beter kan, ik ben niet echt vertrouwd met file-functies van C ;) aangezien ek streams van c++ gebruik.

edit: kheb de indruk dak iets fout doe, wnt dit kan perfect met while ^o)

wlibaers

Legacy Member
killgore zei:
sentinels ...

dus, helemaal hetzelfde als jouw laatste zaak eigenlijk, ma ik break niet (aangezien dat slechts in enkele gevallen echt aan te raden is, zoals zoek-algoritmen).

Persoonlijke voorkeur. Ik verkies de break omdat die de code eenvoudiger en duidelijker houdt (en je moet geen extra variabelen gaan gebruiken).

killgore

Legacy Member
wlibaers zei:
Persoonlijke voorkeur. Ik verkies de break omdat die de code eenvoudiger en duidelijker houdt (en je moet geen extra variabelen gaan gebruiken).
ik vind breaks juist minder duidelijk en te vermijden tenzij je echt vroegtijdig wilt afbreken.
Ma zoals ik zei, is er volgens mij iets mis met men code, ma kzou c-functies vo files is moeten bekijken :p.

Vich

Legacy Member
Wat is er dan mis met:

Code:
// file openen
while (!feof(f))
{
    // inlezen
    // wegschrijven
}

Ik zou zelfs een soort ReadRecord(file*, struct*) functie maken die ook na elke fscanf gaat checken of de file nog niet op z'n einde is. Het bestand kan immers corrupt zijn of je bent misschien een niet-compatible bestand aan het inlezen. Je code wordt er in ieder geval duidelijker op.

wlibaers

Legacy Member
Vich zei:
Wat is er dan mis met:

Code:
// file openen
while (!feof(f))
{
    // inlezen
    // wegschrijven
}

Dat je iets waarvan het inlezen mislukt is gaat wegschrijven. Denk eraan dat het resultaat van feof(f) niet afhangt van of je al dan niet aan het einde van het bestand zit, maar wel of de laatste invoerpoging op dat bestand mislukt is doordat je op het einde van het bestand zit.

Ik zou zelfs een soort ReadRecord(file*, struct*) functie maken die ook na elke fscanf gaat checken of de file nog niet op z'n einde is. Het bestand kan immers corrupt zijn of je bent misschien een niet-compatible bestand aan het inlezen. Je code wordt er in ieder geval duidelijker op.

Dat lijkt me ook een goed idee. Dan kan er meteen ook op andere fouten gecontroleerd worden dan EOF.

Vich

Legacy Member
wlibaers zei:
Dat je iets waarvan het inlezen mislukt is gaat wegschrijven.
Das gewoon kwestie van controleren of het inlezen gelukt is. Dat doe je dan ook niet met feof().

Denk eraan dat het resultaat van feof(f) niet afhangt van of je al dan niet aan het einde van het bestand zit, maar wel of de laatste invoerpoging op dat bestand mislukt is doordat je op het einde van het bestand zit.
Nee, feof(file) kijkt of de huidige lees/schrijf-plaats op het einde van het bestand zit. Je kan die lees/schrijfplaats met fseek beinvloeden(maar dat wist je mss al).

In C++ heb je een systeem met een iterator, daar ga je kijken of die bvb aan het begin van de lijst of het einde staat. Als je door een reeks van objecten gaat, dan ga je daar doorlopen tot je aan lijst.end() bent, das vergelijkbaar met de feof(file) check. Een bestand inlezen gaat in principe op dezelfde manier. Je leest een file in en je leespositie(iterator) verschuift automatisch mee terwijl je dat doet. Je kan met fseek dan de 'iterator' of leespositie verplaatsen.

killgore

Legacy Member
Vich zei:
In C++ heb je een systeem met een iterator, daar ga je kijken of die bvb aan het begin van de lijst of het einde staat. Als je door een reeks van objecten gaat, dan ga je daar doorlopen tot je aan lijst.end() bent, das vergelijkbaar met de feof(file) check. Een bestand inlezen gaat in principe op dezelfde manier. Je leest een file in en je leespositie(iterator) verschuift automatisch mee terwijl je dat doet. Je kan met fseek dan de 'iterator' of leespositie verplaatsen.
uhu, dat dacht ik dus uit c++ standpt, daarom dak die do-while construtie deed ;).

wlibaers

Legacy Member
Vich zei:
Nee, feof(file) kijkt of de huidige lees/schrijf-plaats op het einde van het bestand zit.

OK, om alle verwarring te voorkomen, de C99 standaard.

Iemand is zo vriendelijk geweest dat ding op het net te gooien, voor het geval je hem nog niet hebt.
http://www.nirvani.net.nyud.net:8090/docs/ansi_c.pdf

Kijk naar 7.19.10.2, dit vermeldt duidelijk wat feof echt doet, wat misschien niet meteen het meest logische is (ik heb het zelf ook moeten opzoeken, het was ook niet wat ik dacht).
Vervolgens 7.19.7.1, fgetc. Als er bij het begin van een fgetc functieaanroep nog een char in de stream zit, wordt de end-of-file indicator niet aangezet, zelfs niet als dat char het laatste was, en de stream na afloop dus wel degelijk aan z'n einde zit.
7.19.3, paragraaf 11. Waarom dit ook relevant is voor fscanf.


Ter illustratie, in tenminste een implementatie (gcc-MinGW) gedraagt zich op de in de standaard bepaalde manier (andere implementaties waarschijnlijk ook, maar ik had geen zin om allerlei obscure compilers op te sporen).

bestand t.c
Code:
#include <stdio.h>

int main()
{
	FILE *f;
	f=fopen("x.txt","r");

	printf( "%d ", fgetc(f));
 	printf( feof(f) ? "EOF\n" : "no EOF\n" );
	printf( "%d ", fgetc(f));
 	printf( feof(f) ? "EOF\n" : "no EOF\n" );

	fclose(f);
	return 0;
}

x.txt is een bestand met als inhoud 1 byte, 'a'

commandoprompt:
Code:
D:\test\c>gcc t.c

D:\test\c>a.exe
97 no EOF
-1 EOF

D:\test\c>

Merk op dat, na de eerste fgetc, de stream aan het einde van het bestand zit, maar feof nul geeft. Pas nadat een fgetc faalt doordat de stream aan het einde van het bestand zit, geeft feof een va nul verschillende waarde.

Wanneer aan bovenstaande programma het volgende toegevoegd wordt:
unsigned char c;
en in de printf aanroepen het deel fgetc(f) telkensvervangen wordt door (fscanf(f,"%1c", &c), c) krijg je de volgende uitvoer:
Code:
97 no EOF
97 EOF
Andere waarde voor de tweede regel (c wordt namelijk niet aangepast bij falende fscanf) maar hetzelfde resultaat voor feof.
Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.
Terug
Bovenaan