NOVINKA: Získej 40 hodin praktických dovedností s AI – ZDARMA ke každému akreditovanému kurzu!
S účinností od 26. 3. jsme aktualizovali Zásady zpracování osobních údajů – doplnili jsme informace o monitorování telefonických hovorů se zájemci o studium. Ostatní části zůstávají beze změn.

Diskuze – Lekce 8 - Textové řetězce v jazyce C

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
Odpovídá na Student C
DarkCoder:31.3.2018 19:15

Však v pořádku, od toho to tu forum je abychom my zkušenější poradili.

Odpovědět
31.3.2018 19:15
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Patrik Pastor:24.8.2019 12:50

chtel bych se zeptat na tento formatovy specifikator %[^\n]s - vim ze by to melo znamenat "string bez mezery", ale ja jsem chapl "\n" - jako new line nebo carriage return, ale jako mezeru. Kdyz jsem se ucil regexp, tak sem se ucil ze \t - tabulator, \n - cr, \s - vsechny bile znaky (tabulator, enter, mezera). ale kdyz jsem dal to specifikatoru "%[^\s]s" - napsal mi compiler ze sekvenci "\s" nezna, jak je to tedy s regularnima vyrazema v cecku?

 
Odpovědět
24.8.2019 12:50
Avatar
Odpovídá na DarkCoder
Patrik Pastor:24.8.2019 13:27

jak je to s regularnimi vyrazy v cecku?

 
Odpovědět
24.8.2019 13:27
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Patrik Pastor
DarkCoder:24.8.2019 15:14

Právě naopak, znamená to string s mezerou. Z popisu článku to není jasně zřejmé a chybí v něm jedna důležitá věc.

Funkce scanf() za použití běžného %s čte znaky dokud nenarazí na oddělovací znak (mezera, tabulátor, nový řádek). To co umožňuje funkci scanf() načítat i mezery je to, že má možnost určit sadu zpracovávaných znaků. Specifikátor povolených znaků se vytvoří tak, že se do hranatých závorek vloží seznam znaků.

Zde je příklad určení povolené sady znaků:

%[abcde]

To způsobí, že čtení bude pokračovat dokud je načtený znak součástí znakové sady.

Pomocí spojovníku (-) lze zadat rozsah sady znaků.

%[A-Z]

To způsobí, že budou načteny pouze znaky které jsou součástí velké abecedy.

Když je sada velká, je někdy dobré zadat to co není součástí povolené sady. Provádí se to za pomocí znaku stříška (^)

%[0123456789]

To způsobí, že budou načítány všechny znaky kromě číslic 0 až 9.

Ve všech těchto případech se písmeno s už za sadou znaků neuvádí.

Nyní by mělo být jasné, proč a jak funguje následující specifikace:

scanf(" %50[^\n]s", jmeno);

Jediný znak který není součástí povolené znakové sady je odřádkování. Proto tento zápis povoluje mezeru.

Kdykoli je ve formátovacím řetězci mezera, bude funkce scanf() hledat a odstraňovat oddělovací znaky, dokud není nalezen první znak, který není oddělovacím znakem.

Tou zásadní věcí která není v článku zmíněna je informace o vstupním bufferu, respektive o tom, že tam mohou některé znaky zůstat a mohou být tak načteny následující vstupní funkcí, což může vést a většinou vede ke špatné funkci programu. To že se omezí počet znaků ve funkci scanf() pomůže akorát od pádu programu, ale už nikoli ke špatné funkci programu. Pokud se zadá text delší než stanovená délka ve scanf(), zůstanou tyto znaky ve vstupním bufferu. Tento buffer je třeba čistit!

Následující příklad vykazuje tuto chybu:

#include <stdio.h>

#define BUFFSIZE 50

int main(void) {
        char buffer[BUFFSIZE];

        printf("Zadej delsi text: ");
        scanf("%10[^/n]", buffer);
        printf("%s\n", buffer);

        printf("Zadej znovu delsi text: ");
        scanf("%10[^/n]", buffer);
        printf("%s\n", buffer);

        return 0;
}

Když zadáš dlouhý text, zobrazí se Ti prvních deset znaků. Další znaky ale zůstávají ve vstupním bufferu. Druhá výzva na zadání vstupu je tak přeskočena a je vypsáno až dalších deset znaků z původně zadaného textu.

Funkce gets(), která je v článku zmíněna se skutečně dříve používala. Dnes je zastaralá a je vyřazena. Místo toho se používá pro čtení řetězců funkce fgets() se stdin streamem. Stále je však nutné vyprazdňovat vstupní buffer.

Nakonec dalším řešením je napsat si svou funkci pro čtení řetězců sám.

Odpovědět
24.8.2019 15:14
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na DarkCoder
Patrik Pastor:24.8.2019 16:18

no ale jak je to s regexp? funguji vsechny ve formatovem specifikatoru? jako [class], *,+,$,^ (zacatek konec radku), \w \s \i. Napsal jsi "\n" nepovoluje odradkovani, ale odradkovani je prece "\t" ne? ktere tedy specialni znaky mohou byt v c pouzity?

 
Odpovědět
24.8.2019 16:18
Avatar
Odpovídá na DarkCoder
Patrik Pastor:24.8.2019 17:25

jeste jsem taky zjistil, ze mi staci mit neco jako toto: (nize) bez headeru bez niceho, a kompiler mi to vschno vezme (sice mi da par warningu, ale jinak se nic nestane). compiluju s gcc, tak asi uz je to vymakane

1 int main(){
2 printf("%d\n",st­rcmp("8", "blyskavice"));
1 }
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
1.c 2/3

a stejne mi to compiler vezme - vyhodi -1

 
Odpovědět
24.8.2019 17:25
Avatar
Odpovídá na DarkCoder
Patrik Pastor:24.8.2019 20:48

a jeste neco, mas pravdu ze [^\n] ve specifiaktoru vyloucim mezeru ze sady znaku ve skenovani, ale ja mel nasledujici specifikator " %[^\n1-9][a-z]" ... tedy chtel jsem aby mi scanf vzal ze stdin pouze alpha slova. Kdyz jsem ale zadal ve stdin "abc 123 adf", napsal mi pouze "abc", ale uz nevypsal "adf" - a to jsem mel mezeru pred " %" procenty... ? jak tedy scanf vnitrne pracuje?

A taky mi prosim odpovez na ty regularni vyraze, fakt nechapu jak to ze [^\n] je mezera, kdyz by to melo byt novy radek jako newline "\n" - coz je v tech hranatych zavorkach. Ja jsem si myslel (a treba ve vim programu to tak i funguje) ze mezera je "\s", \t tabulator \n - novy radek, \r - novyradek + enter. JAK JE TO V CECKU S REGULARNIMA VYRAZEMA, na netu jsem to nikde nenasel

 
Odpovědět
24.8.2019 20:48
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Patrik Pastor
DarkCoder:24.8.2019 21:36

Přesně naopak, tím že máš v sadě uveden znak ^, tak tím říkáš, že znaky uvnitř povolené sady nejsou akceptovány a pokud na nějaký z nich se při čtení narazí, načítání se ukončí. Pokud chceš pouze alfa znaky tak použij %[a-zA-Z]. Nebo načti normálně celý řetězec a pomocí funkce isalpha() ze ctype.h otestuj validitu řetězce. Jistě, nemohl vypsat zbylá tři písmena protože narazil na číslice které nemáš povolené a čtení se ukončilo. Jak funkce scanf() pracuje najdeš v knihovně stdio.h a v její dokumentaci. Pokud nemáš zdrojové kódy, můžeš si vše pouze domýšlet. A věz, že pochopení toho co vše načtení obnáší, si vyžaduje dosti dobrou znalost programování.

Regulární výrazy nejsou podporovány v čistém ANSI C. Je to záležitostí knihoven, které lze použít. Regulárními výrazy bych se být tebou nezabýval, věnuj ten čas jiným věcem, které při programování použiješ. To budeš potřebovat neporovnatelně častěji než regulární výrazy.

To co je \n \b \a \t \\ \r a další, to jsou escape sekvence. Tohle jsou ty věci, které by si měl znát.
Chceš-li znát pokročilé techniky, musíš znát všechny předchozí. Nelze začít nejvyšší úrovní.

Odpovědět
24.8.2019 21:36
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Honza Černoch:25.11.2019 19:28

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

int main()
{
char text;
int pismena;
printf("Napis slovo a ja spocitam pocet pismen: \n");
scanf("%s", &text);
pismena = strlen(text);
printf("%d", pismena);

return 0;
}
poradite nekdo?

 
Odpovědět
25.11.2019 19:28
Avatar
Honza Černoch:25.11.2019 19:29

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

int main()
{
char text;
printf("Napis slovo a ja spocitam pocet pismen: \n");
scanf("%s", &text);
printf("%d", strlen(text));

return 0;
}

 
Odpovědět
25.11.2019 19:29
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 10 zpráv z 48.