Např.: // v hlavičkovém souboru nebo na začátku // programu (pod include): typedef struct { char jmeno[20]; char prijmeni[20]; int rok_nar; } CLOVEK;

Podobné dokumenty
10 Práce s řetězci - pokračování

Př. další použití pointerů

8. lekce Úvod do jazyka C 3. část Základní příkazy jazyka C Miroslav Jílek

- jak udělat konstantu long int: L long velka = 78L;

Program převod z desítkové na dvojkovou soustavu: /* Prevod desitkove na binarni */ #include <stdio.h>

Základní datové typy, proměnné - deklarujeme předem - C je case sensitive rozlišuje malá a velká písmena v názvech proměnných a funkcí

Strukturu lze funkci předat: (pole[i])+j. switch(výraz) velikost ukazatele

IUJCE 07/08 Přednáška č. 4. v paměti neexistuje. v paměti existuje

Operační systémy. Cvičení 4: Programování v C pod Unixem

- dělají se také pomocí #define - podobné (použitím) funkcím - předpřipravená jsou např. v ctype.h. - jak na vlastní makro:

for (i = 0, j = 5; i < 10; i++) { // tělo cyklu }

Lekce 19 IMPLEMENTACE OPERAČNÍHO SYSTÉMU LINUX DO VÝUKY INFORMAČNÍCH TECHNOLOGIÍ JAZYK C

Základy programování (IZP)

Pole stručný úvod do začátku, podrobně později - zatím statická pole (ne dynamicky) - číslují se od 0

11a Dynamické dvourozměrné pole (obdobně vícerozměrné)

ZÁPOČTOVÝ TEST. Zpracoval Vilém Závodný, #include "stdafx.h" #include "stdio.h"

Úvod do jazyka C. Ing. Jan Fikejz (KST, FEI) Fakulta elektrotechniky a informatiky Katedra softwarových technologií

11b Další příklady operací vstupu a výstupu (úvod viz 10)

Programování v C++ 1, 1. cvičení

Správné vytvoření a otevření textového souboru pro čtení a zápis představuje

Aplikace Embedded systémů v Mechatronice. Michal Bastl A2/713a

Pole a Funkce. Úvod do programování 1 Tomáš Kühr

9. lekce Úvod do jazyka C 4. část Funkce, rekurze Editace, kompilace, spuštění Miroslav Jílek

Algoritmizace a programování

Formátové specifikace formátovací řetězce

Programování v C++, 2. cvičení

Funkce, intuitivní chápání složitosti

Algoritmizace a programování

PROMĚNNÉ, KONSTANTY A DATOVÉ TYPY TEORIE DATUM VYTVOŘENÍ: KLÍČOVÁ AKTIVITA: 02 PROGRAMOVÁNÍ 2. ROČNÍK (PRG2) HODINOVÁ DOTACE: 1

ZPRO v "C" Ing. Vít Hanousek. verze 0.3

Mělká a hluboká kopie

PROGRAMOVACÍ JAZYKY A PŘEKLADAČE LEXIKÁLNÍ ANALÝZA

Odvozené a strukturované typy dat

Více o konstruktorech a destruktorech

Základy programování (IZP)

Strukturované typy a ukazatele. Úvod do programování 1 Tomáš Kühr

6. lekce Úvod do jazyka C knihovny datové typy, definice proměnných základní struktura programu a jeho editace Miroslav Jílek

Struktury a dynamické proměnné

Základy programování (IZP)

C++ Akademie SH. 2. Prom nné, podmínky, cykly, funkce, rekurze, operátory. Michal Kvasni ka. 20. b ezna Za áte níci C++

Základy programování (IZP)

IUJCE 07/08 Přednáška č. 1

Úvod do jazyka C. Ing. Jan Fikejz (KST, FEI) 28. prosince Fakulta elektrotechniky a informatiky Katedra softwarových technologií

Základy C++ I. Jan Hnilica Počítačové modelování 18

Zápis programu v jazyce C#

BI-PA1 Programování a algoritmizace 1 Katedra teoretické informatiky

Martin Flusser. December 15, 2016

Lekce 6 IMPLEMENTACE OPERAČNÍHO SYSTÉMU LINUX DO VÝUKY INFORMAČNÍCH TECHNOLOGIÍ JAZYK C

Pointery II. Jan Hnilica Počítačové modelování 17

Začínáme vážně programovat. Řídící struktury Přetypování Vstupně výstupní operace Vlastní tvorba programů

Výčtový typ strana 67

int ii char [16] double dd název adresa / proměnná N = nevyužito xxx xxx xxx N xxx xxx N xxx N

Základy programování (IZP)

Obsah. Předmluva 13 Zpětná vazba od čtenářů 14 Zdrojové kódy ke knize 15 Errata 15

Programovanie v jazyku C - funkcie a makra

Výrazy a operátory. Operátory Unární - unární a unární + Např.: a +b

VÝUKOVÝ MATERIÁL. Bratislavská 2166, Varnsdorf, IČO: tel Číslo projektu

Operační systémy. Cvičení 3: Programování v C pod Unixem

1. lekce. do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme:

Ukazatel (Pointer) jako datový typ - proměnné jsou umístěny v paměti na určitém místě (adrese) a zabírají určitý prostor (počet bytů), který je daný

VÝUKOVÝ MATERIÁL. Bratislavská 2166, Varnsdorf, IČO: tel Číslo projektu

for (int i = 0; i < sizeof(hodnoty) / sizeof(int); i++) { cout<<hodonoty[i]<< endl; } cin.get(); return 0; }

Střední škola pedagogická, hotelnictví a služeb, Litoměříce, příspěvková organizace

Základy jazyka C. Základy programování 1 Martin Kauer (Tomáš Kühr)

IUJCE 07/08 Přednáška č. 6

int => unsigned int => long => unsigned long => float => double => long double - tj. bude-li:

Výrazy, operace, příkazy

1. lekce. do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme:

PROGRAMOVACÍ JAZYKY A PŘEKLADAČE REALIZACE PŘEKLADAČE I

Algoritmizace a programování

Příkazy preprocesoru - Před překladem kódu překladačem mu předpřipraví kód preprocesor - Preprocesor vypouští nadbytečné (prázdné) mezery a řádky -

Algoritmizace a programování

Ukazatele, dynamická alokace

Výrazy, operace, příkazy

Pokročilé programování v jazyce C pro chemiky (C3220) Operátory new a delete, virtuální metody

2 Datové typy v jazyce C

PROGRAMOVÁNÍ V SHELLU

Lineární spojový seznam (úvod do dynamických datových struktur)

Jazyk C práce se soubory. Jan Hnilica Počítačové modelování 16

Dílčí příklady použití jazykových konstrukcí v projektu. Jazyk C Příklady. Pravidla překladu v gmake. Zadání

IMPLEMENTACE OPERAČNÍHO SYSTÉMU LINUX DO VÝUKY INFORMAČNÍCH TECHNOLOGIÍ JAZYK C

Jazyk C++, některá rozšíření oproti C

- tzv. standardní vstupní a výstupní proud (input / output stream)

Programování v jazyce C pro chemiky (C2160) 3. Příkaz switch, příkaz cyklu for, operátory ++ a --, pole

Programování v C++ 2, 4. cvičení

PREPROCESOR POKRAČOVÁNÍ

Programování v jazyce C pro chemiky (C2160) 4. Textové řetězce, zápis dat do souboru

Programování v jazyce C pro chemiky (C2160) 6. Funkce, struktury

Jazyk C# a platforma.net

Třídy a struktury v C++

KTE / ZPE Informační technologie

Dynamická vícerozměrná pole. Základy programování 2 Tomáš Kühr

Pokročilé programování v jazyce C pro chemiky (C3220) Třídy v C++

Řídící struktury, if, while, switch

IUJCE Přednáška č. 11. další prvky globální proměnné, řízení viditelnosti proměnných, funkcí

Algoritmizace a programování

Koncepce (větších) programů. Základy programování 2 Tomáš Kühr

Objektově orientované programování

Proměnná. Datový typ. IAJCE Cvičení č. 3. Pojmenované místo v paměti sloužící pro uložení hodnoty.

Transkript:

Struktury - složený datový typ. - datový typ jehož položky jsou jiné proměnné: - používá obvykle dohromady s příkazem typedef nechci vypisovat opakovaně složitou deklaraci pomocí typedef udělám nový datový typ: 9 Např.: // v hlavičkovém souboru nebo na začátku // programu (pod include): typedef struct char jmeno[20]; char prijmeni[20]; int rok_nar; CLOVEK; // Potom v programu CLOVEK a, b; a.rok_nar = 1995; strcpy(a.jmeno, "Pepa"); strcpy(a.prijmeni, "Novak"); printf("%s %s rok narozeni %d", a.jmeno, a.prijmeni, a.rok_nar); b.rok_nar = 1990; strcpy(b.jmeno, "Kunhuta"); strcpy(b.prijmeni, "Vonaskova"); printf("%s %s rok narozeni %d", b.jmeno, b.prijmeni, b.rok_nar); CLOVEK lidi[50]; lidi[0].rok_nar = 1993; strcpy(lidi[0].jmeno, "Eman"); strcpy(lidi[0].prijmeni, "Fiala");

printf("%s %s rok narozeni %d", lidi[0].jmeno, lidi[0].prijmeni, lidi[0].rok_nar); CLOVEK *p_lidi; int delka = 100; p_lidi = (CLOVEK *) malloc(delka * sizeof(clovek)); p_lidi[1].rok_nar = 1999; // jiné způsoby viz níže (p_lidi + 1)->rok_nar = 1999; // totez jako predch.r. free(p_lidi); Také lze: p_lidi[1].rok_nar = 1999; *(p_lidi + 1).rok_nar = 1999; (p_lidi + 1)->rok_nar = 1999; Méně často: typedef struct clovek char jmeno[20]; char prijmeni[20]; int rok_nar; ; struct clovek a, b, c;

Nebo: typedef struct clovek char jmeno[20]; char prijmeni[20]; int rok_nar; struct clovek *p_dite; CLOVEK; void main(void) CLOVEK a, b; CLOVEK lidi[50]; CLOVEK *p_clobrda; CLOVEK *p_lidi; strcpy(a.jmeno, "Pepa"); strcpy(a.prijmeni, "Novak"); a.rok_nar = 1971; strcpy(b.jmeno, "Anicka"); strcpy(b.prijmeni, "Vyskocova"); b.rok_nar = 1988; strcpy(lidi[0].jmeno, "Jana"); strcpy(lidi[0].prijmeni, "Novakova"); lidi[0].rok_nar = 1986; strcpy(lidi[1].jmeno, "Eliska"); strcpy(lidi[1].prijmeni, "Chobotova"); lidi[1].rok_nar = 1986; /* zde asi cyklus... */ /* A nyní dynamicky */ p_clobrda = (CLOVEK *) malloc(sizeof(clovek));

strcpy(p_clobrda->jmeno, "Helena"); strcpy(p_clobrda->prijmeni, "Vesela"); p_clobrda->rok_nar = 1987; lze i s tečkou: (*p_clobrda).rok_nar = 1987; /* A nyní dynamické pole lidí */ p_lidi = (CLOVEK *) malloc(100 * sizeof(clovek)); strcpy(p_lidi[0].jmeno, "Hermína"); strcpy(p_lidi[0].prijmeni, "Dávná"); p_lidi[0].rok_nar = 1910; strcpy((p_lidi + 1)->jmeno, "Lojza"); strcpy((p_lidi + 1)->prijmeni, "Cipera"); (p_lidi + 1)->rok_nar = 2010; free((void *) p_clobrda); free((void *) p_lidi); Nebo další příklad: typedef struct datum int den; int mesic; int rok; DATUM; typedef struct clovek char jmeno[20]; char prijmeni[20]; DATUM datum_narozeni; CLOVEK;

void main(void) CLOVEK a; // tady nějaký kód programu strcpy(a.jmeno, "Pepa"); strcpy(a.prijmeni, "Novak"); a.datum_narozeni.den = 20; a.datum_narozeni.mesic = 6; a.datum_narozeni.rok = 1971; Nebo: void main(void) CLOVEK *p_a; // tady nějaký kód programu p_a = (CLOVEK *) malloc(sizeof(clovek)) strcpy(p_a->jmeno, "Pepa"); strcpy(p_a->prijmeni, "Novak"); p_a->datum_narozeni.den = 20; p_a->datum_narozeni.mesic = 6; p_a->datum_narozeni.rok = 1971; ----------------------------- konec 12.4.2016 --------------

Pro vytvoření řetězu struktur (spojový seznam, linked-list): typedef struct clovek struct clovek *p_dalsi; char jmeno[20]; char prijmeni[20]; DATUM datum_narozeni; CLOVEK; void main(void) CLOVEK *p_lidi; p_lidi = (CLOVEK *) malloc(sizeof(clovek)); strcpy(p_lidi->jmeno, "Helena"); strcpy(p_lidi->prijmeni, "Vesela"); atd pro DATUM... p_lidi->p_dalsi = (CLOVEK *)malloc(sizeof(clovek));

Podobné jsou uniony typedef union char c; pouzivam bud to c nebo i int i; MUJ_UNION; MUJ_UNION prom; Lze použít: prom.c = 'A'; NEBO prom.i = 1234; /* tím jsem přepsal to 'A' */ Tj. v unionech jsou položky v paměti přes sebe. český název je také variantní záznam. Praktické použití typedef union double rozchod; // pro auto nebo: int typprednibrzdy; // pro motorku typy 1,2,3 PARAMETRY; typedef struct data char nazev[20]; int cislotypustroje; // 0 auto, 1 motorka double rozvor; PARAMETRY param; DOPRAV_PROSTR; Pro auto a motorku: DOPRAV_PROSTR jezditka[10]; // auto strcpy(jezditka[0].nazev, "BMW"); jezditka[0].cislotypustroje = 0; jezditka[0].rozvor = 2500.0; // mm jezditka[0].param.rozchod = 2000.0; // mm

// motorka strcpy(jezditka[1].nazev, "Harley"); jezditka[1].cislotypustroje = 1; jezditka[1].rozvor = 1500; // mm jezditka[1].param.typprednibrzdy = 3; // cislo typu // tisk parametru for (i = 0; i < kolikjezditek; i++) printf("nazev: %s\n", jezditka[i].nazev); printf("typ: %d\n", jezditka[i].cislotypustroje); printf("rozvor: %f\n", jezditka[i].rozvor); if (jezditka[i].cislotypustroje == 0) // je to auto printf("nazev: %f", jezditka[i].param.rozchod); else // je to motorka printf("typ brzd: %d", jezditka[i].param. typprednibrzdy);

Výčtový typ - typ obsahující hodnoty, které si zvolíme např. barvy, dny v týdnu atp. - je to ordinální typ tj. hodnoty jsou vnitřně číslovány dle pořadí zleva doprava (od nuly) typedef enum MODRA, CERVENA, ZELENA, ZLUTA BARVY; ordinální značí že MODRA je vnitřně 0, CERVENA 1. Tj. jdou porovnat. MODRA < CERVENA (něco jako porovnáván u znaků) Použití: BARVY a, b; a = MODRA; b = ZLUTA; - pozor: nelze je přímo tisknout!!! printf("barva je %d", b); vytiskne: 3 Pozor lze i toto: a = 30; // jde to i když logicky je to nesmysl stejně tak: a = ZELENA; a++; // v a bude ZLUTA a++; // v a bude 4, není barva, ale C to nevadi

- pokud má tisknout názvy barev: switch (b) case MODRA: printf("barva modra."); break; case CERVENA: printf("barva cervena."); break; case ZELENA: printf("barva zelena."); break; case ZLUTA: printf("barva zluta."); break; default: printf("neznama barva."); break; Nebo ne jako enum, ale jako pole řetězců: char *nazvybarev[] = "Modra", "Cervena", "Zelena", "Zluta"; printf("barva %s\n", nazvybarev[b]);

Použití pole uvnitř struktury využíté jako chytrá náhrada jednoduchého 1D pole: #include <stdio.h> #include <stdlib.h> typedef struct int *p_pole; int delkapole; LUXUSNI_NAHRADA_POLE_INT; void tisk(luxusni_nahrada_pole_int *p_lnpi) int i; for (i = 0; i < p_lnpi->delkapole; i++) printf("%d ", p_lnpi->p_pole[i]); printf("\n"); int tiskdosouboru(luxusni_nahrada_pole_int *p_lnpi) int i; FILE *fw; fw = fopen("data.txt", "w"); if (fw == NULL) printf("soubor nesel otevrit..."); return -1; // neco neslo for (i = 0; i < p_lnpi->delkapole; i++) fprintf(fw, "%d ", p_lnpi->p_pole[i]); fprintf(fw, "\n");

if (fclose(fw) == EOF) printf("soubor nesel zavrit..."); return -1; // neco neslo else return 0; int tiskdocsv(luxusni_nahrada_pole_int *p_lnpi) int i; FILE *fw; fw = fopen("data.csv", "w"); if (fw == NULL) printf("soubor nesel otevrit..."); return -1; // neco neslo for (i = 0; i < p_lnpi->delkapole; i++) fprintf(fw, "%d;", p_lnpi->p_pole[i]); fprintf(fw, "\n"); if (fclose(fw) == EOF) printf("soubor nesel zavrit..."); return -1; // neco neslo else return 0;

int main() LUXUSNI_NAHRADA_POLE_INT *p_sklad_intu; int i; p_sklad_intu = malloc(sizeof(luxusni_nahrada_pole_int)); if (p_sklad_intu == NULL) printf("je to v haji... Neni alokovano...\n"); return(-1); printf("kolik intu bude: "); scanf("%d", &(p_sklad_intu->delkapole)); p_sklad_intu->p_pole = malloc(p_sklad_intu- >delkapole * sizeof(int)); if (p_sklad_intu->p_pole == NULL) printf("je to v haji... Neni alokovano...\n"); return(-1); for (i = 0; i < p_sklad_intu->delkapole; i++) p_sklad_intu->p_pole[i] = 33; tisk(p_sklad_intu); tiskdosouboru(p_sklad_intu); tiskdocsv(p_sklad_intu); free(p_sklad_intu->p_pole); free(p_sklad_intu);

return 0;

Řetězce shrnutí a doplnění - jde o spec. případ polí, speciální pouze v tom, že jde o pole charů - jinak se s nimi jako s běžným polem - mohou deklarována staticky i dynamicky (pomocí malloc) - dohodou je dáno, řetězce se ukončují znakem '\0' viz začátek semestru (konstanty) tzv. nulový byte - pokud tento neuvedu nevadí při použití takového řetězce jako běžného pole. ALE vadí to knihovním funkcím Céčka, které spoléhají, že dle tohoto poznají konec pole. Stejně tak to bude každému programu, který řetězce využívá a na toto ukončení spoléhá. - je to proto, že C nekontroluje meze polí (délky) a já u řetězců nějak musím poznat konec. - tato "norma" se nazývá řetězec ve formátu ASCIZ - znak '\0' nemusí být umístěn až na konci pole, např: char pozdrav[20]; - uložím do něj např. Ahoj uloženo bude: A h o j \0 - tj. mám připraveno pole délky 20, využiji 4 znaky a dám '\0' funkce, které budou např. hledat nějaký znak v řetězci, podřetězec atd., nebudou pracovat s celým polem (tam mne nezajímá co je uloženo ), ale budou pracovat pouze s tím co je tam opravdu uloženo Ahoj

- Pozor: pozor je třeba s jedním znakem navíc (při deklaraci řetězce) protože potřebuji místo na '\0' tj. do našeho řetězce pozdrav mohu uložit max. 19cti znakový text - stejně jako u polí indexujeme od 0. Tj. u řetězce pozdrav je poslední prvek pozdrav[19], ten musí v rezervě na '\0' a poslední možné místo na znak je pozdrav[18]

Řetězcové konstanty - jsou v uvozovkách: "Ahoj jak se máte?" - znak '\0' je zahrnut automaticky (toto pole má 17+1 znak = 18) Deklarace řetězců Tj. např. při inicializaci v deklaraci: char pozdrav[20] = "Ahoj"; - znak '\0' je přidán automaticky, pole má délku 20. char pozdrav[] = "Ahoj"; - znak '\0' je přidán automaticky, pole má délku 5 (Ahoj a '\0'). POZOR: - takovéto přiřazení lze jen při inicializaci C neumí přímo přiřadit řetězec! char pozdrav[20]; pozdrav = "Ahoj"; /* toto v C nelze, ohlásí chybu, pozdrav je pointer na řetězec */ Jak tedy naplnit řetězec? Použít knihovní funkce, includovat soubor <string.h> #include <string.h>...nějaký kód... char pozdrav[20]; char jinypozdrav[30]; strcpy(pozdrav, "Ahoj"); /* naplní (zkopíruje) Ahoj do pozdrav */ strcpy(jinypozdrav, "Nazdar"); /* naplní (zkopíruje) Nazdar do jinypozdrav */

strcpy(pozdrav, jinypozdrav); /* naplní (zkopíruje) jinypozdrav do pozdrav */ Lze narazit na toto (a je to správně): char *p_str = "Ahoj"; - mám pointer na char a přiřadím mu adresu statického řetězce "Ahoj" - tj. je to něco jako int *p_i = &i; Dynamické textové řetězce - stejně jako u 1D dynamických polí Např.: char *p_retez; p_retez = (char *) malloc(20 * sizeof(char)); lze i p_retez = (char *) malloc(20); /* protože sizeof(char) je 1 byte */ - další použití je již stejné jako u statických řetězců. Např.: strcpy(p_retez, "Ahoj"); /* naplní (zkopíruje) Ahoj do p_retez */ p_retez[0] = 'a'; /* v p_retez bude ahoj, jednotlivé znaky lze přiřadit */ Nezapomenout: pokud budu plnit řetězec jinak než konstantní řetězcem (v deklaraci nebo strcpy v programu) nesmím zapomenout připojit '\0' Např.: - mohu např. plnit řetězec znak po znaku, např. naplníme řetězec abeceda znaky A až Z: char abeceda[40]; int i; for (i = 'A'; i <= 'Z'; i++) abeceda[i 'A'] = (char) i;

abeceda['z' 'A' + 1] = '\0'; // za 'Z' dám '\0' nebo jinak: char abeceda[40]; int i; for (i = 0; i <= ('Z'-'A'); i++) abeceda[i] = (char) (i + 'A'); abeceda['z' 'A' + 1] = '\0'; nebo ještě jinak: char abeceda[40]; int znak, j; for (j = 0, znak = 'A'; znak <= 'Z'; znak++, j++) abeceda[j] = (char) znak; abeceda['z' 'A' + 1] = '\0'; Pozor na následující případ: char abeceda[50], *p_ret; int i; for (i = 'A'; i <= 'Z'; i++) abeceda[i - 'A'] = (char) i; abeceda['z' - 'A' + 1] = '\0'; p_ret = abeceda; puts(abeceda); puts(p_ret);

printf("\nabeceda %d %d", sizeof(abeceda), strlen(abeceda)); printf("\np_ret %d %d\n", sizeof(p_ret), strlen(p_ret)); Vytiskne to: ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ abeceda 50 26 p_ret 4 26 - pro proměnnou abeceda, deklarovanou staticky, sizeof vrátí deklarovanou délku pole, ale pro dynamickou deklaraci (pointerem) vrátí velikost pointeru na char (velikost adresy 4byte). Pozor tento jev nastává též při předávání řetězců jako parametrů funkcí!!!!! void moje_funkce(char *p_retez) funkce neco dela, sizeof(p_retez) by byl 4 (velikost pointeru) void main(void) char retez[50] = "Ahoj"; /* v mainu by sizeof(retez) bylo 50 */ moje_funkce(retez); - strlen funguje ve všech případech stejně