NOVINKA - Online rekvalifikační kurz Python programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze – Lekce 9 - Textové řetězce v jazyce C podruhé - Práce se znaky

Zpět

Upozorňujeme, že diskuze pod našimi online kurzy jsou nemoderované a primárně slouží k získávání zpětné vazby pro budoucí vylepšení kurzů. Pro studenty našich rekvalifikačních kurzů nabízíme možnost přímého kontaktu s lektory a studijním referentem pro osobní konzultace a podporu v rámci jejich studia. Toto je exkluzivní služba, která zajišťuje kvalitní a cílenou pomoc v případě jakýchkoli dotazů nebo projektů.

Komentáře
Avatar
DarkCoder
Člen
Avatar
DarkCoder:28.1.2022 14:34

Jelikož se ve zdrojovém kódu Cézarovy šifry uvedeném v článku vyskytuje chyba, kde při vyšších hodnotách posunu nedochází k přechodu od 'z' k 'a', přikládám zde novou verzi doplněnou o lepší programátorské praktiky a pokročilejší programátorské techniky.

#include <stdio.h>

int main(void) {
        unsigned char str[] = "abcdefghijklmnopqrstuvwxyz";
        unsigned char *pstr = str;
        unsigned char shift = 27; // 0 - 255
        const unsigned char range = 'z' - 'a' + 1;

        shift %= range; // normalizace posunu (0 - 25)

        puts(str); // puvodni text

        while (*pstr) *pstr++ += (*pstr + shift > 'z') ? (shift - range) : shift;

        puts(str); // zasifrovany text

        return 0;
}
Odpovědět
28.1.2022 14:34
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
DarkCoder
Člen
Avatar
DarkCoder:28.1.2022 18:59

Pro všechny, co si zde zkoušejí či využívají program - Analýza výskytů ve větě, je nutno poznamenat, že databáze znaků reprezentující souhlásky a samohlásky je chybná (dvě U a absence velkého I b samohláskách a i v souhláskách). Chybou z principu toho jak program funguje je pouze záměna I za U v samohláskách. Přebytečné písmeno i v souhláskách akorát zpomaluje běh programu.

Pominuli tuto chybu vzniklou při psaní, program funguje, leč jeho rychlost je extrémně pomalá. Důvodem je postupné procházení kategorií a testování na výskyt znaku. Rychlost bude tak pomalá, na jaký typ znaku budeme testovat (ostatní znaky nejpomalejší, čísla pomalá, atd.), dle pořadí v hlavním cyklu. Program svoji funkci plní, ale není stavěn na rychlost, jak už to bylo v článku zmíněno.

Pro zvídavé, jak program podstatně urychlit, je zde jiná verze využívající pole k uchování typu znaku. Jelikož každý znak má číselnou hodnotu, lze na konkrétní index pole zaznamenat typ daného znaku. Díky tomu lze okamžitě přečíst o jaký typ znaku jde. Ve zdrojovém kódu jsou opět použity pokročilejší programovací techniky.

#include <stdio.h>

#define UCHAR_MAX 0xff

typedef enum { OSTATNI, SAMOHLASKY, SOUHLASKY, CISLA, POCET_TYPU } TYP_ZNAKU;
typedef unsigned char UCHAR;

void priprava(UCHAR* kam, UCHAR* odkud, TYP_ZNAKU typ);

int main(void) {
        UCHAR identifikace[UCHAR_MAX] = { 0 };
        UCHAR samohlasky[] = "aeiouyAEIOUY";
        UCHAR souhlasky[] = "bcdfghjklmnpqrstvwxzBCDFGHJKLMNPQRSTVWXZ";
        UCHAR cisla[] = "0123456789";
        UCHAR text[] = "Programator se zasekne ve sprse, protoze instrukce na samponu byly: Namydlit, omyt, opakovat 2x.";
        UCHAR* ptext = text;
        UCHAR pocet[POCET_TYPU] = { 0 };

        priprava(identifikace, samohlasky, SAMOHLASKY);
        priprava(identifikace, souhlasky, SOUHLASKY);
        priprava(identifikace, cisla, CISLA);

        puts(text);

        while (*ptext) {
                switch (identifikace[*ptext]) {
                        case OSTATNI: pocet[OSTATNI]++; break;
                        case SAMOHLASKY: pocet[SAMOHLASKY]++; break;
                        case SOUHLASKY: pocet[SOUHLASKY]++; break;
                        case CISLA: pocet[CISLA]++; break;
                }
                ptext++;
        }

        printf("Pocet samohlasek: %d\n", pocet[SAMOHLASKY]);
        printf("Pocet souhlasek: %d\n", pocet[SOUHLASKY]);
        printf("Pocet cisel: %d\n", pocet[CISLA]);
        printf("Pocet ostatnich znaku: %d\n", pocet[OSTATNI]);

        return 0;
}

void priprava(UCHAR* kam, UCHAR* odkud, TYP_ZNAKU typ) {
        while (*odkud) kam[*odkud++] = typ;
}
Odpovědět
28.1.2022 18:59
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Maroš Motaj
Člen
Avatar
Maroš Motaj:22.3.2022 14:08

Pridávam svoju verziu, asi je nič moc ale vynechal som tu metódu obsahuje_znak()

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main(void){
    int pocetSamohlasky = 0;
    int pocetSpoluhlasky = 0;
    int pocetCisla = 0;
    int zvysneZnaky = 0;

    char veta[] = "Mount Everest";
    char samohlasky[] = "aeiouyAEUOUY";
    char spoluhlasky[] = "bcdfghijklmnpqrstvwxzBCDFGHIJKLMNPQRSTVWXZ";
    char cisla[] = "0123456789";

    int i;
    for (i=0;veta[i]!='\0';i++){
        if (strchr(samohlasky, veta[i])!=NULL){
            pocetSamohlasky += 1;
        }
        else if (strchr(spoluhlasky, veta[i])!=NULL){
            pocetSpoluhlasky += 1;
        }
        else if (strchr(cisla, veta[i]!=NULL)){
            pocetCisla += 1;
        }
        else{
            zvysneZnaky += 1;
        }

    }

    printf("Samohlasky: %d\n", pocetSamohlasky);
    printf("Spoluhlasky: %d\n", pocetSpoluhlasky);
    printf("Cisla: %d\n", pocetCisla);
    printf("Zvysne znaky: %d\n", zvysneZnaky);

    return 0;
}
 
Odpovědět
22.3.2022 14:08
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Maroš Motaj
DarkCoder:22.3.2022 15:34

Ano, využití funkce strchr() z knihovny string.h je možným řešením jak úlohu řešit. Nahrazuje vlastní implementaci hledání znaku pomocí funkce obsahuje_znak(). Pokud není prioritou rychlost, pak je tato verze vhodná, neboť je velmi čitelná a na první pohled je zřejmé co se tam děje.

Doplním pár drobností k programu:

  • Není třeba vkládat hlavičkový soubor stdlib.h, makro NULL je definováno i v hlavičkovém souboru string.h. Zřejmě ho tam máš jako pozůstatek používání makra EXIT_SUCCESS při vrácení hodnoty funkce main().
  • Počty znaků dané kategorie nemohou být záporné, vhodnější je použít modifikátor typu unsigned. Není to však chybou.
  • hodnoty v polích samohlasky a spoluhlasky jsou chybné. Dvě U a absence velkého I v samohláskách a i I v spoluhláskách). Chybou z principu toho jak program funguje je pouze záměna I za U v samohláskách. Přebytečné písmeno i v spoluhláskách akorát zpomaluje běh programu.
  • Ač je tělo for cyklu správně:
for (i=0;veta[i]!='\0';i++){

Obvykle se to zapisuje takto:

for (i=0;veta[i];i++){

Podmínka cyklu se vyhodnotí a for cyklus proběhne, když je výraz nenulový.

  • obdobně vnitřek příkazu if
if (strchr(samohlasky, veta[i])!=NULL){

napsat takto:

if (strchr(samohlasky, veta[i])){

Funkce strchr() vrací platný ukazatel na výskyt znaku v poli, toto se vyhodnocuje jako pravdivý výraz. Pokud funkce strchr() znak nenajde, vrací NULL, což způsobí, že kód spojený s if se neprovede.

  • pro inkrementaci proměnné o 1 má jazyk C speciální operátor ++. Tedy zápis
pocetSamohlasky += 1;

Ač je v pořádku, s zapisuje takto:

pocetSamohlasky++;

Pro samostatnou proměnnou lze zapsat i v prefix verzi

++pocetSamohlasky;

Pro dekrementaci (snížení hodnoty proměnné o 1) se používá operátor --. Použití je analogické s operátorem inkrementace ++.

Odpovědět
22.3.2022 15:34
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Maroš Motaj
Člen
Avatar
Odpovídá na DarkCoder
Maroš Motaj:22.3.2022 16:47

Ahoj ďakujem, som to poštudoval o opravil :) ten increment++ som poznal z Javy, ale nešlo mi to nejak asi som mal inde chybu... ale už to ide :)

 
Odpovědět
22.3.2022 16:47
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 5 zpráv z 35.