10 Práce s řetězci - pokračování Máme deklarováno: char retez[50]; - čtení z klávesnice: scanf("%s", retez); - čtení zadané počtu znaků z klávesnice scanf("%10s", retez); // přečti řetězec z klávesnice,max však 10 znaků - tisk na obrazovku: printf("%s", retez); - čtení celého řádku z klávesnice: gets(retez); - pro pointery lze také p_ret = gets(); - tisk řádku/řetězce na obrazovku: puts(retez); - čtení celého řádku ze souboru: fgets(retez, fr); // kde FILE *fr; - tisk řádku/řetězce do souboru: fputs(retez, fw); // kde FILE *fw; Síla příkazů gets a puts je v tom, že mohu znak po znaku zkontrolovat, co uživatel zadal. Když zjistím, že vstup je OK, mohu použít funkce: sscanf(retez, "%d, %d", &a, &b); - čte z řetězce, jako by to byla klávesnice
Opačná funkce: sprintf(retez, "Vysledek je: %f Ohm", a); - tiskne do řetězce, jakoby to byla obrazovka. A potom použiji puts(retez); a je to na obrazovce. #include <stdio.h> #include <stdlib.h> int main() { char zprava[300]; gets(zprava); puts(zprava); double R, U, I; U = 45.78; I = 0.34; R = U / I; sprintf(zprava, "\nvysledek je: %f [Ohm]\n", R); puts(zprava); FILE *fw; fw = fopen("vysledek.txt", "w"); if (fw == NULL) { printf("\nsoubor se nepodarilo otevrit...\n"); return -1; fprintf(fw, "%s", zprava); fputs(zprava, fw); if (fclose(fw) == EOF) { printf("\nsoubor se nepodarilo uzavrit...\n"); return 0;
Základní funkce pro operace s řetězci string.h strcat strchr strcmp strcoll strcpy strcspn strerror strlen strncat strncmp strncpy strpbrk strrchr strspn strstr strtok strxfrm char *strcat( char *dest, const char *src); Funkce připojí řetězec src k řetězci dest. Funkce vrací ukazatel na řetězec dest. char *strncat( char *dest, const char *src, size_t n); Jako funkce strcat, ale přidá jen n znaků z src. Tato funkce je bezpečnější z hlediska možného "přetečení" (pokus zapisovat více dat, než jakou má velikost dest). int strcmp(const char *s1, const char *s2); Porovnává řetězce s1 a s2. Pokud je s1 < s2 pak vrací hodnotu menší než 0, pokud jsou si rovny, pak vrací 0, pokud je s1 > s2 pak vrací hodnotu větší jak 0. int strncmp( const char *s1, const char *s2, size_t n); Jako strcmp(), porovnává však jenom n znaků. char *strcpy( char *dest, const char *src); Zkopíruje řetězec src do řetězce dest. Vrací ukazatel na dest. (Používá se místo přiřazení naplnění řetězce.) char *strncpy( char *dest, const char *src, size_t n); Jako strcpy(), ale zkopíruje maximálně n znaků. (Je-li jich právně n, nepřidá zarážku). size_t strlen( const char *s); Vrací délku řetězce s. char *strchr( const char *s, int c); Vrací ukazatel na první pozici, kde se vyskytuje znak c, nebo NULL v případě, že jej nenajde. (Nenechte se zmást, že znak c je typu int a ne char, má to tak být). char *strrchr( const char *s, int c); To samé jako strchr(), ale hledá první výskyt zprava. char *strstr( const char *haystack, const char *needle); Vrací ukazatel na první výskyt řetězce needle v řetězci haystack. Pokud jej nenajde, vrací NULL. size_t strspn( const char *s, const char *accept); Vrací počet znaků, ve kterých se řetězec s schoduje s řetězcem accept. size_t strcspn( const char *s, const char *reject); Vrací počet znaků, ve kterých se řetězec neshoduje s řetězcem reject. [Zdroj: www.sallyx.org ] char prvni[20], druhy[20]; strcpy(prvni, "Ahoj"); strcpy(druhy, "Nazdar");
printf("\nporovnani %s %s vrati %d", prvni, druhy, strcmp(prvni, druhy)); printf("\nporovnani %s %s vrati %d", druhy, prvni, strcmp(druhy, prvni)); Vytiskne: Porovnani Ahoj Nazdar vrati -1 Porovnani Nazdar Ahoj vrati 1 V <stdlib.h> jsou funkce pro převod typu řetězecčíslo: a = atoi(retezec); - ascii to int Např. z řetězce "23" udělá int 23 atol ascii to long atof ascii to float (pozor konvertuje na double) double cislo; cislo = atof("0.0"); printf("\ncislo je %f\n", cislo); /* S kontrolou jedině pomocí sscanf: */ int povedlo; char retcis[10]; strcpy(retcis, "dsdfghdghd23.5"); povedlo = sscanf(retcis, "%lf", &cislo); printf("\npovedlo se %d, cislo je %f\n", povedlo, cislo); Projdu řetězec a převedu všechny znaky v něm na velké: #define DELKA_RETEZCE 100... char retezec[delka_retezce];
int i;......naplnění a další příkazy i = 0; while ((retezec[i]!= '\0') && (i < DELKA_RETEZCE)) { retezec[i] = toupper(retezec[i]); i++; Pokud neznám funkci toupper: i = 0; while ((retezec[i]!= '\0') && (i < DELKA_RETEZCE)) { retezec[i] = ((retezec[i] >= 'a') && (retezec[i] <= 'z'))? retezec[i] ('a' - 'A') : retezec[i]; i++; Pozn.: - na disku jsou hlavičkové soubory v adresáři překladače (prostředí) v podadresáři /include (a jsou komentované)
Vstup a výstup do souboru ANSI C - 2 typy souborů - binární - textové Jak otevřít soubor pro čtení a jak pro zápis: - musím si připravit proměnnou typu FILE * int main(void) { /* vytvoreni promenne-file descriptor - budouci odkaz na soubor */ FILE *fr, *fw; /* otevreni souboru - pozor na // v ceste k souboru "r" - znaci, ze budu jen cist */ fr = fopen("d:\\pozdravy\\nazdar.txt", "r"); /* otevreni souboru - pozor na // v ceste k souboru "w" - znaci, ze budu zapisovat */ fw = fopen("d:\\pozdravy\\ahoj.txt", "w"); Textové soubory režimy otevření souborů r čtení w zápis (přepsání) a zápis do do souboru - zapisuje na konec existujícího souboru (na rozdíl od "w" nesmaže původní obsah souboru) r+ čtení a zápis w+ čtení, zápis a přepsání a+ čtení a zápis na konec Binární soubory režimy otevření souborů rb, wb, ab pro binární soubory rb+, wb+, ab+ pro binární soubory
Klávesnice a obrazovka funkce vstupu/výstupu vstup znaku: c = getchar(); tisk znaku: putchar(c); formátované čtení klávesnice: scanf("%d, %d ", &i, &j); formátovaný tisk na obrazovku: printf("%f", cislo); Přečtení celého řádku až po Enter: char s[300], *jine_s; gets(s); jine_s = gets(); např. mohu zkontrolovat, co uživatel zadal přes klávesnici a je-li to v pořádku, mohu potom z řetězce celé číslo přečíst pomocí: sscanf(s, "%d", &i) Tisk do řetězce: sprintf(s, "Cislo je %f", cislo); Zápis řetězce na obrazovku: puts(s); Pro soubory funkce vstupu/výstupu FILE *fr, *fw; fr = fopen("d:\\pozdravy\\nazdar.txt", "r"); fw = fopen("d:\\pozdravy\\ahoj.txt", "w"); - čtení jednoho znaku ze souboru: c = getc(fr); /*ctu z nazdar.txt*/ - zápis jednoho znaku do souboru: putc(c, fw); /*zap. do ahoj.txt*/
formátované čtení ze souboru: fscanf(fr, "%d", &i); formátovaný tisk do souboru: fprintf(fw, "%f", cislo); Např.: a = 2.4; b = 5.6; c = 8.9; d = 4.5; fprintf(fr, "%f;%f;%f;%f\n", a, b, c, d); V souboru bude: 2.4;5.6;8.9;4.5 EOF znaková konstanta - značí konec souboru (End Of File), je deklarována v stdio.h Lepší je použít funkci feof(fr); - vrací 1, když jsem na konci souboru Pro ukončení práce se souborem, je nutno soubor uzavřít: fclose(fr); fclose(fw); /* uzavření obou souborů */
Pozor na různé značení konce řádky \n\r obvykle Windows \r \n Unix apod. Test konce souboru též lze pomocí makra feof(fr); /* vrací pravda jsme-li na konci souboru */ Např. tisk obsahu souboru na obrazovku: while (!feof(fr)) { c = getc(fr); putchar(c); - feof je vhodné použít při práci s binárními soubory (kde nejde použít test na konstantu EOF jako u textových) Test otevření souboru dělejte vždy!!! - test na konst. NULL if ((fr = fopen("orig.txt", "r")) == NULL) { printf("soubor ORIG.TXT se nepodarilo otevrit\n"); return; /* ukonceni funkce */ Totéž, ale rozepsané: fr = fopen("orig.txt", "r"); if (fr == NULL) { printf("soubor ORIG.TXT se nepodarilo otevrit\n"); return; /* ukonceni funkce */
Test zavření souboru - test na konst. EOF if (fclose(fr) == EOF) { printf("soubor ORIG.TXT se nepodarilo uzavrit\n"); return; Totéž, ale rozepsané: int jaktodopadlo; jaktodopadlo = fclose(fr); if (jaktodopadlo == EOF) { printf("soubor ORIG.TXT se nepodarilo uzavrit\n"); return;