Programování v jazyce C pro chemiky (C2160) 7. Ukazatele, Funkce pro práci s řetězci

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

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

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

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

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

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

Programování v jazyce C pro chemiky (C2160) 5. Čtení dat ze souboru

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

Základy programování (IZP)

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

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

Programování v jazyce C pro chemiky (C2160) 8. Načítání a zápis PDB souboru

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:

Práce s řetězci. IUJCE Přednáška č. 10. string.h. vrací: délku řetězce str (bez '\0')

2 Datové typy v jazyce C

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

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

Pokročilé programování v jazyce C pro chemiky (C3220) Vstup a výstup v C++

Základy programování (IZP)

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

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

Martin Flusser. Faculty of Nuclear Sciences and Physical Engineering Czech Technical University in Prague. October 17, 2016

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

Pokročilé programování v jazyce C pro chemiky (C3220) Statické proměnné a metody, šablony v C++

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

Programovanie v jazyku C - struktury a polia

Základy programování (IZP)

Více o konstruktorech a destruktorech

Základy programování (IZP)

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)

III/2 Inovace a zkvalitnění výuky prostřednictvím ICT

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

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

Základy programování (IZP)

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

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

Standardní algoritmy vyhledávací.

Preprocesor a koncepce (větších) programů. Úvod do programování 2 Tomáš Kühr

Práce se soubory. Základy programování 2 Tomáš Kühr

Řetězce. Často potřebujeme v řetězci přepsat nějaké znaky. Nemůžeme ale zapsat např.

Základy programování (IZP)

1. D Y N A M I C K É DAT O V É STRUKTUR Y

Programovanie v jazyku C - funkcie a makra

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

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

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

Jazyk C Program v jazyku C má následující strukturu: konstanty nebo proměnné musí Jednoduché datové typy: Strukturované datové typy Výrazy operátory

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

1. test z PJC Jméno studenta: Pocet bodu: Varianta 37: příklad 5 (5 bodů)

Algoritmizace a programování

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ý

DSL manuál. Ing. Jan Hranáč. 27. října V této kapitole je stručný průvodce k tvorbě v systému DrdSim a (v

Programování v jazyce C pro chemiky (C2160) 12. Specifické problémy při vývoji vědeckého softwaru

Algoritmizace a programování

8 Třídy, objekty, metody, předávání argumentů metod

C2110 Operační systém UNIX a základy programování

PROGRAMOVÁNÍ V SHELLU

Funkce pokročilé možnosti. Úvod do programování 2 Tomáš Kühr

Funkční objekty v C++.

- znakové konstanty v apostrofech, např. a, +, (znak mezera) - proměnná zabírá 1 byte, obsahuje kód příslušného znaku

2 Základní funkce a operátory V této kapitole se seznámíme s použitím funkce printf, probereme základní operátory a uvedeme nejdůležitější funkce.

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

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

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

PROGRAMOVÁNÍ V C++ CVIČENÍ

Programování v jazyce C pro chemiky (C2160) 9. Práce s PDB soubory

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

Základy programování (IZP)

Práce s binárními soubory. Základy programování 2 Tomáš Kühr

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

Množina čísel int stl-set-int.cpp

Základy programování (IZP)

Základy programování (IZP)

Základy programování (IZP)

Čtvrtek 8. prosince. Pascal - opakování základů. Struktura programu:

Základy programování (IZP)

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

Algoritmizace a programování

Vyhledávání. doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava. Prezentace ke dni 21.

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;

IAJCE Přednáška č. 8. double tprumer = (t1 + t2 + t3 + t4 + t5 + t6 + t7) / 7; Console.Write("\nPrumerna teplota je {0}", tprumer);

Java Cvičení 01. CHARLES UNIVERSITY IN PRAGUE faculty of mathematics and physics

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

Martin Flusser. Faculty of Nuclear Sciences and Physical Engineering Czech Technical University in Prague. December 7, 2016

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

Mělká a hluboká kopie

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

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

4. Rekurze. BI-EP1 Efektivní programování Martin Kačer

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

Struktura programu v době běhu

Polymorfismus. Časová náročnost lekce: 3 hodiny Datum ukončení a splnění lekce: 30.března

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

Programování v jazyce C a C++

Úvod do programování. Lekce 5

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

VISUAL BASIC. Přehled témat

Základní datové struktury

Transkript:

Programování v jazyce C pro chemiky (C2160) 7. Ukazatele, Funkce pro práci s řetězci

Ukazatele Každá proměnná je umístěna na konkrétním místě v paměti Paměť je organizována lineárně jako posloupnost bytů Každému bytu přísluší adresa, tj. pořadí bytu v paměti V jazyce C někdy potřebujeme zjistit adresu v paměti, kde je uložen obsah proměnné, tuto adresu ukládáme do proměnných nazývaných ukazatel (angl. pointer) Adresa v paměti Její obsah 1000 1004 1008 1012 1016 1020 1024 56 125 7 91 0 13 1 Proměnné typu int (každá zabírá 4 byty) 2

Definice ukazatele Rozlišujeme různé typy ukazatelů, podle toho zda-li ukazují na proměnnou typu int, float, char a pod. Všechny ukazatele obsahují adresu v paměti, kde se proměnná nachází, rozlišení typu má jen praktický význam Ukazatel definujeme podobným způsobem jako běžnou proměnnou, před název proměnné však uvedeme hvězdičku * Ukazatele je vhodné inicializovat hodnotou NULL, která představuje neplatnou adresu (v praxi je to hodnota 0 ukazující na začátek paměti, který však nebývá použit pro uložení proměnných) Názvy ukazatelových proměnných často začínají na p_ aby bylo možné snadno rozpoznat, že se jedná o ukazatel Příklad definice ukazatelů: int *p_n = NULL; float *p_a = NULL, *p_b = NULL; 3

Referenční a dereferenční operátor Pro zjištění adresy proměnné používáme referenční operátor & uvedený před názvem proměnné jejíž adresu chceme zjistit; tuto adresu zpravidla přiřadíme do ukazatelové proměnné Dereferenční operátor * provádí opačnou akci než referenční operátor. Uvádíme jej před názvem ukazatelové proměnné abychom zjistili obsah proměnné nacházejí na adrese uložené v ukazateli. POZOR: Znak * v definici ukazatele nepředstavuje dereferenční operátor, ale pouze poskytuje informaci, že jde o ukazatelovou proměnnou Adresa v paměti: Její obsah: 1000 1004 1008 1012 1016 1020 1024 7 0 NULL Proměnná: a b p_a int a = 7, b = 0; // Definice promennych typu int int *p_a = NULL; // Definice ukazatele na promennou typu int a b p_a 7 0 NULL p_a = &a; b = *p_a; // Do ukazatele p_a priradime adresu promenne a // Do promenne b se priradi hodnota promenne, // ktera se nachazi na adrese zapsane v p_a // coz je promenna a, do b se tedy priradi 7 7 0 1004 7 7 1004 4

Práce s ukazateli Na spojení dereferenčního operátoru * se jménem ukazatele nahlížíme jako by to byla proměnná, tj, můžeme mu přiřadit hodnotu, používat při předání hodnoty proměnné (na niž ukazuje) do volané funkce a pod. Adresa v paměti: Její obsah: Proměnná: int a = 7; int *p_a = NULL; 1000 1004 1008 1012 1016 1020 1024 7 NULL a p_a a p_a 7 NULL p_a = &a; // Do ukazatele p_a priradime // adresu promenne a *p_a = 8; // Zpusobi, ze do promenne a se priradi 8 printf("%i %i", a, *p_a); // Vypise hodnotu a, take hodnotu // z adresy na niz ukazuje p_a // (coz je take a) // V obou pripadech se vypise 8 7 1004 8 1004 5

Ukazatele jako parametry funkcí Funkce v jazyce C mohou vrátit pouze jednu hodnotu Chceme-li vrátit více hodnot, používáme ukazatele Pro proměné do nichž chceme uložit návratové hodnoty předáme funkci jejich ukazatele. Uvnitř funkce tyto ukazatele dereferencujeme a přiřadíme jim potřebné hodnoty. Stejný mechanismus využívají funkce scanf() a fscanf() // Funkce spocita soucet a rozdil prvnich dvou parametru (tj. a, b) // a vysledky priradi do promennych na nez ukazuji dva predavane // ukazatele (tj. p_res1 a p_res2) void soucet_rozdil(int a, int b, int *p_res1, int *p_res2) { *p_res1 = a + b; *p_res2 = a b; } int main() { int x = 8, y = 3; int result1 = 0, result2 = 0; } soucet_rozdil(x, y, &result1, &result2); printf("soucet %i a %i je %i\n", x, y, result1); printf("rozdil %i a %i je %i\n", x, y, result2); 6

Pole a ukazatele V jazyce C používáme obvykle jméno pole ve spojení s hranatými závorkami [] v nichž uvádíme index (tj. pořadí) prvku pole s nímž chceme pracovat Pokud použijeme jméno pole bez uvedení hranatých závorek, je toto považováno za ukazatel na začátek pole, tj. ukazatel na první prvek pole Pokud k názvu pole přičteme číselnou hodnotu n, získáme ukazatel na n-tý prvek pole (tj. prvek pole s indexem n) int n = 0; int *p = NULL; int a[6] = {4, 12, 9, 4, 25, 18}; p = a; // Do ukazatele p se ulozi adresa zacatku pole p = &a[0]; // Totez zapsane jinak n = *a; // Do n se ulozi hodnota prvku pole a[0] (tj. 4) n = *(a + 2); // Do n se ulozi hodnota prvku pole a[2] (tj. 9) Prvky pole: a[0] a[1] a[2] a[3] a[4] a[5] a[6] Ukazatele: a a+1 a+2 a+3 a+4 a+5 a+6 7

Řetězce a ukazatele Řetězce jsou pole typu char [] obsahující zakončovací znak \0 Pro řetězce platí stejná pravidla jako pro pole, tj. jméno řetězcové proměnné použité bez [] je považováno za ukazatel na začátek pole (a při přičtení číselné hodnoty ukazuje na příslušný prvek pole) char s[20] = "HELLO"; char *p_s = NULL; p_s = s; // Promenna p_s bude ukazovat na zacatek retezce s printf("retezec: %s\n", p_s); // Vypise HELLO p_s = s+2; // Promenna p_s bude ukazovat na s[2] printf("retezec: %s\n", p_s); // Vypise LLO 8

Funkce pro manipulaci s textovými řetězci Pro zjednodušení práce s textovými řetězci jsou v jazyce C k dispozici funkce pro práci s řetězci Chceme-li používat funkce pro práci s řetězci, je třeba vložit na začátek programu #include <string.h> Seznam nejdůležitějších funkcí (pouze jména): strlen() zjištění délky řetězce strcpy(), strncpy() kopírování řetězců strcat(), strncat() spojování dvou řetězců strchr(), strrchr() hledání znaku v řetězci strstr(), strcasestr() hledání podřetězce v řetězci strcmp(), strncmp() porovnání dvou řetězců Podrobnější informace lze získat z manuálových stránek UNIXu (man jmeno_funkce případně man 3 jmeno_funkce) 9

Zjištění délky řetězce int strlen(const char *s); Funkce strlen() vrací délku řetězce (tj. počet znaků nacházejících se před zakončovacím znakem '\0') Funkce pro práci s řetězci používají při definici řetězce jako parametru zápis char *s místo char s[], z praktického hlediska je funkčnost obou zápisů stejná Použití slova const, znamená, že předávaný řetězec bude uvnitř funkce pouze čten, nebude do něj zapisováno // Na zacatku musime vlozit #include <string.h> char s[] = "Tady je nejaky text"; int length = 0; length = strlen(s); printf("delka retezce je: %i\n", length); 10

Kopírování řetězce char *strcpy(char *dest, const char *src); char *strncpy(char *dest, const char *src, int size); Funkce strcpy() kopíruje řetězec src (z angl. source) do dest (z angl. destination), kopírují se všechny znaky, dokud se nenarazí na '\0' (v řetězci src), nakonec se do dest zkopíruje i znak '\0' Funkce strncpy() pracuje podobně ale kopíruje se maximálně size znaků. Pokud je řetězec src kratší než size, zkopíruje se i znak '\0', v opačném případě se '\0' nezkopíruje a řetězec dest zůstane nezakončený! Proto po použití funkce strncpy() vždy přiřadíme '\0' do posledního znaku dest Návratová hodnota je ukazatel na řetězec dest POZOR: v praxi upřednostňujeme funkci strncpy() protože v případě použití strcpy() hrozí riziko překročení mezí řetězce dest pokud je délka src větší než paměť alokovaná pro dest 11

Kopírování řetězce - příklad // Ukazka pouziti funkce strcpy() char s1[] = "Tady je nejaky text"; char s2[100] = ""; // Do retezce s2 bude zkopirovan obsah retezce s1 strcpy(s2, s1); // Ukazka pouziti funkce strncpy() char s1[] = "Tady je nejaky text"; char s2[30] = ""; // Do retezce s2 bude zkopirovan obsah retezce s1, // ale max. 29 znaku strncpy(s2, s1, 29); // Do posledniho znaku retezce s2 priradime '\0', // jinak by mohl zustat nezakonceny s2[29] = '\0'; 12

Spojení řetězců char *strcat(char *dest, const char *src); char *strncat(char *dest, const char *src, int size); Funkce strcat() přidá řetězec src na konec řetězce dest, a na konec přidá znak '\0' (znak '\0' který se původně nacházel na konci dest je přepsán) Funkce strncat() pracuje podobně, ale z řetězce src přidá do dst maximálně size znaků + znak '\0' (tedy až size + 1 znaků) Návratová hodnota je ukazatel na řetězec dest Při použití těchto funkcí musíme dávat pozor aby nedošlo k překročení mezí polí pro řetězce #define STR_SIZE 100 char s1[str_size] = "JEDNA "; char s2[str_size] = "DVA "; char s3[str_size] = "TRI CTYRI PET"; strcat(s1, s2); // Retezec s2 pridame na konec retezce s1 strncat(s1, s3, 3); // Dale do s1 pridame 3 znaky z retezce s3 printf("retezec: %s", s1); // Vypise: JEDNA DVA TRI 13

Nalezení znaku v řetězci char *strchr(char *s, int c); char *strrchr(char *s, int c); Funkce strchr() hledá znak c v řetězci s a vrátí ukazatel na jeho první výskyt, pokud znak není nalezen, vrací NULL Funkce strrchr() pracuje podobně, ale vyhledává poslední výskyt znaku (tj. prohledává řetězec od zadu - reverzně) char s[] = "FILE=crambin.pdb"; char *p_s = NULL; // Hledame znak '=', je li nalezen pak je p_str ruzne od NULL // a bude ukazovat na pozici znaku '=' p_s = strchr(s, '='); if (p_s!= NULL) printf("jmeno souboru: %s\n", p_s+1); // Vypise crambin.pdb char s[] = "/home/martinp/data/crambin.pdb"; char *p_s = NULL; // Hledame znak '/' od zadu abychom ziskali jmeno souboru // bez pocatecni adresarove cesty p_s = strrchr(s, '/'); if (p_s!= NULL) printf("jmeno souboru: %s\n", p_s+1); // Vypise crambin.pdb 14

Nalezení podřetězce v řetězci char *strstr(const char *haystack, const char *needle); Funkce strstr() hledá první výskyt řetězce needle v řetězci haystack a vrátí ukazatel na příslušné místo v řetězci haystack. V případě neúspěchu vrací NULL Pokud potřebujeme aby funkce nerozlišovala velká a malá písmena, použijeme strcasestr() char s[] = "Jmeno proteinu je crambin"; char *p_s = NULL; // V retezci s hledame podretzec "crambin", // je li nalezen pak je p_str ruzne od NULL // a bude ukazovat na pozici kde zacina hledany text p_s = strstr(s, "crambin"); if (p_s!= NULL) { printf("slovo crambin bylo nalezeno\n"); printf("text od nalezene pozice: %s\n", p_s); // Vypise: crambin } // Hledame zda li na zacatku retezce s je "Jmeno", pokud ano, // bude vraceny ukazatel ukazovat na zacatek s a tedy bude roven s p_s = strstr(s, "Jmeno"); if (p_s == s) printf("retezec zacina na Jmeno\n"); 15

Porovnání dvou řetězců int strcmp(const char *s1, const char *s2); int strncmp(const char *s1, const char *s2, int size); Funkce strcmp() porovnává řetězce s1 a s2 Funkce strncmp() pracuje podobně ale porovnává pouze prvních size znaků Funkce vrací 0 pokud jsou oba řetězce totožné, zápornou hodnotu pokud s1 je lexikograficky menší než s2, jinak vrací kladnou hodnotu Funkce rozlišují malá a velká písmena (malá písmena jsou lexikograficky větší než velká) Pro porovnání řetězců bez rozlišení velkých a malých písmen lze použít funkce strcasecmp() a strncasecmp() char s1[] = "ATOM1", s2[] = "ATOM2"; if (strcmp(s1, s2) == 0) printf("retezce jsou totozne\n"); else printf("retezce jsou rozdilne\n"); if (strncmp(s1, s2, 4) == 0) printf("shoda v prvnich 4 znacich.\n"); else printf("retezce se lisi v prvnich 4 znacich\n"); 16

Předání parametrů příkazového řádku do funkce main() Funkce main() v jazyce C existuje ve dvou verzích, jedna verze je bez parametrů a druhá verze s argumenty argc a argv; druhou verzi používáme pokud chceme zpracovat parametry předané programu na příkazovém řádku Argument argc obsahuje počet parametrů předaných programu na příkazovém řádku zvětšený o 1 Proměnná argv je pole ukazatelů na řetězce, každý prvek pole odpovída jednomu předanému parametru První hodnota v argv je vždy název a cesta programu tak jak byly uvedeny na příkazovém řádku (proto je argc vždy >= 1) // Program vypise pocet predavanych parametru a jejich seznam int main(int argc, char *argv[]) { int i = 0; printf("pocet predavanych parametru: %i\n", argc); for (i = 0; i < argc; i++) printf("parametr cislo %i je: %s\n", i, argv[i]); return 0; } 17

Dodržujte následující pravidla Při definici proměnných nedávejte příliš mnoho proměnných na jeden řádek. Raději definujte každou proměnnou na smostatném řádku (pak je lze snadněji okomentovat). Na jednom řádku definujte pouze proměnné které spolu souvisí a lze je opatřit jednotným komentářem. Používejte komentáře: Na začátek programu umístěte stručný komentář popisující činnost programu Před každou funkci umístěte komentář popisující její účel, význam předávaných prametrů a význam návratové hodnoty Všechny proměnné (globální i lokální) opatřete komentářem. Proměnné i, j, k, používejte pouze výhradně jako řídící proměnné cyklu (pro jiné účely tyto proměnné nepoužívejte), pak je nemusíte opatřovat komentářem. 18

Úlohy část 1 1. Upravte program pro řešení kvadratické rovnice (cv. 1, úloha 1) tak, aby kořeny byly spočítány v samostatné funkci volané z main(). Do funkce budou předány parametry kvadratické rovnice a, b, c a pomocí ukazatelů budou vráceny hodnoty dvou kořenů. Návratovou hodnotou funkce bude počet nalezených kořenů. 1 bod 1. Vytvořte jednoduchý program který bude obsahovat funkci na záměnu hodnot dvou celočíselných proměnných. Program nejdříve načte od uživatele dvě celá čísla do dvou proměnných. Potom zavolá funkci, která přehodí hodnoty těchto proměnných (obě proměnné do ní budou předány jako ukazatele). Nakonec budou vypsány hodnoty obou proměnných. 1 bod 19

Úlohy část 2 3. Vytvořte program pro procvičení práce s řetězci. Program načte od uživatele řetězec. Poté předá řetězec do samosatné funkce která provede následující: Zjistí délku předaného řetězce a vypíše ji na obrazovku Zkopíruje první 4 znaky do jiného pomocného řetězce s1 a dále zkopíruje 6 znaků od pozice 9. znaku (číslováno od 0) do řetězce s2. Na obrazovku vypíše oba řetezce. Porovná první 4 znaky obou řetězců s1 a s2 a vypíš informaci, zdali se shodují nebo ne. Řetězce s1 a s2 se spojí do jednoho řetězce a to tak, že se nejdříve se zkopíruje obsah s1 do pomocného řetězce s3 a pak se k němu přidá řetězec s2. Výsledný řetězec s3 se vypíše na obrazovku. Určí se délka řetězce s3 a vypíše se na obrazovku. Nakonec implementujte do programu možnost zadat vstupní řetězec jako parametr na příkazovém řádku. Pokud uživatel nezadá řetězec na příkazovém řádku tak si program vyžádá jeho zadání přímo (jako v předchozím případě). 2 body 20

Úlohy část 3 4. Upravte program pro načítání zjednodušeného PDB souboru z předchozího cvičení (cv. 6, úloha 3). Do programu přidejte funkci, která na obrazovku vypíše seznam residuí. Na každém řádku bude vždy uvedena zkratka residua, číslo residua, název a číslo prvního atomu residua (tj. atomu který je v souboru uveden jako první pro dané residuum). 1 bod 21