Tiedostokahva (filehandle) Tekstitiedostot. Tiedoston avaaminen. Tiedoston käyttötavat. Tekstitiedostot ja niiden käyttö. C-ohjelmointi, kevät 2006

Samankaltaiset tiedostot
Tiedostokahva (filehandle) Tekstitiedostot. Tiedoston avaaminen. Tiedoston käyttötavat. Tekstitiedostot ja niiden käyttö. C-ohjelmointi, syksy 2008

Tekstitiedostot ja niiden käyttö

Tekstitiedostot ja niiden käyttö

ehdollinen kääntäminen

ehdollinen kääntäminen

Tiedostot. Tiedostot. Tiedostot. Tiedostot. Tiedostot. Tiedostot

Moduli 5: Kehittyneitä piirteitä

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

Binäärioperaatiot Tiedostot ja I/O

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

Binäärioperaatiot Tiedostot ja I/O

Loppukurssin järjestelyt

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

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

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

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

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

Loppukurssin järjestelyt C:n edistyneet piirteet

ICS-C2000 Tietojenkäsittelyteoria Kevät 2016

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

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

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

C-kurssi kevät t Luento 2: tyypit, rakenteet, makrot

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

C-ohjelmointi, syksy 2006

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

Lyhyt kertaus osoittimista

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

13. Loogiset operaatiot 13.1

Ohjausrakenteet. Valinta:

Ohjelmoinnin perusteet Y Python

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

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

Tietorakenteet ja algoritmit

Tietorakenteet ja algoritmit

Luento 5. Timo Savola. 28. huhtikuuta 2006

C-ohjelmoinnin peruskurssi. Pasi Sarolahti

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

Tietueet. Tietueiden määrittely

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Rakenne. C-ohjelmointi: Tietorakenteita ja tyyppejä. Tyyppimuunnoksia aritmeettisten tyyppien välillä. Tyyppimuunnokset. & (bitti and) Bittioperaatiot

Java-kielen perusteet

Java-kielen perusteita

TIETORAKENTEET JA ALGORITMIT

815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset

Ohjelmointiharjoituksia Arduino-ympäristössä

1.3Lohkorakenne muodostetaan käyttämällä a) puolipistettä b) aaltosulkeita c) BEGIN ja END lausekkeita d) sisennystä

C-ohjelmoinnin peruskurssi. Pasi Sarolahti

Modulaarisessa ohjelmoinnissa jaetaan ohjelma osiin (moduuleihin), jotka ovat yksinkertaisia ja lyhyitä.

Tietorakenteet ja algoritmit

5. HelloWorld-ohjelma 5.1

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

12. Javan toistorakenteet 12.1

Esimerkki 1: Kahviautomaatti.

Sisällys. 16. Ohjelmoinnin tekniikkaa. Aritmetiikkaa toisin merkiten. Aritmetiikkaa toisin merkiten

16. Ohjelmoinnin tekniikkaa 16.1

16. Ohjelmoinnin tekniikkaa 16.1

Ohjelmoinnin perusteet Y Python

C-kieli mahdollistaa hyvin tiiviin ja samalla sekavan tavan esittää asioita, kuitenkin hyvän ohjelman tulisi olla mahdollisimman helppolukuinen ja

C-ohjelmoinnin peruskurssi. Pasi Sarolahti

Sisällys. 17. Ohjelmoinnin tekniikkaa. Aritmetiikkaa toisin merkiten. for-lause lyhemmin

21. oppitunti. Esikäsittelijä. Osa. Esikäsittelijä ja kääntäjä

Tietotyypit ja operaattorit

12. Javan toistorakenteet 12.1

11. Javan toistorakenteet 11.1

Tähtitieteen käytännön menetelmiä Kevät 2009 Luento 5: Python

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

11. Javan valintarakenteet 11.1

Ohjelmoinnin perusteet Y Python

13. Loogiset operaatiot 13.1

tietueet eri tyyppisiä tietoja saman muuttujan arvoiksi

5. HelloWorld-ohjelma 5.1

AS C-ohjelmoinnin peruskurssi 2013: C-kieli käytännössä ja erot Pythoniin

2. C-kieli ja ongelmanratkaisu

C-ohjelmointi, kevät Merkkijonot Komentoriviparametrit. Luento

IDL - proseduurit. ATK tähtitieteessä. IDL - proseduurit

Merkkijonot Komentoriviparametrit

ATK tähtitieteessä. Osa 3 - IDL proseduurit ja rakenteet. 18. syyskuuta 2014

7. Näytölle tulostaminen 7.1

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

Java-kielen perusteet

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

Ohjelmoinnin perusteet Y Python

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

Kieliteknologian ATK-ympäristö Kuudes luento

Ohjelmoinnin perusteet Y Python

Sisällys. 12. Näppäimistöltä lukeminen. Yleistä. Yleistä

12. Näppäimistöltä lukeminen 12.1

Osoittimet ja taulukot

C-ohjelmointi, syksy Merkkijonot Komentoriviparametrit. Luento C-ohjelmointi Syksy

Alkuarvot ja tyyppimuunnokset (1/5) Alkuarvot ja tyyppimuunnokset (2/5) Alkuarvot ja tyyppimuunnokset (3/5)

Harjoitus 4 (viikko 47)

Tähtitieteen käytännön menetelmiä Kevät 2009 Luento 6: Python

System.out.printf("%d / %d = %.2f%n", ekaluku, tokaluku, osamaara);

Ohjelmoinnin perusteet Y Python

C-ohjelmoinnin peruskurssi. Pasi Sarolahti

ATK tähtitieteessä. Osa 4 - IDL input/output. 19. syyskuuta 2014

Sisällys. 12. Javan toistorakenteet. Yleistä. Laskurimuuttujat

Transkriptio:

, kevät 2006 qtekstitiedostot ja niiden käyttö qesikääntäjä, makrot ja ehdollinen kääntäminen Luento 3 31.1.2006 Kevät 2006 Liisa Marttinen & Tiina Niklander 1 Tekstitiedostot ja niiden käyttö Tekstitiedosto Tiedostokahva (Müldnerin kirjassa luku 5) binääritiedosto Tiedoston avaaminen ja sulkeminen Tiedoston käyttötavat Virhetilanteet avauksessa ja sulkemisessa Standarditiedostot Perus I/O-operaatiot tiedostoille Lukeminen ja kirjoittaminen Esimerkkejä ja idiomeja Kevät 2006 Liisa Marttinen & Tiina Niklander 2 Tekstitiedostot Tiedostot ovat pelkkiä tavujonoja. Tiedoston päättää tiedoston lopetusmerkki EOF. Kahdenlaisia tiedostoja; ero niiden käsittelyssä Tekstitiedostot käsitellään riveittäin. Joka rivin lopussa on rivin loppumismerkki ( uuden rivin alkamismerkki ) \n. Binääritiedostossa ei ole mitään erityistavuja. Eri käyttöjärjestelmät käyttävät eri tapoja ilmaisemaan rivin tai tiedoston päättymistä! Tiedostokahva (filehandle) Tiedostokahva on tiedostoon osoittava osoitin (pointer), jonka avulla tiedostoa käsitellään. Tiedostokahvan määrittely: FILE*kahva; FILE *tied1, *tied2; typedef FILE* P_FILE; /*määritellään ensin P_FILE tied1, tied2; tiedostokahvatyyppi */ Kevät 2006 Liisa Marttinen & Tiina Niklander 3 Kevät 2006 Liisa Marttinen & Tiina Niklander 4 Tiedoston avaaminen Ennen käyttöä tiedosto on avattava käyttäen funktiota fopen(). Avaus yhdistää tiedoston tiedostokahvaan. Avattaessa ilmoitetaan tiedoston nimi sekä tiedoston käyttötapa. kahva = fopen( testitiedosto, r ); tied1 = fopen( MyFile.txt, w ); tied2 = fopen( test.out, wb ); Kevät 2006 Liisa Marttinen & Tiina Niklander 5 Tiedoston käyttötavat "r" lukeminen jo olemassa olevasta tiedostosta "w" kirjoittaminen: olemassa olevan tiedoston päälle (overwrite) tai uuteen tiedostoon, joka luodaan vasta tässä (create) "a" kirjoittaminen joko olemassa olevan tiedoston perään (append) tai uuteen luotavaan tiedostoon "r+" lukeminen ja kirjoittaminen, muuten kuten "r" "w+" lukeminen ja kirjoittaminen, muuten kuten "w" "a+" lukeminen ja kirjoittaminen, muuten kuten "a" Jos halutaan käsitelllä tiedostoa binäärimuotoisesti, niin lisätään ylläoleviin merkki b: "r+b. Jos tiedosto on avattu sekä lukemista että kirjoittamista varten, I/O-operaatioiden välillä on aina kutsuttava jotain funktioista: fseek(), fsetpos(), rewind() tai fflush(). Kevät 2006 Liisa Marttinen & Tiina Niklander 6 1

Tiedoston avaaminen voi epäonnistua! Jos tiedoston avaaminen ei onnistu, niin fopen palauttaa arvon NULL (= erityinen nolla-arvo), muuten osoittimen tiedostoon eli tiedostokahvan. Joka kerta tiedostoa avattaessa on siis varmistuttava, että avaus onnistui! if (filehandle = fopen(fname, fmode)) == NULL) /* toiminta virhetilanteessa */ Kevät 2006 Liisa Marttinen & Tiina Niklander 7 Tiedostonimet, avattujen tiedostojen maksimimäärä Tiedostonimi voi myös olla polkunimi. Eri käyttöjärjestelmissä on erilaisia polkunimiä. Näissä voi olla merkkejä, joilla on erityismerkitys C-kielessä. (Esim. DOS-järjestelmän \-merkki) \ on escape-merkki, joka muuttaa seuraavan merkin merkityksen => DOS:n \-merkki korvattava \\-merkeillä FILENAME_MAX (stdio.h) kertoo tiedostonimen maksimipituuden. Avattujen tiedostojen määrä järjestelmässä on rajoitettu: enintään FOPEN_MAX (stdio.h) tiedostoa. Kevät 2006 Liisa Marttinen & Tiina Niklander 8 Tiedoston sulkeminen Avattu tiedosto täytyy sulkea, kun sitä ei enää tarvita. Tiedosto suljetaan käyttäen funktiota fclose(). Parametrina annetaan suljettavan tiedoston kahva. Jos sulkeminen epäonnistuu, niin fclose palauttaa EOF-merkin. Aina varmistettava onnistuminen! if (fclose(tied1) == EOF) /* toiminta, kun tiedostoa ei saada suljettua */ Kevät 2006 Liisa Marttinen & Tiina Niklander 9 Standarditiedostot: stdin, stdout ja stderr Aina käytettävissä olevat ennaltamääritellyt, tiedostoonsa kiinnikolvatut tiedostokahvat Ei tarvitse erikseen avata eikä sulkea! stdin standardisyöttövirta; yleensä näppäimistö stdout standarditulostusvirta; yleensä näytölle stderr standardivirhetulostusvirta; eri kuin normaalitulostus FILE *inkahva;. inkahva = stdin; /* inkahva on synonyymi stdin-kahvalle */ Kevät 2006 Liisa Marttinen & Tiina Niklander 10 I/O-operaatiot tiedostoille (perusoperaatiot) Perusoperaatiot ovat hyvin samankaltaisia kuin pääte-i/o:ssa tai formatoidussa I/O:ssa käytetyt: int fgetc (filehandle) int fputc (int, filehandle) int fscanf (filehandle,..) ~ int getchar() ~ int putchar(int) ~ int scanf( ) int fprintf (filehandle, ) ~ int printf( ) Kevät 2006 Liisa Marttinen & Tiina Niklander 11 Merkin ja luvun lukeminen tiedostosta Yhden merkin lukeminen tiedostosta if ((c=fgetc(filehandle)) == EOF) /* toiminta tiedoston loppuessa */ Yhden luvun lukeminen tiedostosta if (fscanf (filehandle, %d, &i)!= 1) /* toiminta lukemisen epäonnistuessa */ Kevät 2006 Liisa Marttinen & Tiina Niklander 12 2

Esimerkki: Ohjelma lukee kolme lukua tiedostosta luvut ja tulostaa niiden summan näytölle. int main() { FILE *f; double x, y, z; Tiedoston avaamisfraasi! if((f = fopen( luvut", "r")) == NULL) { fprintf(stderr, Ei avaudu: %s\n", luvut"); return EXIT_FAILURE; Kevät 2006 Liisa Marttinen & Tiina Niklander 13 if(fscanf(f, "%lf%lf%lf", &x, &y, &z)!= 3) { fprintf(stderr, Tiedoston lukeminen epäonnistui\n"); return EXIT_FAILURE; Tiedoston Idiom? lukemisfraasi printf("%f\n", x + y + z); if(fclose(f) == EOF) { fprintf(stderr, "Sulkeminen epäonnistui\n"); return EXIT_FAILURE; Tiedoston sulkemisfraasi Rivin loppu ja tiedoston loppu /* Lukee tiedostosta yhden rivin ja tulostaa sen näytölle */ while((c = fgetc(tkahva))!='\n') if (c == EOF) else putchar(c); if(c!= EOF) putchar(c); /* Etsitään vain rivin loppu */ while((c = fgetc(tkahva))!='\n ); /* Lasketaan rivin merkkien määrä */ while((c = fgetc(tkahva))!='\n ) ccount++; Kevät 2006 Liisa Marttinen & Tiina Niklander 15 Laadi ohjelma, joka laskee ja tulostaa tiedoston testi.txt rivien lukumäärän. q Määrittelyt q Avaa tiedosto testi.txt q tiedoston rivien lukumäärän laskeminen q Niin kauan kuin tiedostoa riittää (eli ei vielä EOF-merkki) q Jos \n merkki, niin kasvata rivien lukumäärää. q Tulosta lukumäärä näytölle q Sulje tiedosto testi.txt Kevät 2006 Liisa Marttinen & Tiina Niklander 16 ungetc, feof ungetc (char, filehandle); Palauttaa luetun merkin tiedostoon eli laittaa sen takaisin tiedoston lukupuskuriin, josta se luettavissa uudestaan. Itse tiedostoa ei muuteta. while (ehto (c = fgetc (tiedostokahva))) prosessoi c; ungetc (c, tiedostokahva); feof(filehandle); Testaa tiedoston loppumista. Palauttaa 0, jos tiedosto on loppu, muuten jonkun muun arvon. Tiedoston avaaminen: if ((filehandle = fopen(fname, fmode)) ==NULL) /* failed */ if (close(filehandle) == EOF). /* failed */ Tiedoston sulkeminen if ((c = fgetc(filehandle)) == EOF) /* error */ Yhden merkin lukeminen if (fscanf (filehandle, %d, i)!=1) /* error */ Yhden luvun lukeminen while ((c= fgetc(filehandle))!= \n ) while ((c= fgetc(filehandle))!= EOF) Rivin loppuun lukeminen Tiedoston loppuun lukeminen Fraaseja tiedoston käsittelyyn Kevät 2006 Liisa Marttinen & Tiina Niklander 17 3

Esikääntäjä, makrot ja ehdollinen kääntäminen (Mülderin kirjan luku 6) C-esikääntäjä Makrot Parametrittomat makrot Parametrilliset makrot Ennaltamääritellyt makrot Ulkoisten tiedostojen sisällyttämimen Ehdollinen kääntäminen Eri tavat toteuttaa Käyttö virheenjäljityksessä Assert-makro ja sen käyttö Käyttö otsaketiedostoissa Käyttö siirrettävyyden lisäämiseksi Kevät 2006 Liisa Marttinen & Tiina Niklander 19 C-esikääntäjä #-merkillä alkavat komentorivit tarkoitettu esikääntäjälle => oma syntaksi käsitellään ennen kääntämistä Mihin käytetään? Makrot: korvataan teksti toisella tekstillä Ulkoisten tiedostojen liittäminen #include <stdio> Ehdollinen kääntäminen: vain osa lähdetiedostoa käännetään tietyn ehdon ollessa voimassa; hyötyä virheiden etsinnässä Kevät 2006 Liisa Marttinen & Tiina Niklander 20 Makrotyypit Parametrittomat makrot Lyhennemerkintä; makronimi korvataan aina samalla tekstillä Parametrilliset makrot Parametrit vaikuttavat korvaustekstiin => monipuolisempi, mutta helposti myös yllättäviä sivuvaikutuksia Ennaltamääritellyt makrot C-toteutuksessa jo sisällä Hyötyä virhetilanteessa Kevät 2006 Liisa Marttinen & Tiina Niklander 21 Parametriton makro #define makronimi makroarvo #define PI 3.14 #define PII 3.14159265358979323\ 846264338327950 #define SCREEN_W 80 #define SCREEN_H 25 MakroNimi ISOILLA KIRJAIMILLA! MakroArvo rivin loppuun ( \n -merkkiin asti) \ = jatkuu seuraavalle riville Huomaa: ei =-merkkiä eikä puolipistettä(;)! Kevät 2006 Liisa Marttinen & Tiina Niklander 22 Makronimen korvaus makroarvolla Esikääntäjä korvaa lähdetiedostossa jokaisen makronimi esiintymän makroarvon tekstillä. Esimerkkejä makron käytöstä #define PROMPT printf("enter real value: ") #define SKIP while(getchar()!= '\n'); #define PI 3.14 i=pi; korvaus => i=3.14 #define PII =3.14; i=pii; korvaus => i ==3.14;; VÄÄRIN!!!! Käytä runsaasti sulkuja, etenkin aritmeettisissa lausekkeissa! #define A 2 + 4 Haluttiinko todella tätä? #define B A * 3 => B = 2 + 4 * 3 = 14 #define A (2 + 4) #define B (A * 3) => B = ((2+4) * 3) =18 Kevät 2006 Liisa Marttinen & Tiina Niklander 23 Kevät 2006 Liisa Marttinen & Tiina Niklander 24 4

Parametrilliset makrot #define makronimi(parametrit) makroarvo esim. #define READ(c, tkahva) (c=fgetc(tkahva)). if (READ(char, tied1) == x ) => if ( (char = fgetc(tied1))== x ) Varovaisuutta, huolellisuutta makrojen käytössä! Makroja käytettäessä syntyy helposti sivuvaikutuksia Makro voi helpottaa kirjoittamista, mutta koodin luettavuus voi kärsiä! <eri asia kuin> if ( char = fgetc(tied1)== x ) =>>> Siis käytä runsaasti sulkuja! #define SQR(x) (x*x) SQR(z+1); => (z+1*z+1) #define SQR(x) ((x)*(x)) SQR(z+1); => ((z+1)*(z+1)) Kevät 2006 Liisa Marttinen & Tiina Niklander 25 Kevät 2006 Liisa Marttinen & Tiina Niklander 26 #-merkin muu käyttö Komenteissa ja merkkijonovakioissa olevia makronimiä ja parametreja ei hyväksytä! määrittelyssä parametrin eteen pitää laittaa #-merkki, jolloin sen arvo makron laajennuksessa laitetaan lainausmerkkien sisään #parametri => parametri Merkkien yhteenliittäminen #define TEMP(i) temp ##i TEMP(1) = TEMP(2) => temp1 = temp2 Kevät 2006 Liisa Marttinen & Tiina Niklander 27 #define EMPTY (maxused == 0) #define ASSERT if (!(EMPTY? current == 0 : \ 0 < current && current <=maxused)) {\ fprintf(stderr, invariant failed; current = %d \t; \ maxused= %d\n, current, maxused); \ exit(1); EMPTY? current == 0 : 0 < current && current <=maxused ehdollinen lauseke Kevät 2006 Liisa Marttinen & Tiina Niklander 28 Ennaltamääritellyt makrot 4 kappaletta LINE FILE TIME STDC lähdekoodin tämän rivin numero tämän lähdekoodin nimi käännösaika 1, jos kääntäjä noudattaa ANSI C:tä if (n>10) { /* virhetilanne */ fprintf (stderr, liian suuri n:n arvo tiedoston %s return EXIT_FAILURE; rivillä %d! \n", FILE, LINE ); Makromäärittelyn purkaminen #undef PI jos halutaan määritellä uudestaan PI, niin entinen määrittely on purettava Muuten voi tulla ongelmia! Makromäärittelyn voi purkaa myös kääntäjän komentorivillä Kevät 2006 Liisa Marttinen & Tiina Niklander 29 Kevät 2006 Liisa Marttinen & Tiina Niklander 30 5

Ulkoisen tiedoston lisääminen lähdekoodiin kaksi eri muotoa: miten lisättävä tiedostoa haetaan hakemistosta #include filename /* käyttäjän oma tiedosto, haetaan ensin nykyhakemistosta*/ #include <filename> /*järjestelmän tiedosto, haetaan ensin systeemihakemistosta*/ Standard Header Files stdio.h - the basic declarations needed to perform I/O ctype.h - for testing the state of characters math.h - mathematical functions, such as abs() and sin() kootaan yleensä otsaketiedostoiksi.h Kevät 2006 Liisa Marttinen & Tiina Niklander 31 Kevät 2006 Liisa Marttinen & Tiina Niklander 32 Ehdollinen kääntäminen (Conditional Compilation) = tietyssä tilanteessa, tietyn ehdon ollessa tosi osa koodia jätetään kääntämättä Käytetään virheenjäljityksessä, otsaketiedostoissa siirrettävää koodia tuotettaessa Kaksi eri tapaa #ifdef macroname part1 part2 #ifndef macroname partl part2 #if constantexpression1 part 1 #elif constantexpression2 part2 part3 Kevät 2006 Liisa Marttinen & Tiina Niklander 33 #if constantexpression1 part 1 #elif constantexpression2 part2 part3 #if defined ( STDC ). #error Jotain pielessä - voi olla useita #elif osia - voi puuttua #if defined (name) /*onko name määritelty?*/ #error textmessage Käyttö virheenjäljityksessä Testikoodin poisjättäminen Ehdollinen kääntäminen on poiskommentointia parempi tapa poistaa kulloinkin turhat koodin osat. esim. virheenjäljitystä varten lisätyt tulostuskomennot C:ssä ei saa olla sisäkkäisiä kommentteja! # if 0 poisjätettävä osa Näin sama lähdekoodi voi toimia sekä testiversiona että tuotantoversiona! Kevät 2006 Liisa Marttinen & Tiina Niklander 35 #define DEB /* vain määritelty */ /*jokin virheenjäljitys lause esim. tulostuslause */ printf("value of i = %d", i); /* tuotantokoodia */ Kääntäjän komentorivillä! gcc UDEB prog.c makromäärittely poispäältä gcc DDEB prog.c makromäärittely päälle Kevät 2006 Liisa Marttinen & Tiina Niklander 36 6

Esimerkkejä: Example int main() { int i, j; printf("enter two integer values: "); if(scanf(%d%d, &i, &j)!= 2) return EXIT_FAILURE; printf("entered %d and %d\n", i, j); printf("sum = %d\n", i + j); Mitä hyötyä! int i, j; int res; if( (res = scanf(%d%d, &i, &j) ) )!= 2 ) Enemmän informaatiota! Example { switch(res) { case 0: printf("both values were wrong\n"); case 1: printf("ok first value %d\n", i); case EOF: printf("eof\n"); case 2: printf("both OK\n"); break... int main() { const char SENTINEL =. ; int aux, maxi=0; UG printf( Virheenjäljitys päällä: kopioidaan kaikki merkit\n ); while(1) { if ((aux = getchar()) == EOF aux == SENTINEL) UG putchar(aux); putchar( \n ); if (aux > maxi) UG printf( Suurin merkki on nyt: %c\n, aux); maxi = aux; UG putchar( \n ); printf( Suurin merkki on: %d\n, maxi); Assert makro virheenjäljityksessä (1) assert (int lauseke) (assert.h) Diagnostiikkatietojen kirjoittaminen standardivirhetiedostoon (stderr) Jos lauseke on epätosi (false, 0), niin virhetiedostoon kirjoitetaan lauseke, lähdekooditiedoston nimi ja rivin numero: Assertion failed: ehto, file tiednimi, line rivinro (Tiedostonimi ja rivinumero saadaan makroista FILE ja LINE.) ja ohjelman suoritus keskeytetään abort()-funktiolla. assert-makroilla varmistetaan, että ohjelma toimii kuten sen loogisesti oletetaan toimivan: ennakkoehtoja, jälkiehtoja, oletuksia muuttujien arvoista. Esimerkkejä lausekkeista: assert (i>=0) assert (b*b 4*a*c >=0 assert (0>=i && i <size) Kevät 2006 Liisa Marttinen & Tiina Niklander 40 Assert makro virheenjäljityksessä (2) Assert-makron toimintaa säätelee makron NDEBUG ( = no debug) määrittely. Jos NDEBUG on määritelty, niin assert ei tee mitään. Oletusarvoisesti assert() on käytössä ja valvoo ohjelman toimintaa. Tarkistukset poistetaan ohjelmasta määrittelemällä makrondebug joko makromäärittelyssä #define NDEBUG tai kääntäjän parametrina gcc DNDEBUG. Kevät 2006 Liisa Marttinen & Tiina Niklander 41 Esimerkki assert-koodista /* Assert.cc for GNU C/C++ */ /* #ifdef ASSERT # ifndef NDEBUG */ #ifdef ASSERT void AssertionFailure(char *exp, char *file, char *basefile, int line) { if (!strcmp(file, basefile)) { fprintf(stderr, "Assert(%s) failed in file %s, line %d\n", exp, file, line); else { fprintf(stderr, "Assert(%s) failed in file %s (included from %s), line %d\n", exp, file, basefile, line); Kevät 2006 Liisa Marttinen & Tiina Niklander 42 7

Makro otsaketiedostojen suojana #include<assert.h> void open_record(char *record_name) { assert(record_name!=null); /* Rest of code */ int main(void) { open_record(null); Kevät 2006 Liisa Marttinen & Tiina Niklander 43 Ehdollisella kääntämisellä varmistetaan, että otsaketiedosto käännetään vain kerran: kukin otsaketiedostoa ympäröidään makrolla, joka suoritetaan vain kerran. Useasta osasta koottavaan ohjelmaan tulee helposti sama otsaketiedosto useaan kertaan => käännösvirhe Makro nimetään otsaketiedoston mukaan: screen.h => käytetään makronimeä SCREEN_H #ifndef SCREEN_H #define SCREEN_H /*otsaketiedoston sisältö */ #include screen.h #include screen.h Käännetään vain kerran! Kevät 2006 Liisa Marttinen & Tiina Niklander 44 Mitä seuraava ohjelma tulostaa? Ehdollinen kääntäminen ja siirrettävyys Erilaisissa ympäristöissä toimivien ohjelmien kehittämiseen: #if IBMPC /* ehtolauseke */ #include <ibm.h> #include <generic.h> #ifdef IBMPC /*makromäärittely*/ typedef int MyInteger typedef long MyInteger Kevät 2006 Liisa Marttinen & Tiina Niklander 45 #define LOW -2 #define HIGH (LOW+5) #define PR(arg) printf( %d\n, (arg)) #define FOR(arg) for(; (arg); (arg)--) #define SHOW(x) x int main(){ int i = LOW; int j = HIGH; FOR(j) switch(j) { case 1: PR(i++); case 2: PR(j); default: PR(i); printf ( \n%s\n, SHOW(3)); Mitä seuraava ohjelma tulostaa? #define LOW -2 #define HIGH (LOW+5) #define PR(arg) printf( %d\n, (arg)) #define FOR(arg) for(; (arg); (arg)--) #define SHOW(x) x int main(){ int i = LOW; int i = -2; int j = HIGH; int j = (-2 + 5); /* = 3*/ FOR(j) for (; (j); (j)--) switch(j) { case 1: PR(i++); printf( %d\n, (i++)); case 2: PR(j); printf( %d\n, (j)); default: PR(i); printf( %d\n, (i)); printf ( \n%s\n, SHOW(3)); 8