C-ohjelmointi, syksy 2006

Samankaltaiset tiedostot
C-ohjelmointi, syksy Yksiulotteiset taulukot Moniulotteiset taulukot Dynaamiset taulukot. Binääritiedostot. Luento

Luennon sisältö. Taulukot (arrays) (Müldnerin kirjan luku 10) Yksiulotteiset taulukot. Mikä taulukko on? Taulukko-osoitin. tavallinen osoitin

Ohjelmassa muuttujalla on nimi ja arvo. Kääntäjä ja linkkeri varaavat muistilohkon, jonne muuttujan arvo talletetaan.

Tiedostot. Tiedostot. Tiedostot. Tiedostot. Tiedostot. Tiedostot

Lyhyt kertaus osoittimista

Merkkijono määritellään kuten muutkin taulukot, mutta tilaa on varattava yksi ylimääräinen paikka lopetusmerkille:

Rakenteiset tietotyypit Moniulotteiset taulukot

C-kielessä taulukko on joukko peräkkäisiä muistipaikkoja, jotka kaikki pystyvät tallettamaan samaa tyyppiä olevaa tietoa.

Moduli 5: Kehittyneitä piirteitä

C-ohjelmointi: Osoittimet

Tiedosto on yhteenkuuluvien tietojen joukko, joka tavallisimmin sijaitsee kiintolevyllä, muistitikulla tai jollakin muulla fyysisellä tietovälineellä.

Osoittimet ja taulukot

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset

Operaattoreiden ylikuormitus. Operaattoreiden kuormitus. Operaattoreiden kuormitus. Operaattoreista. Kuormituksesta

Osoittimet ja taulukot

Sisältö. C-ohjelmointi Luento 5: Osoittimet. Keko (heap) Pino (stack) Muistinhallinta Java vs C. Prosessin rakenne

Sisältö. 2. Taulukot. Yleistä. Yleistä

Muistin käyttö. Muistin käyttö. Muistin käyttö. Muistin käyttö. Muistin käyttö. Muistin käyttö. Muistin käyttö C-ohjelmassa

Yleistä. Nyt käsitellään vain taulukko (array), joka on saman tyyppisten muuttujien eli alkioiden (element) kokoelma.

Loppukurssin järjestelyt

Loppukurssin järjestelyt C:n edistyneet piirteet

Tietorakenteet ja algoritmit

Osoitin ja viittaus C++:ssa

Tietueet. Tietueiden määrittely

C-ohjelma. C-ohjelma. C-ohjelma. C-ohjelma. C-ohjelma. C-ohjelma. Operaatioiden suoritusjärjestys

Binäärioperaatiot Tiedostot ja I/O

Dynaaminen muisti. Pasi Sarolahti Aalto University School of Electrical Engineering. C-ohjelmointi Kevät 2017.

Sisältö. 22. Taulukot. Yleistä. Yleistä

1.1 Pino (stack) Koodiluonnos. Graafinen esitys ...

Moduli 4: Moniulotteiset taulukot & Bittioperaatiot

Ohjelmassa henkilön etunimi ja sukunimi luetaan kahteen muuttujaan seuraavasti:

1. Mitä seuraava ohjelma tulostaa? Vastaukseksi riittää yksi rivi joka esittää tulosteen. (6 p)

Binäärioperaatiot Tiedostot ja I/O

Tietorakenteet ja algoritmit

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

Ohjeet. AS C-ohjelmoinnin peruskurssi Aalto-yliopiston sahkotekniikan korkeakoulu Tentti , Raimo Nikkila

Harjoitustyö: virtuaalikone

Moduli 2: Osoittimet ja taulukot. Joel Huttunen

Olion elinikä. Olion luominen. Olion tuhoutuminen. Olion tuhoutuminen. Kissa rontti = null; rontti = new Kissa();

Java-kielen perusteet

13 Operaattoreiden ylimäärittelyjä

tietueet eri tyyppisiä tietoja saman muuttujan arvoiksi

815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset

Ohjelmoinnin perusteet Y Python

Ohjelmointi 2. Jussi Pohjolainen. TAMK» Tieto- ja viestintäteknologia , Jussi Pohjolainen TAMPEREEN AMMATTIKORKEAKOULU

Sisällys. 7. Oliot ja viitteet. Olion luominen. Olio Java-kielessä

Luennon sisältö Tyypit int, char, float, double signed, unsigned short, long Vakiot const Rakenteet if, for, while, switch, do-while Syöttö ja tulostu

Kirjoita oma versio funktioista strcpy ja strcat, jotka saavat parametrinaan kaksi merkkiosoitinta.

Taulukoiden käsittely Javalla

ITKP102 Ohjelmointi 1 (6 op)

TIETORAKENTEET JA ALGORITMIT

Osoittimet. Mikä on osoitin?

Tietorakenteet ja algoritmit

Aliohjelmatyypit (2) Jakso 4 Aliohjelmien toteutus

Dynaaminen muisti Rakenteiset tietotyypit

Taulukot. Taulukon määrittely ja käyttö. Taulukko metodin parametrina. Taulukon sisällön kopiointi toiseen taulukkoon. Taulukon lajittelu

Ohjelmoinnin peruskurssi Y1

5.6. C-kielen perusteet, osa 6/8, Taulukko , pva, kuvat jma

Luento 4 Aliohjelmien toteutus

Java-kielen perusteet

Ohjelmoinnin perusteet Y Python

Jakso 4 Aliohjelmien toteutus

C-ohjelmointi Luento 5: Osoittimet Tiina Niklander

C-ohjelmointi Luento 5: Osoittimet

Ohjelmoinnin perusteet Y Python

C-kurssi kevät Luennon sisältö

Luennon sisältö. C-kurssi kevät Tasokokeen kohta 1: Taulukon järjestäminen. Tasokokeen kohta 2. Tasokokeen kohta 2. Tasokokeen kohta 3

ITKP102 Ohjelmointi 1 (6 op)

Ohjelmoinnin perusteet Y Python

7. Oliot ja viitteet 7.1

Ohjelmointi 1 Taulukot ja merkkijonot

Jakso 4 Aliohjelmien toteutus

Ohjelmoinnin perusteet Y Python

ITKP102 Ohjelmointi 1 (6 op)

C-kurssi syksy ltö. Luennon sisält. Luento 2: tyypit, rakenteet, makrot Tyypit. signed, unsigned short,, long Vakiot const Rakenteet

Tietotyypit ja operaattorit

Luennon sisält. ltö. C-kurssi syksy ääreet: int ja char. Yksinkertaiset tyypit. Kokonaisluvut. Merkit

Luokassa määriteltävät jäsenet ovat pääasiassa tietojäseniä tai aliohjelmajäseniä. Luokan määrittelyyn liittyvät varatut sanat:

Algoritmit 1. Luento 4 Ke Timo Männikkö

TIE448 Kääntäjätekniikka, syksy Antti-Juhani Kaijanaho. 27. lokakuuta 2009

Pythonin Kertaus. Cse-a1130. Tietotekniikka Sovelluksissa. Versio 0.01b

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Taulukot. Taulukon käsittely. Tämän osan sisältö. Esimerkki. Taulukon esittely ja luonti. Taulukon alustaminen. Taulukon koko

#include <stdio.h> // io-toiminnot. //#define KM_MAILISSA int main( ){

Algoritmit 2. Luento 13 Ti Timo Männikkö

Harjoitus 5 (viikko 48)

812347A Olio-ohjelmointi, 2015 syksy 2. vsk. X Poikkeusten käsittelystä

Algoritmit 1. Demot Timo Männikkö

Informaatioteknologian laitos Olio-ohjelmoinnin perusteet / Salo

Ohjelmoinnin perusteet Y Python

58131 Tietorakenteet ja algoritmit (syksy 2015)

Tietorakenteet. JAVA-OHJELMOINTI Osa 5: Tietorakenteita. Sisällys. Merkkijonot (String) Luokka String. Metodeja (public)

Harjoitus 4 (viikko 47)

// // whiledemov1.c // #include <stdio.h> int main(void){ int luku1 = -1; int luku2 = -1;

Koottu lause; { ja } -merkkien väliin kirjoitetut lauseet muodostavat lohkon, jonka sisällä lauseet suoritetaan peräkkäin.

Perusteet. Pasi Sarolahti Aalto University School of Electrical Engineering. C-ohjelmointi Kevät Pasi Sarolahti

Java-kielen perusteita

Kääreluokat (oppikirjan luku 9.4) (Wrapper-classes)

Ohjelmoinnin perusteet Y Python

Transkriptio:

, syksy 2006 Taulukot Yksiulotteiset taulukot Moniulotteiset taulukot Dynaamiset taulukot Binääritiedostot Luento 8 3.10.2006 Syksy 2006 1

Luennon sisältö Taulukoiden käsittelyä Yksiulotteiset taulukot Määrittely Vertailu Alustus Vakiotaulukko Taulukko parametrina Moniulotteiset taulukot Dynaamiset taulukot Binääritiedostot Syksy 2006 2

Taulukot (arrays) (Müldnerin kirjan luku 10) Yksiulotteiset taulukot C:ssä taulukot ovat staattisia (koko tiedettävä ennen kääntämistä), mutta muuten samankaltaisia kuin Javassa. Alkaa aina nollasta määrittely: type arrayname[size]; int luvut[20]; char *nimet[5*10+1]; #define SIZE 10 int taulu1[size]; Siirrettävyys: const int koko =20; /* vain funktioissa */ /* int taulu2[koko]; tässä laiton */ warning: ISO C90 forbids int foo(){ int taulu2[koko]; variable- size array 'taulu (ISO C99 sallii Syksy 2006 käytön, kuten myös gcc) 3

Mikä taulukko on? Taulukko on osoitin Vakioarvoinen eli osoittaa aina samaan paikkaan Osoittaa muistilohkoon, josta on varattu tilaa taulukon alkioille Vakioarvoinen osoitin muistilohko 0 1 2 3 4 5.. Muistilohkossa on tilaa taulukon koon ilmoittamalle määrälle taulukon tyypin kokoisia olioita int luvut[20]; Tilaa 20 kokonaisluvulle char*nimet[5 *10+1]; Tilaa 51 char-tyyppiselle osoittimelle Viittaukset eri alkioihin: luvut[0], luvut[1], luvut[2]. luvut [19] luvut nimet HUOM! Ajoaikana järjestelmä ei tarkista indeksien oikeellisuutta. Viittaus luvut[20] ei välttämättä aiheuta suoritusvirhettä, vaan ohjelma vain toimii, miten sattuu toimimaan! Syksy 2006 4

Yleisiä virheitä määrittelyssä ja käytössä Taulukon koko ilmoitettava vakiona int lkm=5; int taulu[lkm]; /*virheellinen */ Taulukko on vakioarvoinen osoitin, jonka arvoa ei saa muuttaa int luvut[20]; char *p; luvut = p; /*ei näin*/ p=luvut; /*ihan OK! Nyt p:kin osoittaa samaan */ Varo sivuvaikutuksia a[i] = i++; /* toiminta riippuu toteutuksesta! */ Kumpi tehdään ensin, kasvatus vai käyttö? ensin a[i] ja sitten vasta i++? vai ensin i++ ja sitten a[i]? luvut p Luvut osoittaa aina tähän muistilohkoon! 4 5 4 5 Kumpi?? Syksy 2006 5

Taulukko-osoitin tavallinen osoitin int luvut[20] Vakio Osoittaa aina samaan tietyn kokoiseen muistialueeseen sizeof(luvut) on 20 kokonaisluvun tarvitsema tavumäärä eli koko taulukon koko int *osoitin Muuttuja, joka voi osoittaa eri paikkoihin Mitään muistialuetta ei ole varattu sizeof(osoitin) on osoittimen tarvitsema tavumäärä Syksy 2006 6

Kokojen tulostaminen #include <stdio.h> #include <stdlib.h> int main(int argc, char **argv) { int *taulu[20]; int *s; printf ("Taulukon 'taulu' koko: %d\n", sizeof(taulu) ); printf ("Osoittimen 's' koko: %d\n", sizeof(s)); printf ("Taulukon alkion koko: %d\n", sizeof(taulu[0])); printf ("Taulukon alkioiden lukumäärä: %d\n", sizeof(taulu)/sizeof(taulu[0])); return 0; } int *taulu[20]; int *s; printf ("Taulukon 'taulu' koko: %d\n", sizeof(taulu) ); /*=> 80 */ printf ("Osoittimen 's' koko: %d\n", sizeof(s)) /* => 4 */ printf ("Taulukon alkion koko: %d\n", sizeof(taulu[0])); /* => 4 */ printf ("Taulukon alkioiden lukumäärä: %d\n", sizeof(taulu)/sizeof(taulu[0]); /* =>20*/ Syksy 2006 7

Taulukkojen vertailu: sama sisältö? #define SIZE 10 int x[size]; int y[size]; x y int *px,*py; for (px=x, py = y; px<x+size; px++, py++) if (*px!=*py).. Toimii vain jos saman kokoisia! Entä jos eivät ole? for (px=x; px<x+size; px++) if (*px!=y[px-x]).. for (i=0; i<size; i++ ) if(x[i]!= y[i]). Entä vertailu X== Y?? Mitä tässä verrataan? Syksy 2006 8

Taulukon alustaminen Taulukko alustetaan antamalla sen alkioiden arvot muodossa Esim. {a1, a2,, an} int t[] = {1, 2, 3}; int t[3] = {1, 2, 3}; int t[3] = {1, 2}; int t[3] = {1, 2, 3, 4}; 1 2 3 1 2 3 1 2 0 Taulukon nollaus: int taulu[10000]={0}; Alkioiden lukumäärä määrää taulukon koon! Täytetään järjestyksessä. Loput nollia. 1 2 3 Kolmen alkion taulukossa ei ole tilaa arvolle 4 => virhe!! Syksy 2006 9

Vakioksi määritelty taulukko const int days[] ={1, 2, 3, 4, 5, 6, 7} osoittimen days tyyppi: const int * const Merkkijonovakiot: char nimi[] = Pekka ; nimi Pekka\0 char *nimet[] = { Maija, Jussimatti }; nimet Maija\0 Jussimatti\0 Syksy 2006 10

Taulukon kopiointi for (i=0; i<size; i++) x[i] = y[i]; Oltava saman kokoisia! Entä jos eivät ole? kokox=sizeof(x); kokoy = sizeof(y); if (kokox < kokoy) koko = kokox else koko = kokoy; koko = kokox < kokoy? kokox: kokoy; for (i=0; i<koko; i++) x[i] = y[i]; Syksy 2006 11

Taulukko parametrina funktion määrittelyssä voi käyttää: int minit(double arr[], int size); int minip(double *arr, int size); Funktion sisällä taulukkoparametreja käsitellään aina osoittimina => Taulukon kokoa ei voi kysyä näin! sizeof( arr) (= osoitinmuuttujan koko) Syksy 2006 12

Esimerkki: maxmin palauttaa taulukon maksimi ja minimiarvon int maxmin (double arr[], int size, double *max, double*min) { double *p if (arr==null size <= 0) return 0; for (*max=*min = arr[0], p = arr+1; p<arr + size; p++) { if(*max <*p) *max= *p; if (*min >*p) *min = *p; } return 1; } Kutsu: maxmin(x, SIZE, &max, &min); Mitä tekee seuraava kutsu? maxmin(x+3, 5, &max, &min); Syksy 2006 13

Paikalliset static-taulukot static char* opnimi(int n) { static char* operaattori [] = { lvalue, rvalue, push, +, - }; return operaattori[n]; } static => funktion yksityinen ja pysyvä taulukko Varo roikkumaan jääviä osoittimia! char *setname (int i){ } char name1[] = Maija ; char name2[] = Jussi ; if (i=0) return name1; return name2; Paikalliselle muuttujalle varataan tilaa pinosta joka kutsukerralla erikseen. char *p = setname(1); Osoitin p jää osoittamaan siihen kohtaan pinoa, josta tällä kertaa varattiin tilat, mutta joka funktion suorituksen jälkeen vapautettiin. Syksy 2006 14

Mielivaltaisen pitkän rivin lukeminen Varataan tarpeeksi suuri muistilohko ja toivotaan sen riittävän. Varataan esim. 80 merkin muistilohko ja aina tarvittaessa kasvatetaan riville varatun muistilohkon pituutta (dynaaminen taulukko) Käytetään rekursiivista funktiota: aina kun varattu (esim. 80 merkin) muistialue on täynnä ja rivi yhä jatkuu, niin funktio kutsuu itse itseään. Edellisen kutsun muistialue jää talteen pinoon ja uusi suorituskerta varaa uuden muistialueen pinosta. Syksy 2006 15

#define KOKO 80 int luerivi(file *in, char **tulos){ char puskuri[koko]; int c, i, base; /*luettu merkki, indeksimuuttuja, apumuuttuja */ static int luettu = 0; /* tämän rivipätkän koko */ for (i=0; i< KOKO; i++) { c = fgetc(in); if (c==eof) { } /*virhetilanne */ if (c== \n ) break; /*rivi loppui*/ puskuri[i] = c; } luettu += i; if (c!= EOF && c!= \n ){ /*vielä luettavaa */ if (luerivi(in, tulos) == 0) { luettu=0; return 0} } else { /* kaikki luettu */ if ((*tulos = malloc((luettu+1) *sizeof(char))) == NULL) { luettu= 0; return 0;} (*tulos)[koko]= \0 ; /* NULL-merkki viimeiseksi */ } base = luettu -i; memcpy(*tulos +base, puskuri, i) luettu -=i; return 1; } Esimerkki: mielivaltaisen pituisen rivin lukeminen rekursiivisesti Kukin kutsukerta kopioi lukemansa puskurin oikeaan paikkaan yhteistä muistitilaa. Luetaan korkeintaan 80 merkkiä puskuriin. Joka kutsukerralla eri puskuri, joka jää talteen pinoon. Rekursiivinen kutsu Tämä suoritetaan vain kerran: kun viimeinen pätkä riviä on luettu! Vertaa rekursiivinen kertoman laskeminen tito-kurssilla!

pino puskuri 1. Kutsu Esimerkki jatkuu: luettu=80 - pinon käyttö i =80 - muistilohkon täyttö puskuri 2. kutsu luettu=160 i =80 puskuri 3. Kutsu i =80 luettu=240 puskuri 4.Kutsu (tässä rivi i =60 loppui) Kun rivin pituus on 300 merkkiä luettu=300 *tulos Kaikilla kutsukerroilla: base = luettu -i; memcpy(*tulos +base, puskuri, i)

Moniulotteinen taulukko C:n moniulotteiset taulukot ovat yksiulotteisia taulukoita, joiden alkiot ovat taulukoita int t[3][2] = { {1,2},{11,12}, {21,22}}; 0 1 2 0 1 1 2 11 12 21 22 for (i=0; i<3; i++) { for (j = 0; j<2; j++) printf ( t[%d][%d] = %d\t, i, j, t[i][j]); putchar( \n ); } t[0][0] = 1 t[0][1] = 2 t[1][0] = 11 t[1][1] = 12 t[2][0] = 21 t[2][1] = 22 Syksy 2006 18

static char paivat [2][13] ={ {0, 31, 28, 31, 30, 31,30,31, 30, 31,30, 31}, {0, 31, 29, 31, 30, 31,30,31, 30, 31,30, 31} }; lkm = paivat[karkaus][2]; Kun karkaus ==0, niin lkm = 28, kun karkaus ==1, niin lkm = 29 Syksy 2006 19

void* malloc (size_t koko); Dynaaminen taulukko void* calloc (size_t koko); void free( void* pt); void* realloc(void* pt, size_t koko); Käytetään dynaamista muistin varaamista (malloc, calloc) Kun taulukolle varattu muistilohko on täynnä eikä siihen enää mahdu alkioita, Yritetään kasvattaa jo varattua muistilohkoa varaamalla lisää muistia heti sen sen perästä. Jos tämä ei onnistu, niin varataan jostain muualta muistista suurempi muistilohko, jonne kopioidaan pieneksi käyneen muistilohkon tiedot, ja vapautetaan tämän varaama muistitila. Voidaan käyttää funktiota realloc tai laatia itse funktio, joka varaa tarvittaessa muistia (malloc, calloc), suorittaa kopioinnin ja vapauttaa (free) turhaksi käyneen muistilohkon. void on geneerinen osoitintyyppi a pointer to something, but we don t know yet to what kind of thing Kopioidut arvot Syksy 2006 20

malloc-funktio (void* malloc (size_t sz);) calloc-funktio (void* calloc(size_t n, size_t sz);) (char*) malloc(4*sizeof(char)); if((p = malloc(4* sizeof(char))) == NULL).. char* calloc(4, sizeof(char)); if((p = calloc(4, sizeof(char))) == NULL).. Muistia ei ole alustettu, se sisältää mitä, siihen on sattunut jäämään. char* 0 0 0 0 Muisti on nollattu. Syksy 2006 21

dangling pointer : Jää osoittamaan poistettuun muistialueeseen. Muistin vapauttaminen: free (void free( void* pt); ) Vapauttaa osoittimen osoittaman muistilohkon Mistä se tietää lohkon koon? Lohkoa varattaessa (malloc, calloc) sen koko on talletettu muistiin juuri ennen lohkon alkua Lohkon koko Vain calloc:lla ja malloc:lla varattujen alueiden vapauttamiseen Vapauta kukin alue vain yhden kerran! Syksy 2006 22 pt

Taulukon koon muuttaminen: realloc (void* realloc(void* pt, size_t sz);) malloc- tai calloc-funktiolla varatun muistilohkon, esim. taulukon, kokoa voidaan sekä suurentaa että pienentää. Lohkon koko lptr Pienentäminen: 32 15 27 36 49 65 89 108 lptr = realloc(lptr, 3*sizeof(long)); Lohkon koko lptr vapaa muistialue 16 15 27 36 16 65 89 108 sen koko Syksy 2006 23

Varatun muistilohkon koon kasvattaminen realloc-funktiolla (1) Käyttöjärjestelmä pitää kirjaa malloc:lla ja calloc:lla varattujen alueiden koosta ja tietää myös, mitkä alueet ovat vapaana Lohkon koko lptr vapaa muistialue lptr=realloc(lptr, 2*sizeof(long)); 16 15 27 36 16 65 89 108 sen koko Lohkon koko lptr vapaa muistialue 24 15 27 36 16 65 8 108 sen koko Syksy 2006 24

Varatun muistilohkon koon kasvattaminen realloc-funktiolla (1) realloc onnistuu aina, kun vain jossain on vapaata muistia tarvittava määrä! Jos kasvatettavan lohkon perässä ei ole riittävästi vapaata tilaa, niin varataan muistista riittävän suuri vapaa tila, kopioidaan sinne taulukon alkiot ja vapautetaan taulukolle alun perin varattu tila. Lohkon koko lptr vapaa muistialue lptr=realloc(lptr, 10*sizeof(long)); 16 15 27 36 16 65 89 108 Varataan uusi lohko 44 kopioidaan sen koko Kopiointi on kallis operaatio ja sitä tulisi välttää! 15 27 36???????????????????????????????????? Ongelmana vielä muut osoittimet: nehän osoittavat vanhaan lohkoon! ja vapautetaan vanha lohko: 32 15 27 36 16 65 89 108 Syksy 2006 25

Dynaamisen taulukon käyttö alkiot Lajittelussa printf( Montako alkiota lajitellaan?\n ); scanf( %i, &n); if ((alkiot = malloc(n * sizeof(float))) == NULL) mallocerror(); read_file(alkiot, n); /*luetaan alkiot*/ sort_data(alkiot, n); Eri pituisten merkkijonojen (sanojen tai nimien) tallettaminen taulukkoon scanf( %20, buf); /*sanan lukeminen*/ len = strlen(buf); /*sanan pituus */ if ((sanat[i] =malloc((len+1) * sizeof(char))) == NULL) mallocerror();; strcpy (sanat[i], buf); sanat C\0 Java\0 Pascal\0 Ada\0 Syksy 2006 26

Monimutkaisia määritelmiä? [] merkeillä korkeampi presedenssi kuin *-merkillä double *f[2]; f doublemuuttujia double (*f2[2])() double (*f3())[] f2 f3 on funktio, joka palauttaa osoittimen double-taulukkoon. Funktioita, jotka palauttavat double-arvon double *(f4[])() VIRHE! Ei voi olla funktiotaulukkoa! Vain osoitteita funktioihin. Syksy 2006 27

Binääritiedostot Tiedon tiiviiseen tallettamiseen Ei rivirakennetta => ei voida käsitellä standardeilla välineillä Eivät suoraan ihmisen luettavissa Usein eivät ole siirrettäviä koneesta toiseen fopen( tied1, wb ); fopen( tied2, rb ); Syksy 2006 28

#include <stdio.h> Operaatioita binääritiedostoille hajasaantitiedostoja (random access) Kun tiedosto on avattu, kahva osoittaa sen hetkiseen käsittelykohtaan Operaatioita long ftell(file *f) palauttaa käsittelykohdan int fseek(file *f, long offset, int mode) siirtää käsittelykohtaa siirtymän (offset) verran mode kertoo mistä kohtaa siirto alkaa: SEEK_SET tiedoston alusta SEEK_CUR nykykohdasta SEEK_END lopusta rewind(file *f) kelaa tiedoston alkuun Syksy 2006 29

Esimerkki: Annetun tiedoston koon selvittäminen long filesize (const char *filename) { FILE *f; long size; if ((f = fopen(filename, rb ))== NULL) return -1L; if (fseek(f, 0L, SEEK_END) == 0) { /* OK!*/ size = ftell(f); if (fclose(f)==eof) return -1L; return size; } fclose(f); return -1L; } Syksy 2006 30

Binäärinen lukeminen ja kirjoittaminen = oliolohkojen kirjoittaminen ja lukeminen #include <stdio.h> size_t fread (void *buf, size_t elsize, size_t count, FILE *in); lukee tiedostosta in count:n ilmoittaman määrän oliolohkoja muistilohkoon, johon buf osoittaa. Oliolohkon koon ilmoittaa elsize. Palauttaa luettujen objektien määrän. Virhetilanteessa palauttaa nollan. size_t fwrite (void *buf, size_t elsize, size_t count, FILE *out); Kirjoittaa tiedostoon out count:n ilmoittaman määrän oliolohkoja buf:n osoittamasta muistilohkosta. Oliolohkon koon ilmoittaa elsize. Olettavat, että tiedosto on jo avattu oikeaa toimintaa (lukemista tai kirjoittamista) varten. Syksy 2006 31

Tekstitiedostosta binääritiedostoon ja binääritiedostosta tekstitiedostoon Teksti => binääri while (fscanf(in, %lf, &d) ==1) if (fwrite (&d, sizeof(double), 1, out)!=1) {error; return} Binääri => teksti while(fread(&d, sizeof(double), 1, in) ==1) { i++; if (i== Max) { putchar( \n ); i = 0; } fprintf(out, %f\t, d);.. } Syksy 2006 32