Tekstitiedostot ja niiden käyttö

Samankaltaiset tiedostot
Tekstitiedostot ja niiden käyttö

ehdollinen kääntäminen

ehdollinen kääntäminen

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

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

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

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

Binäärioperaatiot Tiedostot ja I/O

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

Loppukurssin järjestelyt

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

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

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

ICS-C2000 Tietojenkäsittelyteoria Kevät 2016

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

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

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

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

Lyhyt kertaus osoittimista

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.

Luento 5. Timo Savola. 28. huhtikuuta 2006

Tietorakenteet ja algoritmit

Tietorakenteet ja algoritmit

C-ohjelmoinnin peruskurssi. Pasi Sarolahti

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

Tietueet. Tietueiden määrittely

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

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

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

12. Javan toistorakenteet 12.1

5. HelloWorld-ohjelma 5.1

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

Esimerkki 1: Kahviautomaatti.

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

16. Ohjelmoinnin tekniikkaa 16.1

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

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

C-ohjelmointi, kevät Merkkijonot Komentoriviparametrit. Luento

Tietotyypit ja operaattorit

Merkkijonot Komentoriviparametrit

12. Javan toistorakenteet 12.1

11. Javan toistorakenteet 11.1

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

Muuttujien roolit Kiintoarvo cin >> r;

11. Javan valintarakenteet 11.1

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

13. Loogiset operaatiot 13.1

Ohjelmoinnin perusteet Y Python

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

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

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

2. C-kieli ja ongelmanratkaisu

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

Java-kielen perusteet

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

7. Näytölle tulostaminen 7.1

Merkkijonot Komentoriviparametrit

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

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Kieliteknologian ATK-ympäristö Kuudes luento

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

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

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

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

Osoittimet ja taulukot

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);

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

ITKP102 Ohjelmointi 1 (6 op)

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 1

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ä! Kevät 2006 Liisa Marttinen & Tiina Niklander 3 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 4 2

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 3

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 4

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 5

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 6

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 lukemisfraasi Idiom? printf("%f\n", x + y + z); if(fclose(f) == EOF) { fprintf(stderr, "Sulkeminen epäonnistui\n"); return EXIT_FAILURE; return EXIT_SUCCESS; Tiedoston sulkemisfraasi 7

Rivin loppu ja tiedoston loppu /* Lukee tiedostosta yhden rivin ja tulostaa sen näytölle */ while((c = fgetc(tkahva))!='\n') if (c == EOF) break; 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 8

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. Kevät 2006 Liisa Marttinen & Tiina Niklander 17 Tiedoston avaaminen: if ((filehandle = fopen(fname, fmode)) ==NULL) /* failed */ if (close(filehandle) == EOF). /* failed */ if ((c = fgetc(filehandle)) == EOF) /* error */ Tiedoston sulkeminen 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 9

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 10

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 11

Makronimen korvaus makroarvolla Esikääntäjä korvaa lähdetiedostossa jokaisen makronimi esiintymän makroarvon tekstillä. #define PI 3.14 i=pi; korvaus => i=3.14 #define PII =3.14; i=pii; korvaus => i ==3.14;; VÄÄRIN!!!! Kevät 2006 Liisa Marttinen & Tiina Niklander 23 Esimerkkejä makron käytöstä #define PROMPT printf("enter real value: ") #define SKIP while(getchar()!= '\n'); 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 24 12

Parametrilliset makrot #define makronimi(parametrit) makroarvo esim. #define READ(c, tkahva) (c=fgetc(tkahva)). if (READ(char, tied1) == x ) => if ( (char = fgetc(tied1))== x ) <eri asia kuin> if ( char = fgetc(tied1)== x ) =>>> Siis käytä runsaasti sulkuja! Kevät 2006 Liisa Marttinen & Tiina Niklander 25 Varovaisuutta, huolellisuutta makrojen käytössä! Makroja käytettäessä syntyy helposti sivuvaikutuksia Makro voi helpottaa kirjoittamista, mutta koodin luettavuus voi kärsiä! #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 26 13

#-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 14

Ennaltamääritellyt makrot 4 kappaletta LINE lähdekoodin tämän rivin numero FILE tämän lähdekoodin nimi TIME käännösaika STDC 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 ); Kevät 2006 Liisa Marttinen & Tiina Niklander 29 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 30 15

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*/ kootaan yleensä otsaketiedostoiksi.h Kevät 2006 Liisa Marttinen & Tiina Niklander 31 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() Kevät 2006 Liisa Marttinen & Tiina Niklander 32 16

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 #else part2 #ifndef macroname partl #else part2 #if constantexpression1 part 1 #elif constantexpression2 part2 #else part3 Kevät 2006 Liisa Marttinen & Tiina Niklander 33 #if constantexpression1 part 1 #elif constantexpression2 part2 #else part3 - voi olla useita #elif osia - #else voi puuttua #if defined (name) /*onko name määritelty?*/ #error textmessage #if defined ( STDC ). #else #error Jotain pielessä 17

Käyttö virheenjäljityksessä 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 Testikoodin poisjättäminen #define DEB /* vain määritelty */ #ifdef DEB /*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 18

Esimerkkejä: Example int main() { int i, j; printf("enter two integer values: "); if(scanf(%d%d, &i, &j)!= 2) return EXIT_FAILURE; #ifdef DEB printf("entered %d and %d\n", i, j); printf("sum = %d\n", i + j); return EXIT_SUCCESS; Mitä hyötyä! int i, j; #ifdef DEB int res; if( #ifdef DEB (res = scanf(%d%d, &i, &j) #ifdef DEB ) )!= 2 ) Example #ifdef DEB { switch(res) { case 0: printf("both values were wrong\n"); break; case 1: printf("ok first value %d\n", i); break; case EOF: printf("eof\n"); break; case 2: printf("both OK\n"); break... Enemmän informaatiota! 19

int main() { const char SENTINEL =. ; int aux, maxi=0; #ifdef DEBUG printf( Virheenjäljitys päällä: kopioidaan kaikki merkit\n ); while(1) { if ((aux = getchar()) == EOF aux == SENTINEL) break; #ifdef DEBUG putchar(aux); putchar( \n ); if (aux > maxi) #ifdef DEBUG printf( Suurin merkki on nyt: %c\n, aux); maxi = aux; #ifdef DEBUG putchar( \n ); printf( Suurin merkki on: %d\n, maxi); return EXIT_SUCCESS; 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 20

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ä makro NDEBUG 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 21

#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 Makro otsaketiedostojen suojana 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 22

Ehdollinen kääntäminen ja siirrettävyys Erilaisissa ympäristöissä toimivien ohjelmien kehittämiseen: #if IBMPC /* ehtolauseke */ #include <ibm.h> #else #include <generic.h> #ifdef IBMPC /*makromäärittely*/ typedef int MyInteger #else typedef long MyInteger Kevät 2006 Liisa Marttinen & Tiina Niklander 45 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 j = HIGH; FOR(j) switch(j) { case 1: PR(i++); case 2: PR(j); break; default: PR(i); printf ( \n%s\n, SHOW(3)); return EXIT_SUCCESS; 23

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)); break; default: PR(i); printf( %d\n, (i)); printf ( \n%s\n, SHOW(3)); return EXIT_SUCCESS; 24