Java týden První novoroční výprodej
Hledáš brigádu v IT, která bude 100 % home office a 100 % flexibilní? Pak napiš na: redakce [zavináč] itnetwork.cz pro více info!
80 % bodů zdarma díky akci Black Friday! Tento týden rovněž sleva na e-learning Java až 80 %

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

Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem.
Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, Pole v jazyce C, jsme si představili pole. Až doposud jsme se v našem kurzu programovacího jazyka C úspěšně vyhýbali textovým řetězcům a pracovali jsme pouze s čísly a znaky. V naprosté většině reálných aplikací ovšem figurují víceznakové texty. Těm se v programování říká textové řetězce (jelikož se jedná o řetěz znaků) nebo někdy jen řetězce. Důvodem odložení tohoto tématu je, že jazyk C jako nízký jazyk žádný datový typ pro řetězce nemá a vlastně s nimi téměř nepočítá. S textem však v céčku můžeme běžně pracovat, jen je to komplikovanější.

Pole znaků

S řetězci lze v céčku pracovat několika způsoby. My si v tomto dílu uvedeme zatím ten nejjednodušší, tzv. statický řetězec, kterým je pole charů. Když budeme chtít uložit do proměnné textový řetězec "itnetwork", potřebujeme v paměti vytvořit následující pole typu char (znak):

'i' 't' 'n' 'e' 't' 'w' 'o' 'r' 'k' '\0'

V každé přihrádce pole je uložený jeden znak. Všimněte si ovšem, že poslední přihrádka je navíc a obsahuje znak \0, což je tzv. nulový znak. Tím musí končit všechny textové řetězce. Ačkoli totiž céčko jako jazyk textové řetězce nepodporuje, obsahuje standardní knihovny, které s nimi pracují. A proto musíme řetězce ukládat tak, jak se předpokládá, že budou vypadat. Pole s řetězcem tedy musí být vždy o 1 delší, než je délka textu, který do něj vkládáme!.

Pozn.: Ačkoli je to nad rámec této lekce, uveďme si, že nulový znak je na konci řetězce z toho důvodu, abychom poznali, kde řetězec končí. Kromě statických polí můžeme totiž řetězce ukládat pomocí ukazatelů jako libovolně dlouhé úseky v paměti, kde se bez této berličky neobejdeme. Tento způsob si ukážeme dále v seriálu. Druhým způsobem, jak označit konec řetězce, je uložit jeho délku před první znak. Tento systém se používal např. v jazyce Pascal, mnohem častěji se však používá ukončení nulovým znakem.

Vytvořme si jednoduchý příklad. Do proměnné si uložme nějaký text a ten následně vypišme do konzole:

char text[5] = {'d', 'u', 'h', 'a', '\0'};
printf("%s", text);

Výsledek:

Konzolová aplikace
duha

Dobrá zpráva je, že jazyk C nám umožňuje zadávat text v uvozovkách, který následně nahradí tzv. řetězcovou konstantou (polem charů, zakončeným znakem \0). Kód výše můžeme přepsat na tuto podobu:

char text[5] = "duha";
printf("%s", text);

Všimněte si, že pole musí mít stále délku 5, i když má duha 4 písmena. Když bude ještě delší, nebude to vadit. Dokonce na céčku můžeme nechat zjištění délky textu:

char text[] = "duha";
printf("%s", text);

Co již bohužel nefunguje je přiřazení řetězcové konstanty do již existujícího pole:

char text[5];
text = "duha"; // Tento řádek způsobí chybu
printf("%s", text);
Naši partneři možná hledají právě tebe!

Je to kvůli tomu, že nelze přiřadit pole do pole. Nic nám ovšem nebrání přiřadit jednotlivé znaky pomocí cyklu nebo použít funkce pro kopírování řetězců, viz. dále.

Práce s jednotlivými znaky

S řetězcem můžeme zacházet úplně stejně jako s polem, protože polem je :) Není tedy problém vypsat např. 1. znak nebo jej změnit, případně řetězec zkrátit:

char text[] = "duha";
text[0] = 'h';
text[3] = '\0';
printf("%s", text);

Výsledek:

Konzolová aplikace
huh

Změnou čtvrtého znaku na \0 jsme docílili ukončení řetězce před tímto znakem. Na nulový znak si dejte při editaci znaků řetězce pozor, když na něj zapomenete, program nebude vědět kde řetězec končí a dostanete se do paměti, která vám nepatří.

Čtení/výpis řetězce

Řetězce můžeme jednoduše načítat/vypisovat jako jsme byli zvyklí doposud, použijeme k tomu formátovací sekvenci %s. Proměnnou pro řetězec založíme jako pole charů a určíme si nějakou maximální velikost, např. 50 znaků (což je velikost 51). U parametrů typu %s vypouštíme před proměnnou znak &, jelikož s polem předáváme rovnou jeho adresu.

Následující program si nechá zadat vaše jméno a následně vás pozdraví:

printf("Zadej své jméno: ");
char jmeno[51];
scanf("%50s", jmeno);
printf("Ahoj uživateli %s, vítám tě!", jmeno);

Všimněte si, že ve formátovacím řetězci funkce scanf() je uvedena i maximální délka načítaného řetězce. Když bychom ji nezadali a natrefili na exotického uživatele nebo jen na záškodníka, došlo by k přetečení pole a rozbití programu.

Funkce scanf() text bohužel přeruší se zadáním mezery. Abychom mohli načíst např. Jan Novák" do jedné proměnné, upravíme formátovací řetězec ještě tak, aby načítal vše kromě konce řádku. Upravte si řádku s načítáním do této podoby (mezera na začátku je opravdu důležitá, protože v bufferu nenechá bílé znaky):

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

Někdy můžete při načítání textu z konzole narazit na použití funkcí gets() nebo fgets(). Funkci gets() se vyhněte, jelikož neumožňuje omezit délku načítaného řetězce a fgets() se musí přesměrovat na standardní vstup. Se scanf() si bohatě vystačíme.

Standardní funkce pro práci s řetězci

Specifikace jazyka C nám poskytuje mnoho připravených funkcí pro práci s řetězci, které zjednoduší naše programy. Pro práci s nimi musíme na začátek souboru přidat vložení hlavičkového souboru string.h:

#include <string.h>

Pozn.: Protože jsou funkce pojmenovány pomocí zkratek, uvádím vždy i z čeho název vychází pro lepší zapamatování.

strlen() - STRing LENgth

Délku řetězce můžeme zjistit pomocí strlen(). Jedná se o délku viditelné části bez znaku \0.

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

int main(void)
{
    printf("%d", strlen("duha")); // vrátí 4
    return (EXIT_SUCCESS);
}

strcat() - STRing conCATenate

2 textové řetězce můžeme spojit do jednoho pomocí funkce strcat(). Dejte pozor, aby byl v prvním řetězci dostatek místa.

char text[20] = "duha";
strcat(text, " je na nebi"); // uloží do text "duha je na nebi"
printf("%s", text);

strcpy() - STRing CoPY

Jelikož pole nelze jednoduše celá kopírovat, je nám poskytnuta tato funkce, která naklonuje textový řetězec do jiné proměnné.

char text[5];
strcpy(text, "duha");
printf("%s", text);

strchr() - STRing CHaR

V textu si můžeme nechat vyhledat nějaký znak. Céčko ho od začátku do konce prohledá a pokud znak nalezne, vrátí na něj tzv. ukazatel. I když ty ještě neumíme, bude nám stačit, že když od této hodnoty odečteme řetězec, získáme pozici, na které se znak nachází. Pokud text znak neobsahuje, získáme hodnotu NULL.

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

int main(int argc, char** argv) {
    char text[] = "Pan X znovu udeřil.";
    char *p = strchr(text, 'X'); // Zjistíme pozici znaku 'X' v textu
    int pozice = p - text;
    if (p != NULL)
    {
        printf("Nalezeno na pozici %d", pozice);
    }
    else
    {
        printf("Nenalezeno");
    }
    return (EXIT_SUCCESS);
}

Asi vás nepřekvapí, že se pozice indexuje od nuly.

strstr() - STRing subSTRing

Úplně stejně, jako můžeme vyhledat jeden znak, můžeme vyhledat i řetězec v řetězci. O tom dále hovoříme jako o tzv. podřetězci. Funkce se používá analogicky s funkcí strchr().

strcmp() - STRing CoMPare

Porovná 2 řetězce podle abecedy a vrátí záporné číslo pokud je první před druhým, 0 pokud jsou stejné a kladné číslo pokud je první za druhým.

printf("%d", strcmp("akát", "blýskavice")); // vrátí záporné číslo

Funkce pro práci s řetězci můžeme nalézt také v dalších variantách. Pokud chceme, aby céčko pracovalo s řetězcem odzadu (např. vyhledávalo od konce), vyskytuje se v názvu funkce písmeno r (jako reverse). Takovou funkcí je např. strrchr(). Další varianty funkcí mají v názvu navíc písmeno n (jako number) a přijímají navíc další parametr. Ten udává limit znaků, které funkce v řetězci zpracovávají. Pokud je řetězec delší, vrátí jen jeho část, useknutou na maximální počet znaků. Pozor, tato část neobsahuje znak \0. Příkladem takové funkce budiž strncat().

V příští lekci, Textové řetězce v jazyce C podruhé - Práce se znaky, budeme s textovými řetězci v jazyce C pokračovat, ukážeme si jak pracovat s jednotlivými znaky.


 

Stáhnout

Staženo 415x (31.89 kB)

 

 

Článek pro vás napsal David Čápka
Avatar
Jak se ti líbí článek?
8 hlasů
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor sítě se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.
Předchozí článek
Pole v jazyce C
Všechny články v sekci
Základní konstrukce jazyka C
Miniatura
Následující článek
Textové řetězce v jazyce C podruhé - Práce se znaky
Aktivity (18)

 

 

Komentáře

Avatar
tomisoka
Redaktor
Avatar
tomisoka:17.10.2014 19:55
char[] text = "duha";
strcat(text, " je na nebi"); // uloží do text "duha je na nebi"

Nezpůsobí to "náhodou" error? (Kvůli nedostatečné velikosti "text")

Editováno 17.10.2014 19:56
 
Odpovědět
17.10.2014 19:55
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na tomisoka
David Čápka:17.10.2014 20:02

Máš pravdu, díky, opravil jsem.

Odpovědět
17.10.2014 20:02
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
ra3sk
Člen
Avatar
ra3sk:18.10.2015 0:12

Ahoj, trocha ma to metie. V škole sa učíme že %c je pre char prečo je tam %s ?
A ešte, že pri

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

by to malo byť

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

Neviem teda. Prosím o radu alebo o link kde je to vysvetlené. Predom ďakujem.

 
Odpovědět
18.10.2015 0:12
Avatar
Milan Křepelka
Redaktor
Avatar
Milan Křepelka:18.10.2015 0:23

%c je právě jeden znak. %s je pole znaků, tedy string - text
http://www.codingunit.com/…atted-output

 
Odpovědět
18.10.2015 0:23
Avatar
Taskkill
Redaktor
Avatar
Odpovídá na ra3sk
Taskkill:18.10.2015 2:16

Jak pise Milan .. char je od slova character, tedy znak... C nepracuje standardne se Stringem... nema ho tam... takze retezce uklada jako pole characteru... nicmene na vystup uz to musis specifikovat, to je jasne proc... vypisovac potrebuje vedet co do nej posilas...sam si na to neprijde, kdyz jde o data, ktera muzou bejt interpretovana ruzne viz char jako cislo char jako znak..

a ta druha otazka... scanf bere minimalne dva parametry... typ a ukazatel... ono totiz v cecku neni standardne mozny na ty nizsi vrstve nacist hodnotu a hodit ti ji jako return do vysi vrstvy ..neptej se me proc... nicmene se to resi trikem... druhy parametr neni promenna jmeno ale jen odkaz, ukazatel na ni..ten se znaci ampersandem tedy znakem & pred nazvem promenne...

snad vsechno jasne... za absenci diakritiky se omlouvam - en klavesnice ;)

 
Odpovědět
18.10.2015 2:16
Avatar
ra3sk
Člen
Avatar
Odpovídá na Taskkill
ra3sk:18.10.2015 9:18

Viac menej áno. Keďže je stredoškolské vysvetlenie docela chabé tak to takto dohladávam po nete. Ďakujem za vysvetlenie. Je vysokopravdepo­dobné, že sa budem v tomto seriály ešte dosť pýtať. :-)

 
Odpovědět
18.10.2015 9:18
Avatar
ra3sk
Člen
Avatar
Odpovídá na David Čápka
ra3sk:7.11.2015 20:25

Teraz som si to skúšal STRCOPY v Xcode a píše mi, že to nie je platné v C99. Je tu nejaká náhrada alebo?

 
Odpovědět
7.11.2015 20:25
Avatar
David Novák
Redaktor
Avatar
Odpovídá na ra3sk
David Novák:7.11.2015 21:54

STRCOPY? Pokud vím, tak v C nic takového není - pouze strcpy() v knihovně string.h

Odpovědět
7.11.2015 21:54
Chyba je mezi klávesnicí a židlí.
Avatar
ra3sk
Člen
Avatar
 
Odpovědět
7.11.2015 22:33
Avatar
Odpovídá na ra3sk
Libor Šimo (libcosenior):8.11.2015 0:51

Zda sa mi, ze som ti uz raz poslal link na lekciu o retazcoch od Herouta, alebo nie?

Odpovědět
8.11.2015 0:51
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Odpovídá na Libor Šimo (libcosenior)
Lukáš Horňák:27.1.2016 13:11

nazdar chlapi programátoři jak jde programování já jsem úplně blbý neumím zjistit ani délku řetězce tak mně prosím poradte, vy ste asi dobří když tu píšete takové moudra tak na vás spoléhám s pozdravem phpmaestro

 
Odpovědět
27.1.2016 13:11
Avatar
Odpovídá na Lukáš Horňák
Libor Šimo (libcosenior):27.1.2016 14:06
#include <stdio.h>
#include <string.h> // použitie strlen()

int main(void)
{
    int dlzka = 0;
    char *retazec = "Nazdar chlapi programatori jak jde programovani?";

    printf("Dlzka retazca je %d.\n", strlen(retazec)); // pouzitie strlen()

    while(*retazec++ != '\0') { // dalsi jeden z moznych sposobov
        dlzka++;
    }
    printf("Dlzka retazca je %d.\n", dlzka);

    return 0;
}
Odpovědět
27.1.2016 14:06
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Odpovídá na Lukáš Horňák
Libor Šimo (libcosenior):27.1.2016 14:08

Dôležité je uvedomiť si, že reťazec je jednorozmerné pole znakov, ukončené znakom '\0'.
Veľkosť poľa by si už mohol vedieľ zistiť aj sám.

Odpovědět
27.1.2016 14:08
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Odpovídá na Libor Šimo (libcosenior)
Rastislav Mikláš:8.1.2017 21:48

Ahoj, má ta hviezdička v názve *reťazec nejaký význam? Vďaka za odpoveď :)

 
Odpovědět
8.1.2017 21:48
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Rastislav Mikláš
DarkCoder:9.1.2017 0:32

Samozřejmě. Pokud by tam nebyla, pak by proměnná retazec byla deklarována jako proměnná schopna pojmout jeden znak a současná inicializace této proměnné by byla chybná. To co Libor vytvořil je řetězcová konstanta, která je uložena v tabulce řetězců programu, na kterou překladač vytváří ukazatel. Tedy proměnná retazec je zde inicializována adresou řetězce.

Odpovědět
9.1.2017 0:32
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Rastislav Mikláš
DarkCoder:9.1.2017 0:42
while(*retazec++ != '\0') { // dalsi jeden z moznych sposobov
        dlzka++;
    }

Zde má * význam jako operátor dereference ukazatelové proměnné, bere se hodnota proměnné.

Odpovědět
9.1.2017 0:42
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Avatar
David Švec
Člen
Avatar
David Švec:18.7.2017 14:49

Zdravím všechny,
mám 2. dotazy :)
char *p = strchr(text, 'X');

1. proč je u toho char p ta hvězdička?
nikde jsem to nenašel, a vysvětlení, které někdo napsal do komentářů jsem nepochopil.. mohl by mi to někdo vysvětlit nějak po lopatě? :D

2. scanf("%50s", jmeno);
proč je tam 50, když velikost pole je 51? :)

Děkuji za odpověď.

Editováno 18.7.2017 14:52
 
Odpovědět
18.7.2017 14:49
Avatar
Odpovídá na David Švec
Libor Šimo (libcosenior):18.7.2017 15:13
  • ukazuje, ze ide o pointer.

50 preto, ze retazec je ukonceny znakom '\0' a to je ten 51.

Odpovědět
18.7.2017 15:13
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
David Švec
Člen
Avatar
Odpovídá na Libor Šimo (libcosenior)
David Švec:18.7.2017 15:15

Co to znamená pointer? To je někde až v dalších lekcích? Já jsem totiž začátečník :)

 
Odpovědět
18.7.2017 15:15
Avatar
Libor Šimo (libcosenior):18.7.2017 15:17

Pointer je adresa v pamati kde zacina dany retazec. Mallo by to byt v dalsich lekciach.

Odpovědět
18.7.2017 15:17
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
David Švec
Člen
Avatar
Odpovídá na Libor Šimo (libcosenior)
David Švec:18.7.2017 15:19

aha díky, zkusím to nějak nastudovat :)

 
Odpovědět
18.7.2017 15:19
Avatar
David Švec
Člen
Avatar
David Švec:18.7.2017 16:22

scanf(" %50[^\n]s", jmeno);
mohl by mi někdo vysvětlit tento řádek kódu?
myslím proč je před % mezera a proč tam je [^\n] ? děkuji

 
Odpovědět
18.7.2017 16:22
Naši partneři možná hledají právě tebe!
Avatar
Odpovídá na David Švec
Libor Šimo (libcosenior):18.7.2017 16:31

Medzera je na to, aby sa tzv. zahodil predchadzajuci ENTER.
\n ze zadavanie je ukoncene klavesou ENTER.

Odpovědět
18.7.2017 16:31
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
David Švec
Člen
Avatar
 
Odpovědět
18.7.2017 16:48
Avatar
Student C
Člen
Avatar
Student C:31.3.2018 10:27

/************­************************­************************­*****************

  • jarvis program (komunikator) verze 0.0.1 *
  • program za učelem zakladny komunikace s počitacem skrz jeden program *

*============­========================­========================­=================

  • vytvořil: Timoteus kupec datum: 30.3.2018 *

*************­************************­************************­****************/
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <string.h>
#include "jarvis.h"

int main(){

///struktury zakladních vìci pro progrm

struct udaje{
int it_is_you;
char jmeno[50];
char primeni[50];
char rok[156];
char weight[156];
char height[156];
}zakladni;

struct udaje2{
char jmeno2[50];
char primeni2[50];
char rok2[156];
char weight2[156];
char height2[156];
}zakladni2;

struct question{
char otazka001[500];
char odpoved001[500];
char for_read001[500][5­00];
char for_read002[500][5­00];
char for_write[500][500];
char systemova_pro­mena[500];
char nacteni_z_obr_co­mand[500];
}question1;

struct opakovani{
int opacko_programu;
int cikus_pro_naci­tani_ze_soubo­ru1;
}opakovani1;

opakovani1.opac­ko_programu=1;
///deklarace souborù

FILE txt1,txt_name_co­mand,*txt_coman­d;

jarvis_nadpis();

printf("it is you?if is you write 1!\n");
scanf("%i", &zakladni.it_is_y­ou);

if(zakladni.it_is_y­ou!=1){

txt1=fopen("jar­vis udaje tech.txt","w");

if(txt1==NULL){
printf("File don't opening.\n");
exit(1);
}

///nacitani udaju
printf("\nWrite your name.\n");
scanf("\n%[^\n]s", zakladni.jmeno);
getchar();
fprintf(txt1,"%s;­", zakladni.jmeno);
printf("Write your surname.\n");
scanf("%[^\n]s", zakladni.primeni);
getchar();
fprintf(txt1,"%s;­", zakladni.primeni);
printf("Write your age\n");
scanf("%s", zakladni.rok);
getchar();
fprintf(txt1,"%s;­", zakladni.rok);
printf("Write your weight in kg.\n");
scanf("%s", zakladni.weight);
getchar();
fprintf(txt1,"%s;­", zakladni.weight);
printf("Write your height in cm.\n");
scanf("%s", zakladni.height);
getchar();
fprintf(txt1,"%s;­", zakladni.height);

fclose(txt1);
}

txt1=fopen("jar­vis udaje tech.txt","r");

if(txt1==NULL){
printf("File don't opening.\n");
exit(1);
}

///tisknuti udaju z txt
fscanf(txt1,"%[^;­]s", zakladni2.jme­no2);
fscanf(txt1,";%[^­;]s", zakladni2.pri­meni2);
fscanf(txt1,";%[^­;]s", zakladni2.rok2);
fscanf(txt1,";%[^­;]s", zakladni2.weig­ht2);
fscanf(txt1,";%[^­;]s", zakladni2.heig­ht2);

system("cls");
jarvis_nadpis();
printf("\n\tHello %s, what can you do?\n",zaklad­ni2.jmeno2);

fclose(txt1);

do{do{

scanf("%[^\n]s", question1.otaz­ka001);
getchar();

txt_name_coman­d=fopen("name of comand.txt","r");
if(txt_name_co­mand==NULL){
printf("File don't opening(name of comand).\n");
exit(1);
}

for(opakovani.cikus_pro_na­citani_ze_sou­boru1=0; opakovani1.ci­kus_pro_nacita­ni_ze_souboru1<=500; opakovani1.ci­kus_pro_nacita­ni_ze_souboru1++){
fscanf(txt_na­me_comand,";%[^;]s", question1.for_re­ad001[opakova­ni1.cikus_pro_na­citani_ze_sou­boru1]);
}
fclose(txt_na­me_comand);

txt_comand=fo­pen("comand with name.txt","r");
if(txt_comand==NUL­L){
printf("File don't opening(comand with name).\n");
exit(1);
}
for(opakovani.cikus_pro_na­citani_ze_sou­boru1=0; opakovani1.ci­kus_pro_nacita­ni_ze_souboru1<=500; opakovani1.ci­kus_pro_nacita­ni_ze_souboru1++){
fscanf(txt_co­mand,";%[^;]s", question1.for_re­ad002[opakova­ni1.cikus_pro_na­citani_ze_sou­boru1]);
}
fclose(txt_comand);

for(question.for_read001; question1.for_re­ad001[opakova­ni1.cikus_pro_na­citani_ze_sou­boru1]!=questi­on1.otazka001; opakovani1.ci­kus_pro_nacita­ni_ze_souboru1++){
strcpy(questi­on1.systemova_pro­mena,question.for_read002[o­pakovani1.cikus_pro_na­citani_ze_sou­boru1]);
}

system("cls");
jarvis_nadpis();

if(strcmp(ques­tion1.otazka001,"stu­dents book")==0){
jarvis_znamky_va­zene();
}

if(strcmp(ques­tion1.otazka001,"e­xit")==0){
jarvis_vypnuti_pro­gramu();
}

}while(strcmp(qu­estion1.syste­mova_promena,";")<0&&s­trcmp(question.systemova_pro­mena,";")>0&&s­trcmp(question.otazka001,"stu­dents book")==0);

printf("I don't know what it means.\nPlease writ what you can.");
scanf("%[^\n]s", question1.nac­teni_z_obr_co­mand);
getchar();

txt_comand=fo­pen("name of comand.txt","a");
fprintf(txt_co­mand,"%s;", question1.nac­teni_z_obr_co­mand);
fclose(txt_comand);

}while(opakova­ni1.opacko_pro­gramu==1);

getchar();
return 0;
}
pomůžete mi dělal jsem to podle toho co znám a naučil jsem se tady ale sekne se to během chvilky
co s tím mam dělat pls pomoc už nad tím přemýšlím měsíc a vymyslel jsem todle ale nefunguje to a seká se to .!!!
program má vedlejší hlavičkový soubor který obsahuje (kalkulačku apod....)
program má dělat tzv siri píšu a on pote bude brát do systému a zapínat či otevírat
a pod.... tak poradíte??????????­????????????????????????­????????

Odpovědět
31.3.2018 10:27
Cree que puedes manejarlo
Avatar
Student C
Člen
Avatar
Student C:31.3.2018 10:35

pro srozumitelnost přikládám knihovnu a pzn....(prace je delana v code::block)

/************­************************­***************

  • knihovna pro program jarvis verze 0.0.1 *

=============­========================­=============

  • vytvoøil: Timoteus Kupec datum: 30.3.2018 *

*************­************************­**************/

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

///funkce nadpisu

void jarvis_nadpis(){
printf("\t\t\t\t * \n");
printf("\t\t\t\t * * **** * * **** \n");
printf("\t\t\t\t * * * * * * * * * \n");
printf("\t\t\t\t * * * **** * * * *** \n");
printf("\t\t\t\t* * ******* * * * * * *\n");
printf("\t\t\t\t ** * * * * * * **** \n");
printf("********­************************­************************­************************­************************­****************\n");

}

///funkce vženeho prumeru znamek se zaokrouhlenim na konci.

void jarvis_znamky_va­zene(){
int y,n,m;
float x,z[100],a[10­0],delenec,de­litel;
printf("Write, how many marks you're going to type:\n");
scanf("%f", &x);
getchar();
for(y=1; y<=x; y++){
printf("\nWrite your mark:");
scanf("%f", &z[y]);
if(z[y]>=6){
printf("This mark does not exist.\nEnding please wait 10 seconds because you are idiot.");
Sleep(1000*10);
exit(1);
}
getchar();
printf("Write value of the mark:");
scanf("%f",&a[y]);
if(z[y]>=11){
printf("This value does not exist.\nEnding please wait 10 seconds because you are idiot.");
Sleep(1000*10);
exit(1);
}
getchar();
}
for(n=1; n<=x; n++){
delitel=delitel+a[n];
}
for(m=1; m<=x; m++){
delenec=delenec+a[m]*z[m­];
}
printf("\n\n\tThe mark you're searching for is %.2f, so it will be %.0f\n\n", delenec/delitel, delenec/delitel);
getchar();
}

///funkce vypnuti programu

void jarvis_vypnuti_pro­gramu(){
printf("Ending, pleas wait 10 seconds.");
Sleep(1000*10);///u funkce sleep se do argumenu pisi sekundy/1000
exit(1);
}

///zde puijdou dalši funkce:):):)

Odpovědět
31.3.2018 10:35
Cree que puedes manejarlo
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Student C
DarkCoder:31.3.2018 13:20

Asi Tě má slova nepotěší, ale po shlédnutí kódu bych to celé smazal a začal znovu. Je tam špatně snad úplně vše.

Pokud chceš aby Ti kdokoli pomohl, založ nové vlákno v dané kategorii a dodržuj pravidla pro vložení příspěvku.
PRAVIDLA VLOZENI PRISPEVKU

Dvě rady na závěr, jak se dobereš vytouženého cíle:

  1. Postupuj systematicky a nepokračuj v něčem novém, dokud daný problém nevyřešíš.
  2. Zapracuj na písemném projevu, i sebelepší aplikaci zazdíš tím jak ji prezentuješ
Odpovědět
31.3.2018 13:20
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Avatar
Student C
Člen
Avatar
Odpovědět
31.3.2018 17:43
Cree que puedes manejarlo
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Student C
DarkCoder:31.3.2018 18:37

Abych byl více konkrétní a věděl si co je v programu chybně:

Např.:

  • používání void, pokud funkce nemá parametry
  • struktury deklaruj vně funkce
  • proměnné typu struktura definuj uvnitř funkce
  • používej typy které lépe korespondují s daným prvekm struktury
  • deklarace proměnných se v C provádí na začátku bloku
  • pro práci se soubory deklaruj ukazatel na FILE
  • pracuj s funkcemi, zpřehlední Ti to program
  • pro řetězce používej fgets()
  • nehledej ve scanf() složitosti
  • používej kratší identifikátory pro proměnné
  • v operacích se soubory vždy testuj na úspěšnost

Nic však z toho co jsem uvedl není složité.

Editováno 31.3.2018 18:37
Odpovědět
31.3.2018 18:37
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Avatar
Student C
Člen
Avatar
Odpovídá na DarkCoder
Student C:31.3.2018 18:45

dík
já jsem začátečník já se algoritmy teprv učím.

Odpovědět
31.3.2018 18:45
Cree que puedes manejarlo
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
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
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
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
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
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
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
Avatar
Honza Černoch:25.11.2019 19:30

kde jsem udelal chybu?

 
Odpovědět
25.11.2019 19:30
Avatar
Odpovídá na Honza Černoch
Honza Černoch:25.11.2019 20:26

chybu jsem uz nasel:

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

int main()
{
char text[100];
int pismena;
printf("Napis slovo a ja spocitam pocet pismen: \n");
scanf("%99s", text);
pismena = strlen(text);
printf("Slovo ma %d pismen.", pismena);

return 0;
}

 
Odpovědět
25.11.2019 20:26
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Honza Černoch
DarkCoder:25.11.2019 20:37

Slovo je skupina hlásek tvořící ustálený celek a mající určitý ustálený význam. Z programátorského hlediska se jedná o jednorozměrné pole znaků, někdy též nazývaný řetězec. Pro uložení slova je třeba deklarovat proměnnou jako pole znaků.

Např.

char text[50];

Tímto deklaruješ pole do kterého se vejde 50 znaků (v případě řetězce 49 plus '\0'). Pro čtení řetězců se používá funkce fgets(). Na výsledku bys pak prováděl některé úpravy. Když chceš použít funkci scanf(), je třeba si uvědomit, že načítání Ti ukončí bílý znak a nikoli tečka, čárka, vykřičník, otazník, apod. Pokud Ti stačí mezera, můžeš funkci scanf() použít. Při načítání řetězce se u funkce scanf() nepoužívá ampersand. Předává se adresa pole a tedy argumentem je jméno pole.

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

#define SIZE 50

int main(void) {
        char text[SIZE];

        scanf("%s", text);
        printf("%d\n", strlen(text));

        return 0;
}
Odpovědět
25.11.2019 20:37
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
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 43 zpráv z 43.