ehdollinen kääntäminen

Samankaltaiset tiedostot
Tekstitiedostot ja niiden käyttö

Tekstitiedostot ja niiden käyttö

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

Loppukurssin järjestelyt

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

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

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

Loppukurssin järjestelyt C:n edistyneet piirteet

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

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

Tietorakenteet ja algoritmit

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

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

TIETORAKENTEET JA ALGORITMIT

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Java-kielen perusteet

Java-kielen perusteita

815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset

Ohjelmointiharjoituksia Arduino-ympäristössä

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

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

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

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

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

2. C-kieli ja ongelmanratkaisu

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

Java-kielen perusteet

7. Näytölle tulostaminen 7.1

Merkkijonot Komentoriviparametrit

3. Binääripuu, Java-toteutus

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

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ä! 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

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

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

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

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 */ if (fscanf (filehandle, %d, i)!=1) /* error */ Tiedoston sulkeminen Yhden merkin lukeminen Yhden luvun lukeminen while ((c= fgetc(filehandle))!= \n ) while ((c= fgetc(filehandle))!= EOF) Rivin loppuun lukeminen Tiedoston loppuun lukeminen Fraaseja tiedoston käsittelyyn

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ä. #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

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

#-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 lähdekoodin tämän rivin numero 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

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

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 #endif #ifndef macroname partl #else part2 #endif #if constantexpression1 part 1 #elif constantexpression2 part2 #else part3 #endif Kevät 2006 Liisa Marttinen & Tiina Niklander 33

#if constantexpression1 part 1 #elif constantexpression2 part2 #else part3 #endif - voi olla useita #elif osia - #else voi puuttua #if defined (name) /*onko name määritelty?*/ #error textmessage #if defined ( STDC ). #else #error Jotain pielessä #endif

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 #endif 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); #endif /* 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

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); #endif printf("sum = %d\n", i + j); return EXIT_SUCCESS; } Mitä hyötyä!

int i, j; #ifdef DEB int res; #endif if( #ifdef DEB (res = #endif scanf(%d%d, &i, &j) #ifdef DEB ) #endif )!= 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 } #endif... Enemmän informaatiota!

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

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); } } #endif Kevät 2006 Liisa Marttinen & Tiina Niklander 42

#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ö */ #endif #include screen.h #include screen.h Käännetään vain kerran! Kevät 2006 Liisa Marttinen & Tiina Niklander 44

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> #endif #ifdef IBMPC /*makromäärittely*/ typedef int MyInteger #else typedef long MyInteger #endif 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; }

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