Znakové řetězce


Deklarace a inicialisace:  cislice[] = "9876543210";

pole znaků s ukazatelem           pole znaků s ukazatelem
  '9' '8' '7' '6' '5' '4' '3' '2' '1' '0' '\0'
   cislice    ^                    
    alternativně    
  '9' '8' '7' '6' '5' '4' '3' '2' '1' '0'  0 
   cislice    ^                    


    Kolik znakových řetězců tu je?



odpověď






Deklarace a inicialisace:  pismena[20] = "abcdefghij";

'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' '\0' znakový řetězec prostor pro jeho prodlužování obsah v něm nás nezajímá znakový řetězec a i jeho '\0' nesmí přes tuto červenou čáru na růžové místo smí jen '\0'

V jazyku C se o to, aby znakový řetězec nebyl větší, než je místo pro něj vyčleněné (s možnými nepříjemnými následky:
přepsání hodnot v jiných proměnných a nebo vyvolání přerušení z důvodu porušení ochrany paměti) musí postarat
programátor.





Napište funkci strchins podle následujících pokynů a informací do tohoto programu
/**
 * @file  vkladaniDovnitr.c
 * @author  Ales  Zlamal 
 */

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

/**
 * Funkce vlozi zadany znak do znakoveho retezce na zadane misto 
 *
 * @param  b   ukazatel, kam se ma znak vlozit
 * @param  d   kolik mista jeste zbyva do konce mista pro znakovy retezec
 * @param  z   znak, jenz se ma vlozit
 * @return  NULL, pokud se vkladany znak jiz nevesel; anebo pokud se vesel, adresu kam mel byt vlozen 
 */
char *strchins(char *b, int d, char z);

#define DELKA_RETEZCE 25

int main()
{
    char str[DELKA_RETEZCE] = "Pridava se dopredu: ";
    
    printf("%s\n", str);
    strchins(str + 20, DELKA_RETEZCE - strlen(str), 'D');
    printf("%s\n", str);
    strchins(str + 20, DELKA_RETEZCE - strlen(str), 'C');
    printf("%s\n", str);
    strchins(str + 20, DELKA_RETEZCE - strlen(str), 'B');
    printf("%s\n", str);
    strchins(str + 20, DELKA_RETEZCE - strlen(str), 'A');
    printf("%s\n", str);
    printf("Delka retezce je %zu.\n", strlen(str));
    if (strchins(str + 20, DELKA_RETEZCE - strlen(str), 'X') == NULL) {
        printf("Nejde to - ");
    }
    printf("%s\n", str);
    printf("Delka retezce je %zu.\n", strlen(str));
    return EXIT_SUCCESS;
}

'a' 'b' 'c' 'd' 'e' 'f' 'X' 'g' 'h' 'i' 'j' '\0' sem chceme vlozit X Start

Princip je skoro stejný jako v třídění zařazováním (Insert sortu).

Výstup programu je:
Pridava se dopredu: 
Pridava se dopredu: D
Pridava se dopredu: CD
Pridava se dopredu: BCD
Pridava se dopredu: ABCD
Delka retezce je 24.
Nejde to - Pridava se dopredu: ABCD
Delka retezce je 24.





Použitím funkce strchins (stejné jako v předchozím zadání) napište nerekursivní funkci, která zadanou číselnou hodnotu vyjádřenouv pravidelné posiční soustavě o zadaném základu vloží do zadaného místa znakového řetězce.
/**
 * @file  vyjadreniCisel.c
 * @author  Ales  Zlamal 
 */

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

/**
 * Funkce udela ze zadane ciselne hodnoty prislusnou cislici
 *
 * @param  x   cislena hodnota
 * @return  cislice 
 */
char cislice(unsigned int x);

/**
 * Funkce vlozi zadany znak do znakoveho retezce na zadane misto 
 *
 * @param  b   ukazatel, kam se ma znak vlozit
 * @param  d   kolik mista jeste zbyva do konce mista pro znakovy retezec
 * @param  z   znak, jenz se ma vlozit
 * @return  NULL, pokud se vkladany znak jiz nevesel; anebo pokud se vesel, adresu kam mel byt vlozen 
 */
char *strchins(char *b, int d, char z);

/**
 * Funkce vlozi cislo v posicni soustave se zadanym zakladem do znakoveho retezce na zadane misto 
 *
 * @param  s   ukazatel, kam se ma znak vlozit
 * @param  d   kolik mista jeste zbyva do konce mista pro znakovy retezec
 * @param  c   cislo, jehoz representace se ma vlozit
 * @param  z   zaklad represenace cisla, jehoz representace se ma vlozit
 * @return  NULL, pokud se vkladany znak jiz nevesel; anebo pokud se vesel, adresu kam mel byt vlozen 
 */
char *strnumbsins(char *s, int d, unsigned int c, unsigned int b);

#define DELKA_RETEZCE 75
#define D_C 12

int main()
{
    unsigned int cislo, zaklad; 
    char rtz[DELKA_RETEZCE];
    char s[D_C];
    char *kca;

    for(;;) {
        printf("Zadejte cislo a zaklad: ");
        if (fgets(s, D_C, stdin) == NULL || *s == '\n') break;
        cislo = (unsigned int)strtoul(s, &kca, 10);
        if (*kca != '\n') { 
            zaklad = (unsigned int)strtoul(kca, &kca, 10);
        } else {
            printf("Zadejte jeste zaklad: ");
            if (fgets(s, D_C, stdin) == NULL || *s == '\n') break;
            zaklad = (unsigned int)strtoul(s, &kca, 10); 
        }
        sprintf(rtz, "Cislo %u je v pravidelne posicni soustave o zakladu %u rovno ", cislo, zaklad); 
        strnumbsins(rtz, DELKA_RETEZCE, cislo, zaklad); 
        printf("%s.\n", rtz); 
        printf(" Delka retezce je %zu.\n", strlen(rtz));
    }
    return EXIT_SUCCESS;
}


char cislice(unsigned int x)
{
    return x < 10 ? '0' + x : 'A' - 10 + x; 
}


Výstup programu je:
Zadejte cislo a zaklad: 2184
Zadejte jeste zaklad: 2
Cislo 2184 je v pravidelne posicni soustave o zakladu 2 rovno 100010001000.
 Delka retezce je 74.
Zadejte cislo a zaklad: 4096 2
Cislo 4096 je v pravidelne posicni soustave o zakladu 2 rovno 000000000000.
 Delka retezce je 74.
Zadejte cislo a zaklad:




Parsing

V češtině pro parsovat, parsování a parsing nemáme vhodné termíny a tak se zhusta používají odvozeniny toho anglofonního.
(Při čtení anglofonní odborné literatury se tak zmenšuje možnost zmatení … )
Parsování znamená rozdělit znakový řetězec na znakové podřetězce navzájem oddělené zadanými oddělovači.
Ilustraci zvolíme velmi zjednodušenou: v parsovaném řetězci je oddělovačem právě jedna mezera, ani na začátku
a ani na konci není tento oddělovač a není v něm žádná interpunkce.

Úkol: napočítejte počet „slov” a (dynamicky) naalokujte stejně velké pole ukazatelů na řetězce.
Velikost znakových polí pro uložení „slov” ‑ řetězců musí být ještě o 1 větší než je velikost ukládaných „slov” ‑ řetězců
pro uložení řetězec ukončujícího '\0'.
Řetezec k vyzkoušení: "Boleslav pije sladkou vodu a Jaroslava se myje vodou slanou a Karel spravuje boty"



V jazyku C mezi funkcemi pracujícími se znakovými řetězce (jejichž hlavičky jsou v hlavičkovém souboru <string.h>) je i funkce strtok
(Asi zkratka ze string tokenize).
Ta má řadu nectností, jak vidno dále:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main()
{
    char r[32], *p, *q[7];
    int i, c;

    strcpy(r, "pec spadla a skakal pes");
    printf("|%s|\n", r);
    printf("\n");
    p = q[0] = strtok(r, " ");
    i = 0;
    p = strtok(NULL, " ");
    while (p != NULL) {
        q[++i] = p;
        p = strtok(NULL, " ");
    }
    c = i;
    for (i = 0; i <= c; ++i) {
        printf("|%s|\n", q[i]);
    }
    printf("\n");
    printf("|%s|\n", r);
    printf("\n");
    strcpy(r, "Putin je vrah");
    printf("|%s|\n", r);
    printf("\n");
    for (i = 0; i <= c; ++i) {
        printf("|%s|\n", q[i]);
    }
    return EXIT_SUCCESS;
}

S výstupem:
|pec spadla a skakal pes|

|pec|
|spadla|
|a|
|skakal|
|pes|

|pec|

|Putin je vrah|

|Putin je vrah|
|n je vrah|
|ah|
||
|pes|

Navíc tato funkce není reentrantní. Další informace třeba tady.
Osobně doporučuji tuto funkci nepoužívat.