Esittely latautuu. Ole hyvä ja odota

Esittely latautuu. Ole hyvä ja odota

Merkit ja merkistöt C:n perusmerkistö (basic character set): a-z A-Z 0-9 ! " # % & ' ( ) * +, -. / : ; ? [ \ ] ^ _ { | } ~ sekä välilyönti, tabulaattori,

Samankaltaiset esitykset


Esitys aiheesta: "Merkit ja merkistöt C:n perusmerkistö (basic character set): a-z A-Z 0-9 ! " # % & ' ( ) * +, -. / : ; ? [ \ ] ^ _ { | } ~ sekä välilyönti, tabulaattori,"— Esityksen transkriptio:

1 Merkit ja merkistöt C:n perusmerkistö (basic character set): a-z A-Z 0-9 ! " # % & ' ( ) * +, -. / : ; ? [ \ ] ^ _ { | } ~ sekä välilyönti, tabulaattori, pystytabulaattori ja sivunvaihto. Näiden pitää toimia sekä lähdekoodissa (source character set) että suorituksen aikana (execution character set). Edellisessä pitää lisäksi olla jokin tapa merkitä rivin loppu, jälkimmäisessä pitää olla erikseen rivinvaihto, telanpalautus sekä alert ja backspace. Muut merkit ovat toteutuskohtaisia.

2 Erikoismerkit \a = alert \b = backspace \f = sivunvaihto (formfeed) \n = rivinvaihto (newline) \r = telanpalautus (carriage return) \t = tabulaattori \v = pystytabulaattori \\ = \ \? = ? \' = ' \" = "

3 Minkä tahansa merkin voi syöttää myös oktaalilukuna, \0... \377 (1-3 numeroa 0-7) tai heksadesimaalina, \x00.. \xFF (enemmän jos char on pitempi kuin 8 bittiä).

4 trigraphs Joitakin perusmerkistön merkkejä voidaan esittää trigraph-notaatiolla: ??= # ??( [ ??/ \ ??) ] ??' ^ ??< { ??! | ??> } ??- ~ Kahden kysymysmerkin väliin pitää laittaa \, jos haluaa estää tämän muunnoksen ("?\?!" jne). Trigraph-muunnos tehdään kaikkein ensimmäiseksi koodia tulkittaessa.

5 digraphs Lisäksi seuraavat tekstialkiot tulkitaan samoiksi: <: [ :> ] <% { %> } %: # %:%: ## Tämä ei kuitenkaan ole merkkimuunnos eikä sitä tehdä merkkivakioille tai merkkijonoille.

6 Merkkivakio merkitään yksinkertaisilla lainausmerkeillä: ch = 'a'; ch = 'B'; ch='0'; ch=' '; ch='\n'; ch='\t'; ch='\33'; ch='\033'; ch='\x1B'; ch='\x1b'; // samoja ch='#'; ch='??='; // samat ch='['; ch='<:'; // virhe! Merkkivakion tyyppi on int, ei char.

7 Merkeillä laskeminen char on kuin pieni kokonaislukutyyppi, merkkejä voi verrata ja niillä voi laskea, ja niitä voi vapaasti yhdistellä muiden tyyppien kanssa: char ch; int i; i = 'B'; ch=65; ch++; if (i==ch) printf("näyttää ASCIIlta\n"); if ('A'>'B') printf("auh, merkistö on outo\n"); if ('a'<=c && c<='z') c -= 'A'-'a';

8 Merkkien järjestystä ei ole tiukasti rajattu, ainoastaa numeroiden '0'...'9' osalta on kiinnitetty että ne ovat peräkkäin: for (i='0'; i<='9'; i++) { // numerot '0'..'9' Kirjaimia voi käydä läpi samaan tapaan mutta järjestys voi yllättää: for (i='a'; i<='z'; ++i) { // ei toimi aina! Käytännössä ainoa ympäristö missä a-z ja A-Z eivät ole peräkkäin on IBM:n suurkoneet, joissa yhä saattaa esiintyä EBCDIC-koodia.

9 char voi olla signed tai unsigned: if ('ä' < 0) printf("char is signed\n"); char n; for (n=1; n<200; ++n) { // toimii jos char unsigned unsigned char c; int i, i; c='ä'; i=c; j='ä'; if (i==j) { // voi olla epätosi!

10 Merkki-I/O printf ja scanf: %c scanf("%c", &x); // lukee yhden merkin printf("%c", x); // tulostaa yhden merkin printf("%5c",x); // tulostaa 4 tyhjää ja x:n huom. %c:n kanssa scanf ei ohita alkutyhjiä, jos sitä halutaan formaattiin pitää laittaa tyhjä: scanf(" %c", &ch);

11 Koska scanf ei %c:n kanssa ohita alkutyhjiä, se ei ohita myöskään rivinvaihtoa. Esim. hypätään rivin loppuun (luetaan merkkejä rivinvaihtoon saakka): do { scanf("%c",&c); } while (ch!='\n');

12 getchar ja putchar Yksittäisen merkin lukemiseen ja tulostukseen on omat funktiot: ch = getchar(); // scanf("%c", &ch); putchar(ch); // printf("%c", ch); while (getchar()!='\n') // hypätään rivin loppuun ; while (getchar()!=' ') // ohitetaan tyhjät ;

13 Käytettäessä scanf ja getchar funktioita sekaisin, varo: scanf voi "katsoa" merkkejä joita se ei kuitenkaan "käytä". Esim. printf("Anna luku: "); scanf("%d", &x); printf("Komento? "); cmd=getchar(); // todennäköisesti rivinvaihto

14 Monitavuiset ja leveät merkit Perusmerkistön lisäksi C sallii toteutuskohtaisesti laajempiakin merkkijoukkoja, myös monitavuisia - kahdella eri tavalla. Normaalissa merkkijonossa voi olla monitavuisia merkkejä (multibyte characters) ja käytettävissä on myös "leveä merkki" -tyyppi, wchar_t, joka on yleensä sama kuin short tai int. Leveät merkkivakiot merkitään etuliitteellä L, esim. L'ä' (vast. merkkijonot L"..."). Näiden käsittelyyn on omat kirjastofunktionsa.

15 Tyyppimuunnoksista Aritmeettisia tyyppejä, ts. kokonaislukuja (ml. char ja _Bool) ja liukulukuja (C99:ssä myös _Complex) saa yhdistellä vapaasti. Automaattinen tyyppimuunnos tehdään neljässä tilanteessa: * kun laskutoimituksen operandien tyypit eroavat (aritmeettiset muunnokset) * kun muuttujan tyyppi on eri kuin siihen sijoitettavan lausekkeen * kun argumentin tyyppi funktiokutsussa on eri kuin vastaavan parametrin * kun return-lausekkeen tyyppi on eri kuin ao. funktion

16 Aritmeettiset muunnokset Pääsääntö: muunnetaan "pienimpään" tyyppiin johon molemmat operandit mahtuvat. Liukuluvut: float->double->long double Liukuluku+kokonaisluku: -> liukuluku (sama tyyppi kuin toisella operandilla) Kokonaisluvut: ensin char, short -> int sitten int->unsigned->long->unsigned long poikkeus: jos long ja unsigned samanmittaisia, niitä yhdistettäessä molemmat -> unsigned long. Yhdistettäessä etumerkillisiä ja etumerkittömiä muunnetaan etumerkittömiksi.

17 Etumerkillisten ja etumerkittömien yhdisteleminen on vaarallista, tulokset usein yllättäviä: int i=-10; unsigned int u=10; if (i>u) { // tosi! int i=-10; unsigned char u=10; if (i>u) { // epätosi int i=-10; unsigned short u=10; if (i>u) { // epätosi jos short pienempi kuin int

18 char ja short muunnetaan aina -> int, vaikka lausekkeessa ei muuta olisikaan (-> unsigned vain jos alkuperäinen arvo ei muuten mahdu): laskutoimitukset tehdään aina vähintään int- tarkkuudella. char a=120, b=130, c=100, d=100, e; e=a+b+c-3*d; // 50, ei ylivuotoa

19 Aritmeettiset muunnokset tehdään laskutoimitus kerrallaan, ei koko lausekkeelle - välivaiheissa voi tapahtua tarkkuuden menetystä: int i=2, j=4; double x=1, y; y = x + i / j; // 1.0 -- kokonaislukujakolasku! y = 1.0 + 2 / 4; // samoin y = 1 + 2.0/4 // 1.5

20 Kokonaislukuja ja liukulukuja yhdistettäessä kokonaisluku muunnetaan liukuluvuksi, vaikka tarkkuus vähenisikin: long long h = 1234567890123456789; long double x; Mitkä seuraavista toimivat oikein: x = h+1; printf("%Lf\n", x); x = h+1.0; printf("%Lf\n", x); x = h+1L; printf("%Lf\n", x);

21 Kokonaislukuja ja liukulukuja yhdistettäessä kokonaisluku muunnetaan liukuluvuksi, vaikka tarkkuus vähenisikin: long long h = 1234567890123456789; long double x; Mitkä seuraavista toimivat oikein: x = h+1; printf("%Lf\n", x); x = h+1.0; printf("%Lf\n", x); x = h+1L; printf("%Lf\n", x); x = h+1.0L; printf("%Lf\n", x);

22 Kokonaislukuja ja liukulukuja yhdistettäessä kokonaisluku muunnetaan liukuluvuksi, vaikka tarkkuus vähenisikin: long long h = 1234567890123456789; long double x; Mitkä seuraavista toimivat oikein: x = h+1; printf("%Lf\n", x); // oikein: 1 int ->long long x = h+1.0; printf("%Lf\n", x); // pyöristysvirhe; h->double x = h+1L; printf("%Lf\n", x); // oikein: 1L long long x = h+1.0L; printf("%Lf\n", x); // oikein: 1.0L long double

23 Muunnos sijoituslauseessa Sijoitettaessa lauseke muunnetaan muuttujan tyyppiseksi. "Isompaan" tyyppiin muutettaessa ongelmatonta, muuten: * liukukuku kokonaisluvuksi: desimaaliosa pois * etumerkittömäksi muunnettaessa lasketaan "modulo 2^n", missä n bittien määrä * _Bool'iksi: kaikki nollasta eroavat -> 1 * kompleksiluku muuksi: imaginaariosa pois Etumerkillisillä kokonaisluvuilla ja liukuluvuilla ylivuoto on virhe (määrittelemätön).

24 Eksplisiittinen tyyppimuunnos Lausekkeen tyypin voi pakottaa halutuksi: (tyyppi) lauseke float f, d; d= f - (int)f; // desimaaliosa Tyyppimuunnoksella on korkeampi prioriteetti kuin kahden operandin laskutoimituksilla: float q; int n, k; q = (float) n / k; // ((float) n)) / k

25 Eksplisiittinen tyyppimuunnos voi olla tarpeen myös ylivuodon välttämiseksi: long k; int j=1000; k = j*j; // ylivuoto jos int 16-bittinen k = (long) j*j; // ok k = (long) (j*j); // VÄÄRIN

26 typedef Uuden tyypin voi määritellä typedef -lauseella: typedef int Bool; // Bool synonyymi int'ille vrt. #define BOOL int Mitä eroja?

27 Erityisesti kokonaislukutyypit kannattaa nimetä uudelleen siirrettävyyden parantamiseksi, koska niiden tarkkuus vaihtelee paljon konekohtaisesti. (Standardikirjasto määrittelee kokoelman konekohtaisesti vaihtuvan kokoisia tyyppejä, joita voi ja kannattaa myös käyttää.) Muista muuttaa myös printf- ja scanf-formaatit vastaavasti!

28 typedef Lkm int; #define LKMFMT ”%d” typedef Lkm long; #define KLMFMT ”%ld” Lkm i;... printf(”Lukumäärä on ” KLMFMT ”\n”, i);

29 sizeof sizeof(tyyppi) // sulut pakolliset sizeof lauseke // sulut eivät pakollisia // mutta hyvin suositeltavia sizeof(int) sizeof(unsigned short int) sizeof x sizeof(x+y*j) sizeof(2+3.0L) Huom. sizeof i+j == sizeof(i) + j, ei sizeof(i+j)!

30 sizeof palauttaa tuloksen tyyppiä size_t, toteutuskohtainen kokonaislukutyyppi. C89:ssä se mahtuu aina unsigned long'iin: printf(”%lu\n”, (unsigned long) sizeof(x)); C99:ssä sille on oma formaatti: printf(”%zu\n”, sizeof(x));

31 Taulukot Yksiulotteiset taulukot: int a[10]; // indeksit 0...9 a[0]=1; x=a[5]+b[j*2-1]; ++t[i]; #define N 10 int sum, a[N]; for (i=0; i<N; i++) a[i]=0; for (i=0; i<N; i++) sum+=a[i];

32 C89:ssä taulukon kokomäärityksen on oltava vakio - lauseke OK, muuttuja ei: int n=5; int a[n]; // virhe int a[5*6]; // OK Indeksejä ei tarkisteta automaattisesti - alueen ylitys on virhe. int a[10], i; for (i=0; i<=10; i++) a[i]=0;

33 Varo sivuvaikutuksia taulukoiden indeksien kanssa: i=0; while (i<N) a[i] = b[i++]; // voi tehdä mitä vain!

34 Taulukoiden alustus int a[5] = { 1,2,3,4,5 }; int a[10] = { 1,2,3 }; // loput nolliksi int a[100] = { 0 }; // täyteen nollia int a[] = { 1, 2, 3 }; // sama kuin int a[3] =... C99: int a[10] = { [2]=1, [3]=2, [5]=3, [7]=4 }; int a[] = { [30]=1, [2]=5 }; // int a[31] int a[10] = { [5]=1, 2, 3 }; // a[6]=2, a[7]=3

35 sizeof ja taulukot int a[10]; sizeof(a); // 10*sizeof(int) sizeof(a)/sizeof(int); // alkioiden lukumäärä for (i=0; i < sizeof(a)/sizeof(int); ++i) {... // kääntäjä saattaa varoittaa - parempi (jos int i): for (i=0; i < (int)sizeof(a)/sizeof(int); ++i) {...

36 Moniulotteiset taulukot int w[4][4]; // EI w[4,4]!! int (w[4])[4]; // toimii - miksi? char x[2][2][2]; for (i=0;i<4;++i) for (j=0;j<4;j++) w[i][j] = 0;

37 Taulukot tallennetaan riveittäin, esim. int a[2][3]: a[0][0],a[0][1],a[0][2],a[1][0],a[1][1],a[1][2] Alustus: int m[2][3] = { { 1,2,3 } {4,5,6}}; int m[2][3] = { {1} { 2,3 }}; // täydennetään 0:lla int m[2][3] = { 1,2,3,4,5,6 }; // toimii mutta rumaa C99: int m[2][3] = { [1][2]=5, [0][1]=6 };

38 Vakiotaulukot Taulukon (kuten muunkin muuttujan) voi määritellä vakioksi, jolloin kääntäjä valittaa jos sitä yritetään muuttaa: const char heksat[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

39 Muuttuvankokoiset taulukot C99:ssä taulukon koko voi muuttua: int n; scanf(”%d”, n); float f[n]; Muuttuvankokoisen taulukkomäärityksen ohi ei saa hypätä edes goto'lla.

40 Taulukko-operaatiot Taulukoilla voi suoraan tehdä hyvin vähän, esim. kopiointi ei noin vain onnistu: float a[10], b[10]; a=b; // VIRHE Tarvitaan silmukka: for (i=0; i<10; i++) a[i]=b[i];

41 Funktiot Esimerkki: double keskiarvo (double x, double y) { return (x+y)/2; } kutsu: printf(”%g\n”, keskiarvo(x,5));

42 Funktion (palauttaman arvon) tyyppi voi olla mitä tahansa paitsi taulukko. Jos se ei palauta mitään, tyypiksi merkitään void: void tulosta_keskiarvo(double x, double y) { printf(”%g\n”, (x+y)/2); } kutsu: tulosta_keskiarvo(x, 5);

43 Sulut kutsussa ovat pakolliset, vaikkei parametreja olisikaan: void vingu(void) { printf(”Vinkaisu!\n”); }... vingu();

44 Jos funktio palauttaa arvon josta emme välitä: (void) printf(”Hei!\n”);


Lataa ppt "Merkit ja merkistöt C:n perusmerkistö (basic character set): a-z A-Z 0-9 ! " # % & ' ( ) * +, -. / : ; ? [ \ ] ^ _ { | } ~ sekä välilyönti, tabulaattori,"

Samankaltaiset esitykset


Iklan oleh Google