Osaisikohan joku selittää miksi seuraava c-koodinpätkä ei toimi?
Haluaisin siis määritellä ja nollata vektorin käyttämällä calloc()-funktiota ja lukea siihen arvot tiedostosta. Homma toimii ongelmitta jos käytän nyt kommentoitua tapaa vektorin määrittelyyn, mutta kun pitäisi käyttää dynaamista muistinhallintaa.
#include <stdio.h> #include <stdlib.h> int main(){ int koko = 5; double *vektori = calloc(koko, sizeof(double)); //double vektori[koko]; FILE *pointteri; pointteri = fopen("tiedosto.bin", "rb"); fread(&vektori, koko*sizeof(double), 1, pointteri); int i; for(i = 0; i < koko; i++){ printf("alkio %i: %lf\n", i+1, vektori[i]); } free(vektori); fclose(pointteri); return 0; }
Sivustolla http://www.cplusplus.com/reference/clibrary/
int * pData; printf ("Amount of numbers to be entered: "); scanf ("%d",&i); pData = (int*) calloc (i,sizeof(int));
Kokeiles vastaavasti tehdä tuo näin:
double *vektori = (double*)calloc(koko, sizeof(double));
Sain ainakin kääntymään ja ajamaan tuon kohdan ohi ilman virhettä. En tiedä ratkaiseeko mutta worth a try varmaan?
Ja laita ihmeessä tarkistus että tiedosto myös aukeaa :D Ilman sitä tulee kiva segmentation fault ;-)
Varmaankin tämän rivin:
fread(&vektori, koko*sizeof(double), 1, pointteri);
pitäisi olla:
fread(vektori, koko*sizeof(double), 1, pointteri);
Tuossa vektori on osoitin, joka osoittaa muistialueeseen, jonne tiedoston sisältö halutaan lukea. &vektori taas on osoitin osoittimeen, eli sen lähettämisestä freadille tuskin seuraa mitään hyvää.
tneva82 kirjoitti:
Sivustolla http://www.cplusplus.com/reference/clibrary/
cstdlib/calloc.html näytettiin esimerkkinä: int * pData; printf ("Amount of numbers to be entered: "); scanf ("%d",&i); pData = (int*) calloc (i,sizeof(int));Kokeiles vastaavasti tehdä tuo näin:
double *vektori = (double*)calloc(koko, sizeof(double));
Sain ainakin kääntymään ja ajamaan tuon kohdan ohi ilman virhettä.
Kokeiltu en, tyyppimuunnos ei vaikuta toimintaan. Ymmärtääkseni tyyppimuunnoksen tarve/tarpeettomuus riippuu kääntäjästä.
tneva82 kirjoitti:
Ja laita ihmeessä tarkistus että tiedosto myös aukeaa :D Ilman sitä tulee kiva segmentation fault ;-)
Juu tiedossa on. Kyse on isohkosta projektista jota en viitsinyt kokonaisuudessaan läväyttää tähän foorumille, siksi tässä vain ongelmani kannalta relevantti pätkä.
Sisuaski kirjoitti:
Varmaankin tämän rivin:
fread(&vektori, koko*sizeof(double), 1, pointteri);pitäisi olla:
fread(vektori, koko*sizeof(double), 1, pointteri);Tuossa vektori on osoitin, joka osoittaa muistialueeseen, jonne tiedoston sisältö halutaan lukea. &vektori taas on osoitin osoittimeen, eli sen lähettämisestä freadille tuskin seuraa mitään hyvää.
No nyt toimii, kiitos! Yllättäen taas vika johtuu ponttereista (tai siis käyttäjästä joka ei ole ihan sisäistänyt pointtereita).
C:ssä osoittimen tyyppimuunnosta ei tarvita.
Sisuaski osui ongelman ytimeen. Kysyjän koodin kommentoitukaan tapa ei toimi oikein, kyseessä on lähes oikeasta toiminnasta johtuva harha.
Metabolix kirjoitti:
Sisuaski osui ongelman ytimeen. Kysyjän koodin kommentoitukaan tapa ei toimi oikein, kyseessä on lähes oikeasta toiminnasta johtuva harha.
Selitätkö vähän tarkemmin? Oon nimittäin taistellut asian kanssa pitkään ja hartaasti.
ongelma kirjoitti:
Kokeiltu en, tyyppimuunnos ei vaikuta toimintaan. Ymmärtääkseni tyyppimuunnoksen tarve/tarpeettomuus riippuu kääntäjästä.
Jep, C-kielen speksejä noudattavat kääntäjät eivät tarvitse eksplisiittistä tyyppimuunnosta.
<ot> Jotkut kuitenkin suosittelevat sitä virheiden välttämiseksi, sillä sen avulla kääntäjästä on apua esimerkiksi seuraavassa skenaariossa:
//-- short *a; a = malloc(size * sizeof(short));
Jaa, tarvitsenkin suurempia muuttujia:
// short *a; int *a; a = malloc(size * sizeof(short)); /* Mahdollinen virhe: a ei välttämättä osoita size-alkion kokoiseen muisti- alueeseen. Koodi on kuitenkin sinänsä oikein, joten kääntäjä ei valita; oikea määrittelemätön toiminta sattuu (jos sattuu) kun a:n viimeisiä alkiota käytetään */ // Toisaalta: a = (short *)malloc(size * sizeof(short)); /* Mahdollinen virhe: Myös kääntäjä huomauttaa asiasta */
Toiset (ml. minä itse) suosivat dereferointia koon selvittämiseksi dynaamisen muistinhallinnan kanssa (allaoleva on oikein, kunhan a on osoitin, muttei void*
). Tämä säästää paljolta visuaaliselta tauhkalta varsinkin struct
ien kanssa (toteutettavissa haluttaessa myös makroilla):
//-- int *a; a = malloc(size * sizeof(*a)); /* vertaa: tmp = (struct type_s *)malloc(size * sizeof(struct type_s)); tmp = malloc(size * sizeof(*tmp)); */
</ot>
//-- int koko = 5; double vektori[koko];
Ylläoleva olisi väärin, koska koko ei ole (teknisesti) vakio, vaan nimenomaisesti muuttuja. Staattinen, tai automaattinen muistinhallinta vaatii koon tietämistä käännöshetkellä; koko on muistissa sijaitseva muuttuja, ei staattinen vakio. const
-attribuuttikaan ei auta, sillä se on vain "vihje".
edit: sisennys
koodic
näemmä hylkää kaiken whitespacen ennen ensimmäistä "ei-whitespace":a. Lieköhän tarkoituksenmukaista, kun esim. koodi
ei näin tee.
eq kirjoitti:
//-- int koko = 5; double vektori[koko];Ylläoleva olisi väärin, koska koko ei ole (teknisesti) vakio, vaan nimenomaisesti muuttuja. Staattinen, tai automaattinen muistinhallinta vaatii koon tietämistä käännöshetkellä; koko on muistissa sijaitseva muuttuja, ei staattinen vakio. const-attribuuttikaan ei auta, sillä se on vain "vihje".
C:ssä (eli C:n voimassa olevassa standardissa C99:ssä) kyllä muuttujen kokoiset staattiset taulukot ovat ihan sallittuja.
Sisuaski kirjoitti:
C:ssä (eli C:n voimassa olevassa standardissa C99:ssä) kyllä muuttujen kokoiset staattiset taulukot ovat ihan sallittuja.
Tuli näemmä puhuttua aivan puutaheinää. Ylläoleva pätee siis (jotakuinkin) vain globaalilla tasolla (käsittääkseni myös C90:ssä funktioiden sisäiset "staattiset" taulukot voidaan luoda muuttujien koon mukaan). eq out.
eq kirjoitti:
käsittääkseni myös C90:ssä funktioiden sisäiset "staattiset" taulukot voidaan luoda muuttujien koon mukaan
C90:ssä se on kiellettyä, mutta esim. GCC sallii ne.
Aihe on jo aika vanha, joten et voi enää vastata siihen.