C riadok funkcie spracovania reťazcov. Operácie so strunami. Základné funkcie štandardnej knižnice string.h

  • 19.04.2019

Habra, ahoj!

Nie je to tak dávno, čo som mal dosť zaujímavú príhodu, do ktorej bol zapletený jeden z učiteľov vysokej školy informatiky.

Rozhovor o linuxovom programovaní sa pomaly posunul do bodu, keď tento muž tvrdil, že zložitosť programovanie systému je v skutočnosti značne prehnané. Že jazyk C je v skutočnosti jednoduchý ako zápalka Linuxové jadro(z jeho slov).

Mal som so sebou notebook s Linuxom s pánskou sadou vývojových nástrojov C (gcc, vim, make, valgrind, gdb). Už si nepamätám, aký cieľ sme si vtedy dali, ale po pár minútach sa môj súper ocitol za týmto notebookom, úplne pripravený problém vyriešiť.

A doslova hneď na prvých riadkoch urobil vážnu chybu pri prideľovaní pamäte pre ... riadok.

Char * str = (char *) malloc (sizeof (char) * strlen (buffer));
buffer je zásobníková premenná, do ktorej sa zapisovali dáta z klávesnice.

Myslím si, že sa určite nájdu ľudia, ktorí sa budú pýtať: "Môže tu byť niečo zle?"
Verte mi, dá sa.

A čo presne - prečítajte si na strihu.

Trochu teórie – akýsi FaceBez.

Ak viete, prejdite na ďalšiu hlavičku.

Reťazec v C je pole znakov, ktoré by mali priateľsky vždy končiť "\ 0" - znak konca riadku. Reťazce v zásobníku (statické) sú deklarované takto:

Char str [n] = (0);
n je veľkosť poľa znakov, rovnaká ako dĺžka reťazca.

Priradenie (0) - "nulovanie" reťazca (voliteľné, môžete ho deklarovať aj bez neho). Výsledok je rovnaký ako pri funkciách memset (str, 0, sizeof (str)) a bzero (str, sizeof (str)). Používa sa na zabránenie vzniku odpadu v neinicializovaných premenných.

Aj v zásobníku môžete okamžite inicializovať riadok:

Char buf = "predvolený text vyrovnávacej pamäte \ n";
Okrem toho môže byť reťazec deklarovaný ako ukazovateľ a môže mu byť pridelená pamäť na halde:

Char * str = malloc (veľkosť);
size - počet bajtov, ktoré reťazcu pridelíme. Takéto čiary sa nazývajú dynamické (kvôli tomu, že správna veľkosť vypočítaná dynamicky + veľkosť pridelenej pamäte je možné kedykoľvek zvýšiť pomocou funkcie realloc ()).

V prípade premennej zásobníka som na určenie veľkosti poľa použil zápis n, v prípade premennej na halde som použil veľkosť zápisu. A to dokonale odráža skutočnú podstatu rozdielu medzi deklaráciou na zásobníku a deklaráciou s alokáciou pamäte na halde, pretože n sa zvyčajne používa, keď hovoríme o počte prvkov. A veľkosť je úplne iný príbeh...

Valgrind nám pomôže

Vo svojom predchádzajúcom článku som to tiež spomenul. Valgrind (, dva - malý návod) - veľmi užitočný program ktorý pomáha programátorovi vystopovať úniky pamäte a kontextové chyby – to sú veci, ktoré sa najčastejšie objavujú pri práci s reťazcami.

Pozrime sa na malý zoznam, ktorý implementuje niečo podobné ako program, ktorý som spomenul, a spustite ho cez valgrind:

#include #include #include #define HELLO_STRING "Ahoj Habr! \ n" void main () (char * str = malloc (sizeof (char) * strlen (HELLO_STRING)); strcpy (str, HELLO_STRING); printf ("-> \ t% s" , str); zadarmo (str);)
A vlastne aj výsledok programu:

$ gcc main.c $ ./a.out -> Ahoj Habr!
Zatiaľ nič neobvyklé. Teraz poďme spustiť tento program s valgrindom!

$ valgrind --tool = memcheck ./a.out == 3892 == Memcheck, detektor chýb pamäte == 3892 == Copyright (C) 2002-2015 a GNU GPL "d, Julian Seward a kol. == 3892 == Pomocou Valgrind-3.12.0 a LibVEX; znova spustite s -h pre informácie o autorských právach == 3892 == Príkaz: ./a.out == 3892 == == 3892 == Neplatný zápis veľkosti 2 == 3892 = = na 0x4005B4: main (v /home/indever/prg/C/public/a.out) == 3892 == Adresa 0x520004c je 12 bajtov vo vnútri bloku s veľkosťou 13 alloc "d == 3892 == na 0x4C2DB9D: malloc (vg_replace_malloc.c: 299) == 3892 == podľa 0x400597: main (v /home/indever/prg/C/public/a.out) == 3892 == == 3892 == Neplatné čítanie veľkosti 1 == 3892 == na 0x4C30BC4: strlen (vg_replace_strmem.c: 454) == 3892 == podľa 0x4E89AD0: vfprintf (v /usr/lib64/libc-2.24.so) == 3892 usr == rf (071x4E: print) lib64 / libc-2.24.so) == 3892 == podľa 0x4005CF: main (v /home/indever/prg/C/public/a.out) == 3892 == Adresa 0x520004d je 0 bajtov po bloku veľkosti 13 alloc "d == 3892 == na 0x4C2DB9D: malloc (vg_replace_malloc.c: 299) == 3892 == podľa 0x400597: hlavné (v / doma / indever / prg / C / public / a.out) == 3892 == -> Dobrý deň, Habr! == 3892 == == 3892 == SÚHRN HEAP: == 3892 == používa sa pri ukončení: 0 bajtov v 0 blokoch == 3892 == celkové využitie haldy: 2 alokácie, 2 uvoľnenia, 1 037 pridelených bajtov == 3892 = = == 3892 == Všetky bloky haldy boli uvoľnené – nie sú možné žiadne úniky == 3892 == == 3892 == Pre počty zistených a potlačených chýb spustite znova s: -v == 3892 == SÚHRN CHYB: 3 chyby z 2 kontexty (potlačené: 0 z 0)
== 3892 == Všetky bloky haldy boli uvoľnené - nie sú možné žiadne úniky- nedochádza k žiadnym únikom, a to je dobrá správa. Ale stojí za to sklopiť oči trochu nižšie (aj keď, chcem poznamenať, je to len zhrnutie, základné informácie sú trochu inde):

== 3892 == SÚHRN CHYB: 3 chyby z 2 kontextov (potlačené: 0 z 0)
3 chyby. V 2 kontextoch. V takom jednoduchom programe. Ako!?

Je to veľmi jednoduché. Celý „trik“ je v tom, že funkcia strlen neberie do úvahy znak konca riadku – „\ 0“. Aj keď to explicitne určíte vo vstupnom riadku (#define HELLO_STRING "Ahoj Habr! \ N \ 0"), bude sa ignorovať.

Mierne nad výsledkom vykonávania programu sú riadky -> Ahoj Habr! o tom, čo a kde sa nepáčilo nášmu vzácnemu valgrindovi, je podrobná správa. Navrhujem, aby ste sa na tieto riadky pozreli sami a vyvodili závery.

Vlastne, správna verzia program bude vyzerať takto:

#include #include #include #define HELLO_STRING "Ahoj Habr! \ n" void main () (char * str = malloc (sizeof (char) * (strlen (HELLO_STRING) + 1)); strcpy (str, HELLO_STRING); printf ("-> \ t% s ", str); voľný (str);)
Poďme cez valgrind:

$ valgrind --tool = memcheck ./a.out -> Ahoj Habr! == 3435 == == 3435 == SÚHRN HEAP: == 3435 == používa sa pri ukončení: 0 bajtov v 0 blokoch == 3435 == celkové využitie haldy: 2 pridelenia, 2 uvoľnenia, 1 038 pridelených bajtov == 3435 = = == 3435 == Všetky bloky haldy sa uvoľnili – nie sú možné žiadne úniky == 3435 == == 3435 == Pre počty zistených a potlačených chýb spustite znova s: -v == 3435 == SÚHRN CHYB: 0 chýb z 0 kontextov (potlačené: 0 z 0)
Dobre. Žiadne chyby, +1 bajt pridelenej pamäte pomohol vyriešiť problém.

Zaujímavé je, že vo väčšine prípadov bude prvý aj druhý program fungovať rovnako, ale ak pamäť pridelená pre riadok, do ktorého sa nezmestil koncový znak, nebola prázdna, potom funkcia printf () pri výstupe napr. riadku, tiež vypíše všetky odpadky za týmto riadkom - všetko sa zobrazí, kým sa na ceste printf () neobjaví znak konca riadka.

Však viete, (strlen (str) + 1) je také riešenie. Stretávame sa s 2 problémami:

  1. A ak potrebujeme alokovať pamäť pre reťazec vytvorený napríklad pomocou s (n) printf (..)? Nepodporujeme argumenty.
  2. Vzhľad. Riadok deklarácie premennej vyzerá hrozne. Niektorým chlapom sa podarí naskrutkovať (char *) aj malloc, ako keby písali pod plusky. V programe, kde pravidelne potrebujete spracovávať reťazce, má zmysel nájsť elegantnejšie riešenie.
Poďme prísť s riešením, ktoré uspokojí nás aj valgrind.

snprintf ()

int snprintf (char * str, veľkosť_t veľkosť, const char * formát, ...);- funkcia - rozšírenie sprintf, ktoré naformátuje reťazec a zapíše ho do ukazovateľa odovzdaného ako prvý argument. Od sprintf () sa líši tým, že str nebude zapísaných viac bajtov ako je veľkosť.

Funkcia má jednu zaujímavá vlastnosť- v každom prípade vráti veľkosť vygenerovaného reťazca (okrem znaku konca riadka). Ak je reťazec prázdny, vráti sa 0.

Jeden z problémov, ktoré som opísal pri používaní strlen, súvisí s funkciami sprintf () a snprintf (). Predpokladajme, že musíme niečo napísať do str. Posledný reťazec obsahuje hodnoty ďalších premenných. Náš vstup by mal znieť takto:

Char * str = / * tu alokujte pamäť * /; sprintf (str, "Ahoj,% s \ n", "Habr!");
Vzniká otázka: ako určiť, koľko pamäte by sa malo prideliť pre reťazec str?

Char * str = malloc (sizeof (char) * (strlen (str, "Dobrý deň, % s \ n", "Habr!") + 1)); - nepôjde to. Prototyp funkcie strlen () vyzerá takto:

#include size_t strlen (const char * s);
const char * s neznamená, že reťazec odovzdaný do s môže byť formátovací reťazec s premenlivým počtom argumentov.

Tu nám niečo pomôže užitočný majetok funkciu snprintf (), ktorú som spomenul vyššie. Poďme sa pozrieť na kód ďalší program:

#include #include #include void main () (/ * Keďže snprintf () neberie do úvahy znak konca riadka, pridajte jeho veľkosť k výsledku * / size_t need_mem = snprintf (NULL, 0, "Dobrý deň, % s! \ n" , "Habr") + sizeof ("\ 0"); char * str = malloc (needed_mem); snprintf (str, need_mem, "Dobrý deň, % s! \ n", "Habr"); printf ("-> \ t% s", str); voľný (str);)
Spustite program vo valgrind:

$ valgrind --tool = memcheck ./a.out -> Ahoj Habr! == 4132 == == 4132 == SÚHRN HEAP: == 4132 == používa sa pri ukončení: 0 bajtov v 0 blokoch == 4132 == celkové využitie haldy: 2 alokácie, 2 uvoľnenia, 1 041 pridelených bajtov == 4132 = = == 4132 == Všetky bloky haldy boli uvoľnené – nie sú možné žiadne úniky == 4132 == == 4132 == Pre počty zistených a potlačených chýb spustite znova s: -v == 4132 == SÚHRN CHYB: 0 chýb z 0 kontextov (potlačený: 0 z 0) $
Dobre. Máme podporu pre argumenty. Vzhľadom na to, že funkcii snprintf () odovzdávame nulu ako druhý argument, zápis nulovým ukazovateľom nikdy nepovedie k Seagfault. Napriek tomu však funkcia stále vráti požadovanú veľkosť reťazca.

Ale na druhej strane sme museli pridať ďalšiu premennú, a to konštrukciu

Size_t need_mem = snprintf (NULL, 0, "Dobrý deň, % s! \ N", "Habr") + sizeof ("\ 0");
vyzerá ešte horšie ako strlen ().

Vo všeobecnosti možno + sizeof ("\ 0") odstrániť explicitným zadaním "\ 0" na konci formátovacieho reťazca (size_t need_mem = snprintf (NULL, 0, "Dobrý deň, % s! \ N \0 "," Habr ");), ale to nie je v žiadnom prípade vždy možné (v závislosti od mechanizmu spracovania riadkov môžeme prideliť bajt navyše).

Je potrebné niečo urobiť. Trochu som sa zamyslel a rozhodol som sa, že teraz nadišla hodina odvolať sa na múdrosť staroveku. Poďme si popísať makro funkciu, ktorá bude volať snprintf () s nulovým ukazovateľom ako prvým argumentom a null ako druhým. A nezabudnime na koniec radu!

#define strsize (args ...) snprintf (NULL, 0, args) + sizeof ("\ 0")
Áno, pre niekoho to môže byť novinka, ale makrá v C podporujú premenlivý počet argumentov a elipsa hovorí preprocesoru, že zadaný argument funkcie makra (v našom prípade je to args) zodpovedá niekoľkým skutočným argumentom.

Pozrime sa na naše riešenie v praxi:

#include #include #include #define strsize (args ...) snprintf (NULL, 0, args) + sizeof ("\ 0") void main () (char * str = malloc (strsize ("Ahoj,% s \ n", "Habr! ")); sprintf (str," Ahoj,% s \ n "," Habr! "); printf (" -> \ t% s ", str); zadarmo (str);)
Beh s valgrundom:

$ valgrind --tool = memcheck ./a.out -> Ahoj Habr! == 6432 == == 6432 == SÚHRN HEAP: == 6432 == používa sa pri ukončení: 0 bajtov v 0 blokoch == 6432 == celkové využitie haldy: 2 alokácie, 2 uvoľnenia, 1 041 pridelených bajtov == 6432 = = == 6432 == Všetky bloky haldy boli uvoľnené – nie sú možné žiadne úniky == 6432 == == 6432 == Pre počty zistených a potlačených chýb spustite znova s: -v == 6432 == SÚHRN CHYB: 0 chýb z 0 kontextov (potlačené: 0 z 0)
Áno, nie sú tam žiadne chyby. Všetko je správne. A valgrind je šťastný a programátor môže ísť konečne spať.

Nakoniec však poviem niečo iné. V prípade, že potrebujeme alokovať pamäť pre akýkoľvek reťazec (aj s argumentmi), už existuje plne funkčný hotové riešenie .

to je o funkcii asprintf:

#define _GNU_SOURCE / * Pozri feature_test_macros (7) * / #include int asprintf (char ** strp, const char * fmt, ...);
Ako prvý argument vezme ukazovateľ na reťazec (** strp) a pridelí pamäť dereferencovanému ukazovateľu.

Náš program asprintf () by vyzeral takto:

#include #include #include void main () (char * str; asprintf (& str, "Dobrý deň, % s! \ n", "Habr"); printf ("-> \ t% s", str); voľné (str);)
A v skutočnosti vo valgrind:

$ valgrind --tool = memcheck ./a.out -> Ahoj Habr! == 6674 == == 6674 == SÚHRN HEAP: == 6674 == používa sa pri ukončení: 0 bajtov v 0 blokoch == 6674 == celkové využitie haldy: 3 pridelenia, 3 uvoľnenia, 1 138 pridelených bajtov == 6674 = = == 6674 == Všetky bloky haldy boli uvoľnené – nie sú možné žiadne úniky == 6674 == == 6674 == Pre počty zistených a potlačených chýb spustite znova s: -v == 6674 == SÚHRN CHYB: 0 chýb z 0 kontextov (potlačený: 0 z 0)
Všetko je v poriadku, ale ako vidíte, bolo pridelených viac pamäte a teraz existujú tri alokácie, nie dve. Na slabých vstavaných systémoch je táto funkcia nežiaduca.
Okrem toho, ak do konzoly napíšeme man asprintf, uvidíme:

VYHOVUJÚCE Tieto funkcie sú rozšíreniami GNU, nie v C alebo POSIX. Sú tiež dostupné pod * BSD. Implementácia FreeBSD nastaví strp na NULL pri chybe.

Z toho je jasné, že táto funkcia je dostupná len v GNU zdroji.

Záver

Na záver chcem povedať, že práca s reťazcami v C je veľmi zložitá téma, ktorá má množstvo nuancií. Napríklad na písanie "bezpečného" kódu pre dynamickú alokáciu pamäte sa stále odporúča použiť funkciu calloc () namiesto malloc () - calloc upcháva pridelenú pamäť nulami. Alebo po pridelení pamäte použite funkciu memset (). V opačnom prípade môže odpad, ktorý pôvodne ležal v oblasti pridelenej pamäte, spôsobiť otázky počas ladenia a niekedy aj pri práci s reťazcom.

Viac ako polovica mojich kolegov programátorov v jazyku C (väčšina z nich sú začiatočníci), ktorí na moju žiadosť riešili problém s alokáciou pamäte pre reťazce, to robili tak, že to v konečnom dôsledku viedlo k chybám v kontexte. V jednom prípade - dokonca k úniku pamäte (no, človek zabudol urobiť zadarmo (str), komu sa to nestane). V skutočnosti ma to podnietilo vytvoriť tento výtvor, ktorý ste práve čítali.

Dúfam, že pre niekoho bude tento článok užitočný. Prečo som to všetko zjednával - žiadny jazyk nie je jednoduchý. Všade má svoje jemnosti. A čím viac jemností jazyka poznáte, tým lepší je váš kód.

Verím, že po prečítaní tohto článku bude váš kód o niečo lepší :)
Veľa šťastia, Habr!

Reťazce v C++

Reťazec je postupnosť (pole) znakov. Ak sa vo výraze vyskytuje jeden znak, musí byť uzavretý jednoduché úvodzovky ... Pri použití vo výrazoch je reťazec uzavretý v dvojité úvodzovky. Na konci riadku je nulový znak \0 ... V C ++ môžu byť reťazce opísané pomocou symbolov (pole prvkov typu char), ktorý by mal poskytnúť miesto na uloženie ukončovača vedenia.

Napríklad 25-miestny popis reťazca by mal vyzerať takto:

Môžete tiež opísať pole reťazcov:

Je definované pole 3 riadkov po 25 bajtoch.

Na prácu s ukazovateľmi môžete použiť ( znak *). Adresa prvého znaku bude počiatočnou hodnotou ukazovateľa.

Pozrime sa na príklad deklarovania a zobrazenia reťazcov.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

#include "stdafx.h"
#include
pomocou menného priestoru std;
int main ()
{
setlocale (LC_ALL, "Rus");
// opíšeme 3 riadky, s3 je ukazovateľ
char s2 [20], * s3, s4 [30];
cout<< «s2=» ; cin >> s2; // vstupný reťazec s2
cout<< «s2=» << s2<< endl;
// zapíšeme do s3 adresu reťazca, kde je uložený s4. Teraz v premenných
// (ukazovatele) s3 a s4 ukladajú hodnotu rovnakej adresy
s3 = s4;
cout<< «s3=» ; cin >> s3; // vstupný reťazec s3
// zobrazenie riadkov s3 a s4, hoci v dôsledku priradenia s3 = s4;
// teraz sú s3 a s4 rovnaké
cout<< «s3=» << s3<< endl;
cout<< «s4=» << s4<< endl;
systém ("pauza");
návrat 0;
}

Výsledok programu:

Treba však poznamenať, že ak používateľ zadá slová oddelené medzerou do jednej premennej, program bude fungovať inak:

Ide o to, že funkcia cin vstúpi do riadkov pred nájdeným priestorom. Všestrannejšia funkcia je getline.

cin.getline (char * s, int n);

Navrhnuté pre vstupné reťazce klávesnice s s medzerami by riadok nemal obsahovať viac ako n postavy. Preto pre správne zadanie riadkov obsahujúcich medzeru je potrebné v našom programe nahradiť cin >> s na cin.getline (s, 80).

Reťazcové operácie

S reťazcom možno zaobchádzať ako s poľom znakov pomocou algoritmov na spracovanie poľa alebo špeciálnych funkcií na spracovanie reťazcov, z ktorých niektoré sú uvedené nižšie. Ak chcete pracovať s týmito riadkami, musíte pripojiť knižnicu cstring.

Ak chcete previesť číslo na reťazec, môžete použiť funkciu sprintf z knižnice stdio.h.

Niektoré funkcie pre prácu s reťazcami:

Funkčný prototyp Popis funkcie
size_t strlen (const char * s) vypočíta dĺžku reťazca s v bajtoch.
char * strcat (char * dest, const char * scr) pripojí reťazec src na koniec reťazca dest, výsledný výraz sa vráti ako výsledok
char * strcpy (char * dest, const char * scr) skopíruje reťazec sc do miesta v pamäti, na ktoré ukazuje cieľ
char strncat (char * dest, const char * dest, size_t maxlen) pripojí reťazec znakov maxlen z src na koniec dest
char * strncpy (char * dest, const char * scr, size_t maxlen) skopíruje maxlen znaky src do miesta v pamäti, na ktoré ukazuje cieľ
int ctrcmp (const char * s1, const char * s2) porovná dva reťazce v lexikografickom poradí, pričom zohľadní rozdiel medzi veľkými a malými písmenami, funkcia vráti 0, ak sú reťazce rovnaké, vráti - 1, ak je s1 v abecednom poradí pred s2, a inak 1.
int strncmp (const char * s1, const char * s2, size_t maxlen) porovná maximálne znaky dvoch reťazcov v lexikografickom poradí, funkcia vráti 0, ak sú reťazce rovnaké, vráti - 1, ak je s1 v abecednom poradí pred s2, a inak 1.
dvojitý atof (konšt. znak * s) prevedie reťazec na reálne číslo, v prípade neúspešného prevodu sa vráti číslo 0
dlhý atol (konšt. znak * s) skonvertuje reťazec na dlhé celé číslo, ak konverzia zlyhá, vráti sa 0
char * strchr (const char * s, int c); vráti ukazovateľ na prvý výskyt znaku c na reťazec, na ktorý ukazuje s... Ak je symbol c nenájdené, vráti hodnotu NULL
char * strupr (char * s) skonvertuje znaky reťazca, na ktorý ukazuje s, na veľké písmená a potom ho vráti

Typ údajov reťazca

Okrem práce s reťazcami ako s poľom znakov existuje v C ++ špeciálny dátový typ reťazec... Na zadanie premenných tohto typu môžete použiť cin alebo špeciálna funkcia getline.

getline (cin, s);

Tu s- názov premennej typu vstupu reťazec.

Pri popise premennej tohto typu môžete okamžite priradiť hodnotu tejto premennej.

var (s);

Tu var- názov premennej, s- strunová konštanta. Výsledkom tohto operátora je vytvorenie premennej var typu reťazec a zapíše sa do nej hodnota reťazcovej konštanty s... Napríklad,

reťazec v ("Ahoj");

Vytvorí sa reťazec v, do ktorého sa zapisuje hodnota Ahoj.

Prístup k i-tý riadkový prvok s typu reťazec vykonávané štandardným spôsobom s [i]... Nad riadkami ako reťazec sú definované nasledujúce operácie:

  • priradenia, napríklad s1 = s2;
  • zreťazenie reťazca (s1 + = s2 alebo s1 = s1 + s2) - pridá reťazec s2 k reťazcu s1, výsledok sa uloží do reťazca s1, príklad zreťazenia reťazca:
  • porovnania reťazcov na základe lexikografického poradia: s1 = s2, s1! = s2, s1 s2, s1<=s2, s1>= s2 - výsledkom bude boolovská hodnota;

Pri spracovaní reťazcov ako reťazec môžete použiť nasledujúce funkcie:

  • s.substr (pos, dĺžka)- vráti podreťazec z reťazca s počnúc od čísla poz dlhý dĺžka postavy;
  • s.prázdny ()- vráti true, ak reťazec s prázdny, inak falošný;
  • s.insert (pos, s1)- vloží riadok s1 v rade s počnúc od pozície poz;
  • s.remove (poz., dĺžka)- odstraňuje zo šnúrky s podreťazec dĺžka dlhý poz postavy;
  • s.find (s1, poz.)- vráti číslo prvého výskytu reťazca s1 v rade s, vyhľadávanie začína číslom poz, parameter poz môže chýbať, v tomto prípade vyhľadávanie začína od začiatku riadku;
  • s.findfirst (s1, poz.)- vráti číslo prvého výskytu ľubovoľného znaku z reťazca s1 v rade s, vyhľadávanie začína číslom poz ktorý môže chýbať.

Ruština pre struny

Myslím, že ste si už všimli, že pri zobrazovaní ruských písmen sa v konzole objavujú znaky "vľavo". Aby ste predišli tomuto nedorozumeniu, musíte použiť funkciu tretej strany CharToOemA... Pripojíme knižnicu okná.h, je potrebný, aby naša funkcia mohla konvertovať reťazce do iného kódovania. Tiež potrebujeme ďalšie pole znakov. Zdrojový kód programu bude vyzerať takto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14

#include "stdafx.h"
#include
#include
pomocou menného priestoru std;
int main ()
(setlocale (LC_ALL, "Rus");
char s [255] = ( "Musím sa premeniť"} ;
char * pre = nový znak [255];
CharToOemA (s, pre); // transformovať
cout<< s;
vymazať pred;
systém ("pauza >> void");
návrat 0;
}

Práve opísaná metóda nie je dostatočne pohodlná. Na „ruský“ problém však existuje jednoduchšie riešenie. Ako vidíte, program používa funkciu setlocale (), namiesto toho je pohodlnejšie napísať do hlavnej funkcie nasledujúcu konštrukciu.

n »Dôveryhodná SEO agentúra v Indii môže zvýšiť príjmy malých podnikov

80 % používateľov pred nákupom vyhľadáva na Google a iných vyhľadávačoch a viac ako 50 % dopytov generovaných prostredníctvom vyhľadávačov sa konvertuje. Tieto dve štatistiky dokazujú dôležitosť optimalizácie pre vyhľadávače. Existuje mnoho takýchto štatistík a faktov, ktoré jasne ukazujú: akýkoľvek malý, stredný alebo veľký podnik potrebuje profesionálne SEO služby. Malé podniky a začínajúce podniky často čelia problémom s rozpočtom. Môžu využiť pomoc akejkoľvek dôveryhodnej SEO agentúry z Indie, aby získali najlepšiu službu SEO vo svojom rozpočte, aby zvýšili svoje príjmy.
Vyhľadávanie má veľký vplyv na mysle spotrebiteľov. Podľa rôznych štatistík zdieľaných hlavnými odborníkmi na optimalizáciu pre vyhľadávače na rôznych autorizovaných webových stránkach, ako sú Search Engine Land, Moz, SEO Journal, Digital Marketers India, Hubspot atď. SEO zachytáva väčšinu potenciálnych zákazníkov. Okrem toho potenciálni zákazníci pochádzajúci z výsledkov organického vyhľadávania majú vyššiu mieru konverzie. Tieto štatistiky a správanie spotrebiteľov jasnejšie poukazujú na to, že najlepšia služba SEO nie je luxus, ale nevyhnutnosť pre každé podnikanie.
Aby každá organizácia obišla konkurenciu a zvýšila obchodný rast, musí využívať služby optimalizácie pre vyhľadávače. Veľké značky môžu investovať dostatok peňazí do expertnej SEO služby, ktorú ponúka špičková SEO firma alebo SEO špecialista, no majitelia malých firiem často robia kompromisy v kvalite tejto služby kvôli menšiemu rozpočtu. Je tvrdá skutočnosť, že malé podniky a začínajúce podniky opúšťajú príležitosti, ktoré sa dajú vytvoriť pomocou profesionálnej služby SEO, alebo využívajú lacnú službu SEO, ktorá neprináša žiadne pozitívne výsledky.
Majitelia malých podnikov a začínajúci podnikatelia môžu využívať profesionálne SEO služby aj pri obmedzenom rozpočte. Najlepším riešením je nájsť dôveryhodnú SEO spoločnosť so sídlom v Indii. V Indii je veľa SEO expertov, ktorí spolupracujú s agentúrou pre digitálny marketing a ponúkajú najlepšie služby v tomto odvetví. Môžu vám poskytnúť požadované SEO služby vo vašom rozpočte. Mzdy je možné dohodnúť s indickou SEO agentúrou, aby ste získali lepšie služby za nižšie ceny. Nepodliehajte však lacnej službe SEO, ktorá účtuje menej, a sľubujte, že dáte viac, pretože odborné znalosti prichádzajú na svoje vlastné náklady. Pred uzavretím zmluvy so spoločnosťou pre vaše podnikanie musíte vidieť portfólio alebo položiť správne otázky.
SEO experti v Indii majú skúsenosti s najlepšími postupmi optimalizácie pre vyhľadávače. V Indii sú tiež niektorí špecialisti na SEO, ako napríklad Ash Vyas, ktorí sa špecializujú na vytváranie najlepšej stratégie optimalizácie pre vyhľadávače pre podnikanie s daným rozpočtom. SEO profesionáli vytvoria jasný plán a podelia sa aj o očakávané výsledky. Takto si môžete byť dobre vedomí svojich investícií a výnosov. Pomáha to robiť lepšie obchodné rozhodnutia.
Dobrým nápadom je čo najskôr nájsť a uzavrieť zmluvu s dôveryhodnou SEO spoločnosťou z Indie, ktorá ponúka najlepšie SEO služby. Môžete tiež začať s malým rozpočtom a obmedzenými aktivitami, aby ste mohli začať indexovať svoje webové stránky a posilniť svoje kľúčové slová vo vyhľadávačoch. Nečakajte na ideálny čas alebo deň, kedy budete mať tisíce dolárov na investovanie do najlepších SEO služieb. Ak začnete včas, pomôže vám to dosiahnuť rýchlejšie výsledky, keď budete so svojím marketingovým prístupom agresívni. Dôveryhodná SEO spoločnosť so sídlom v Indii vám pomôže definovať vaše súčasné a budúce plány na dosiahnutie dobrých výsledkov. Viac indexovaných stránok zlepšilo hodnotenie a dôveryhodná značka vášho podnikania pomocou nepretržitých profesionálnych postupov SEO zdvojnásobí dopyty, podnikanie a príjmy. Každá malá firma môže začať s dvojcifernou investíciou do profesionálnych SEO služieb. V Indii je veľa SEO agentúr, ktoré ponúkajú nízky rozpočet, ale sú výsledkom orientovaných služieb optimalizácie pre vyhľadávače.

prieskumy z exilu

  • CraigWew

    12.04.2018

    п »їVýznam vytvorenia vzťahu so zákazníkom v oblasti nehnuteľností a všeobecného predaja

    Dôležitosť nadviazania vzťahu so zákazníkom.
    Nadviazanie vzťahu so zákazníkom si treba zaslúžiť a musí sa k nemu pristupovať ako k veľmi integrálnej súčasti procesu predaja.
    Aby ste prinútili zákazníka a seba, aby sa vzťahovali na skutočnej báze jeden k jednému, zahŕňa to dve veci!
    Najprv si to musíte uvedomiť a byť tam! Po druhé, musíte pochopiť, že počas tohto procesu nastanú dve rôzne fázy.
    A-Buď tam-čo to znamená?
    o Väčšina ľudí v skutočnosti nepočúva druhú osobu, keď hovorí. Vo všeobecnosti sú takí zaneprázdnení formulovaním svojej ďalšej odpovede alebo vyjadrenia, že ich v skutočnosti nemohli počúvať.
    o Ak to znie ako vy, byť tam znamená držať hubu a počúvať!
    B-Čo je prvá alebo počiatočná fáza?
    o Vo všeobecnosti máte len pár minút na to, aby ste sa v mysliach zákazníkov etablovali ako niekto, s kým chcú rokovať.
    o Ak máte pochybnosti, je najlepšie najprv položiť otázky, ktoré ich vytiahnu a hovoriť o sebe.
    o Je tiež vždy bezpečné vystupovať ako profesionál – nemám na mysli stoického alebo suchého, ale niekoho, kto vie, čo robí, hovorí a vyzerá.
    C-Iné etapy
    o Ako čas plynie, prostredníctvom konverzácie a otázok, ktoré budú mať, buď preukážete svoje schopnosti, alebo nie.
    o Uvedomte si, že vás budú pravdepodobne chvíľu merať. Dobrou správou je, že v určitom bode, ak ste boli úspešní v nadviazaní vzťahu, sa uvoľnia a obaja sa môžete sústrediť na hľadanie alebo predaj domu.
    Čo mi ešte môže pomôcť rozvinúť vzťah?
    o Pokusom porozumieť rôznym typom osobnosti a potom hovorením a kladením správnych otázok.
    o Ak máte dobrý vzťah (dostanete sa na rovnakú vlnovú dĺžku ako zákazník), potom je predaj v podstate ukončený, teraz už len treba nájsť ten správny domov alebo vyplniť zoznam.
    Čo sa týka rôznych osobností
    o Keďže toto nie je kniha o psychiatrii, pochopte zatiaľ len dva hlavné typy.
    o Existujú introvertní a extrovertní ľudia.
    o Poznáte typ. Zamyslite sa nad tromi ľuďmi, ktorých poznáte, ktorí zodpovedajú každej klasifikácii.
    A čo reč tela a rečové vzorce?
    o Ak hovoria rýchlo alebo pomaly, snažte sa napodobniť ich rečové vzorce.
    o Ak hovoria nahlas alebo potichu, urobte to isté. Nakláňajú sa dopredu alebo dozadu?
    o Netreba dodávať, že na túto tému je napísaných veľa kníh. Uvedomte si, že je to dôležitý faktor – najmä keď sedíte v konferenčnej miestnosti alebo u niekoho doma a diskutujete o obchode za 400 000 dolárov.
    Rozvíjanie vzťahu je zručnosť, ktorú sa možno naučiť a zdokonaliť.
    o Všetci sme zažili predajcu, ktorý nám niečo predal, a napriek tomu sme nemali pocit, že nás predávajú. Dôvodom je, že sa vďaka nemu cítite pohodlne tam, kde ste im dôverovali.
    Ako rozvíjame vzťah?
    o Používajte oči a uši a pýtajte sa. Vysvetliť
    o Použite oči:
    o Pozrite sa na ich šaty – ich auto – ich osobný majetok a myslím tým, že sa na ne skutočne pozrite a rozlúštite, čo vám to o nich hovorí.
    o Použite uši:
    o Počúvajte, čo hovoria, a pýtajte sa, aby ste pochopili podstatu ich skutočnej MOTIVÁCIE!
    Teraz počas celého tohto rozhovoru pravdepodobne zistíte jednu alebo dve veci, ktoré s nimi máte spoločné. (Rodina, zemepisné oblasti, rybolov atď.) Keď narazíte na spoločnú reč, povedzte im, že sa poznáte, a potom si nájdite chvíľu na to, aby ste to s nimi prediskutovali.
    Čo je cieľom?
    o Akonáhle vás prijmú ako jedného z nich, budete mať skutočne skvelé skúsenosti s predajom, pretože teraz spolupracujete a potom ako tím – už nie ste predajcom, teraz ste v pozícii poradcu ...
    o Pamätajte, že zákazník vám umožní alebo nedovolí vstúpiť do jeho sveta. Ak to pochopíte a naozaj tvrdo pracujete na tom, aby ste sa k nemu/nej vcítili, môžete získať dôveru. Vo väčšine prípadov ich skutočne uvidíte relaxovať (reč tela), keď sa to stane, keď ste na ceste.
    o Aby ste to ilustrovali, mali ste niekedy prejav a všimli ste si, že keď ste sa konečne spojili s členom publika, súhlasne prikývli. Všetky tieto veci sa môžu zdať banálne, ale nie sú.
    Na záver, ak si dokážete získať dôveru zákazníkov, predaj produktu alebo služby je oveľa jednoduchší a zážitok môže byť príjemný pre všetkých zúčastnených.
    Vždy si pamätajte, že najlepšia situácia je Win / Win.

Práca so strunami. Strunová trieda. Konštruktéri tried. Funkcie priradiť (), pripojiť (), vložiť (), nahradiť (), vymazať (), nájsť (), rfind (), porovnať (), c_str (). Príklady

1. Aký je účel triedy string v programoch C ++?

Trieda string je navrhnutá tak, aby pracovala s reťazcami typu char *, čo sú reťazce ukončené nulou. Trieda string bola zavedená ako alternatíva pre prácu s reťazcami typu char *. Riadky, ktoré sa končia znakom ‘\0’ nazývané aj C-struny. Keďže string je trieda, môžete deklarovať objekty tejto triedy.

2. Aké moduly (knižnice) je potrebné pripojiť, aby ste využili možnosti triedy string v MS Visual Studio C ++?

Ak chcete využiť možnosti triedy string v MS Visual Studio (C ++), musíte zahrnúť knižnicu a std menný priestor.

#include pomocou menného priestoru std;
3. Ako sa deklaruje premenná typu reťazec? Príklady

Deklarovanie premennej typu string sa vykonáva rovnakým spôsobom ako pri bežnej premennej. Možná deklarácia simultánnej inicializácie.

// typ reťazca string s1; // premenná s názvom s1 typu string string s2 = "Toto je reťazcová premenná"; // deklarácia s inicializáciou // pomocou premennej typu string s operátorom priradenia s1 = s2; // s1 = "Toto je reťazcová premenná" s2 = "Nový text";
4. Aké sú výhody a nevýhody použitia triedy string oproti char *?

Vznik nového typu string bol spôsobený nedostatkami práce so znakovými reťazcami, ktoré demonštroval typ char *. V porovnaní s typom char * má typ string tieto hlavné výhody:

  • schopnosť spracovávať reťazce pomocou štandardných operátorov C ++ ( = , + , = = , <> atď.). Ako viete, pri použití typu char * aj tie najjednoduchšie operácie s reťazcami vyzerali komplikovane a vyžadovali písanie nadmerného programovacieho kódu;
  • zabezpečenie najlepšej spoľahlivosti (bezpečnosti) programového kódu. Napríklad pri kopírovaní reťazcov poskytuje typ reťazca vhodné akcie, ktoré sa môžu vyskytnúť, ak je zdrojový reťazec väčší ako cieľový reťazec;
  • poskytovanie reťazca ako nezávislého dátového typu. Deklarácia typu string ako string je rovnaká pre všetky premenné v programe, čo zabezpečuje konzistenciu dát.

Hlavnou nevýhodou typu string v porovnaní s typom char * je nižšia rýchlosť spracovania dát. Je to preto, že typ reťazca je v skutočnosti trieda kontajnera. A práca s triedou vyžaduje dodatočnú implementáciu programového kódu, čo si zase vyžaduje viac času.

5. Aké operátory možno použiť s objektmi triedy string?

Trieda string je pohodlná v tom, že vám umožňuje pohodlne manipulovať s reťazcami pomocou štandardných (preťažených) operátorov.

Nasledujúce operátory možno použiť s objektmi triedy string

  • = - zadanie
  • + - zreťazenie (reťazcové zreťazenie)
  • += - priradenie so zreťazením
  • == - rovnosť
  • != - nerovnosť
  • < - menší
  • <= - menšie alebo rovné
  • > - viac
  • >= - viac alebo rovnaký
  • - indexovanie

príklad, ktorý demonštruje použitie vyššie uvedených operátorov

// typ reťazca, operácie s reťazcami reťazec s1 = "s-1"; reťazec s2 = "s-2"; reťazec s3; bool b; // operácia "=" (priradenie reťazcov) s3 = s1; // s3 = "s-1" // operácia "+" - zreťazenie reťazcov s3 = s3 + s2; // s3 = "s-1s-2" // operácia "+ =" - priradenie so zreťazením s3 = "s-3"; s3 + = "abc"; // s3 = "s-3abc" // operácia "==" - porovnanie reťazcov b = s2 == s1; // b = nepravda b = s2 == "s-2"; // b = pravda // operácia "! =" - porovnanie reťazcov (nerovná sa) s1 = "s1"; s2 = "s2"; b = s1! = s2; // b = pravda // operácie "<" и ">"- porovnanie reťazcov s1 = "abcd"; s2 = "de"; b = s1 > s2; // b = nepravda b = s1< s2; // b = true // operácie "<=" и ">= "- porovnanie reťazcov (menšie alebo rovné, väčšie alebo rovné) s1 = "abcd"; s2 = "ab"; b = s1 > = s2; // b = pravda b = s1<= s2; // b = false b = s2 >= "ab"; // b = pravda // operácia - indexovanie char c; s1 = "abcd"; c = s1; // c = "c" c = s1; // c = "a"
6. Obsahuje trieda string konštruktory?

Ako každá trieda, aj trieda string má množstvo konštruktorov. Hlavné sú nasledovné:

Reťazec (); reťazec (const char * str); string (const string & str);

7. Príklady inicializácie pomocou konštruktorov

Nasledujú príklady inicializácie premenné typu reťazec

Reťazec s1 ("Ahoj!"); string s2 = "Ahoj!" ; // inicializácia - reťazec konštruktora (const char * str) char * ps = "Ahoj"; reťazec s3 (ps); // inicializačný reťazec s4 (s3); // inicializácia - reťazec konštruktora (const string & str) reťazec s5; // inicializácia - reťazec konštruktora ()

8. Priradenie reťazcov. Priradiť funkciu (). Príklady

Ak chcete priradiť jeden reťazec druhému, môžete použiť jednu z dvoch metód:

  • použite operátor priradenia ‘=’ ;
  • použite funkciu priradiť () z triedy string.

Funkcia priradiť () má niekoľko preťažených implementácií.

Prvou možnosťou je volanie funkcie bez parametrov.

String & assign (void);

V tomto prípade ide o jednoduché priradenie jedného reťazca k druhému.

Druhá možnosť vám umožňuje skopírovať daný počet znakov z reťazca:

String & assign (const string & s, size_type st, size_type num);

  • s - objekt, z ktorého je prevzatý zdrojový reťazec;
  • st - index (pozícia) v reťazci, od ktorého sa má začať kopírovať num znakov;
  • num - počet znakov na kopírovanie z pozície st;
  • size_type je radový dátový typ.

Tretí variant funkcie priradiť () skopíruje prvé znaky reťazca s volajúcemu:

String & assign (const char * s, size_type num);

  • s - reťazec ukončený znakom ‘\0’ ;
  • num je počet znakov, ktoré sa skopírujú volajúcemu. Prvý počet znakov z reťazca s sa skopíruje.

Nižšie je uvedený príklad s rôznymi implementáciami funkcie priradiť ().

Príklad.

// priradenie reťazcov, priradenie funkcie () reťazec s1 = "stránka"; reťazec s2; reťazec s3; char * ps = "stránka"; s3 = s1; // s3 = "site" s2.assign (s1); // s2 = "site" s2.assign (s1, 0, 4); // s2 = "najlepsie" s2.assign (ps, 8); // s2 = "bestprog"
9. Reťazenie reťazcov. Funkcia Append (). Príklad

Funkcia append () sa používa na zreťazenie reťazcov. Operáciu môžete použiť aj na pridávanie riadkov ‘+’ , napríklad:

Reťazec s1; reťazec s2; s1 = "abc"; s2 = "def"; s1 = s1 + s2; // s1 = "abcdef"

Funkcia append () je však dobrá, keď potrebujete pripojiť časť reťazca.

Funkcia má nasledujúce možnosti implementácia:

String & append (const string & s, size_type start); string & append (const char * s, size_type num);

V prvej implementácii dostane funkcia odkaz na objekt typu reťazec s ktorý sa pridá k volajúcemu. V druhej implementácii funkcia prijíma ukazovateľ na reťazec const char *, ktorý končí znakom '\ 0'.

Príklad. Ukážka funkcie append ().

Reťazec s1 = "abcdef"; s2 = "1234567890"; pripojiť (s2, 3, 4); // s1 = "abcdef4567" char * ps = "1234567890"; s1 = "abcdef"; s1.append (ps, 3); // s1 = "abcdef123"

10. Vkladanie znakov do riadku. Funkcia Vložiť (). Príklad

Ak chcete vložiť jeden riadok na danú pozíciu iného riadku, musíte použiť vložiť funkciu(), ktorý má viacero možností realizácie.

Prvá verzia funkcie umožňuje vložiť celý reťazec s na zadanú počiatočnú pozíciu volajúcej linky (volajúceho objektu):

String & insert (size_type start, const string & s);

Druhá verzia funkcie umožňuje vložiť časť (parametre insStart, num) reťazca s na danú počiatočnú pozíciu volajúceho reťazca:

String & insert (size_type start, const string & s, size_type insStart, size_type num);

Vo vyššie uvedených funkciách:

  • s - reťazec, ktorý sa má vložiť do volajúceho reťazca;
  • štart - pozícia v volacej linke, z ktorej sa má vložiť reťazec s;
  • insStart - pozícia v reťazci s, z ktorej sa má vložiť;
  • num je počet znakov v reťazci s, ktorý sa má vložiť z pozície insStart.
reťazec s1 = "abcdef"; reťazec s2 = "1234567890"; s1.vložka (3, s2); // s1 = "abc" + "1234567890" + "def" = "abc1234567890def" s2.vložiť (2, s1, 1, 3); // s2 = "12bcd34567890"
11. Nahradenie znakov v reťazci. Funkcia Nahradiť (). Príklad

Funkcia nahradiť () nahrádza znaky vo volajúcom reťazci. Funkcia má nasledujúce možnosti implementácie:

Reťazec & nahradiť (size_type start, size_type num, const string & s); string & nahradit (size_type start, size_type num, const string & s, size_type replStart, size_type replNum);

V prvej implementácii je volací reťazec nahradený reťazcom s. Je možné nastaviť pozíciu (začiatok) a počet znakov (num) vo volajúcom riadku, ktoré je potrebné nahradiť reťazcom s.

Druhá verzia funkcie nahradiť () sa líši od prvej v tom, že umožňuje nahradiť volajúci reťazec iba časťou reťazca s. V tomto prípade dve dodatočné parametre: pozícia replStart a počet znakov v reťazci s, ktorý tvorí podreťazec, ktorý nahrádza volajúci reťazec.

Príklad. Ukážka funkcie nahradiť ().

Reťazec s1 = "abcdef"; reťazec s2 = "1234567890"; s2.nahradiť (2, 4, s1); // s2 = "12abcdef7890" s2 = "1234567890"; s2.nahradiť (3, 2, s1); // s2 = "123abcdef67890" s2 = "1234567890"; s2.nahradiť (5, 1, s1); // s2 = "12345abcdef7890" // nahradenie znakov, funkcia nahradenie (). reťazec s1 = "abcdef"; reťazec s2 = "1234567890"; s2.nahradiť (2, 4, s1); // s2 = "12abcdef7890" s2 = "1234567890"; s2.nahradiť (3, 2, s1); // s2 = "123abcdef67890" s2 = "1234567890"; s2.nahradiť (5, 1, s1); // s2 = "12345abcdef7890" s2 = "1234567890"; s2.nahradiť (5, 1, s1, 2, 3); // s2 = "12345cde7890" s2 = "1234567890"; s2.nahradiť (4, 2, s1, 0, 4); // s2 = "1234abcd7890"

12. Odstránenie dané množstvo znaky z reťazca. Funkcia vymazať (). Príklad

Ak chcete odstrániť znaky z volajúceho reťazca, použite funkciu vymazať ():

String & erase (size_type index = 0, size_type num = npos);

  • index - index (pozícia), od ktorej chcete odstrániť znaky vo volajúcom riadku;
  • num je počet znakov, ktoré sa majú odstrániť.

Príklad.

Reťazec s = "01234567890"; s.erase (3, 5); // s = "012890" s = "01234567890"; s.erase (); // s = ""

13. Vyhľadajte znak v reťazci. Funkcie Find () a rfind (). Príklady

V strunová trieda vyhľadávanie reťazca v podreťazci je možné vykonať dvoma spôsobmi, ktoré sa líšia smerom hľadania:

  • pohľadom na reťazec od začiatku do konca pomocou funkcie find ();
  • skenovaním reťazca od konca po začiatok pomocou rfind ().

Prototyp funkcie find () vyzerá takto:

Size_type find (const string & s, size_type start = 0) const;

  • s - podreťazec, ktorý sa hľadá v reťazci, čo spôsobuje túto funkciu... Funkcia hľadá prvý výskyt reťazca s. Ak sa v reťazci, ktorý volal danú funkciu, nachádza podreťazec s, vráti sa pozícia prvého výskytu. V opačnom prípade sa vráti -1;

Prototyp funkcie rfind () je:

Size_type rfind (const string & s, size_type start = npos) const;

  • s je podreťazec, ktorý sa má hľadať vo volajúcom reťazci. Vyhľadávanie podreťazca v reťazci sa vykonáva od konca po začiatok. Ak sa vo volajúcom reťazci nachádza podreťazec s, funkcia vráti pozíciu prvého výskytu. V opačnom prípade funkcia vráti -1;
  • npos - pozícia posledného znaku volajúcej linky;
  • štart - pozícia, z ktorej sa vyhľadávanie vykonáva.

Príklad 1Útržok kódu, ktorý demonštruje výsledok funkcie find ().

// typ reťazca, funkcia find (). reťazec s1 = "01234567890"; reťazec s2 = "345"; reťazec s3 = "abcd"; int poz; poz = s1.nájsť (s2); // pos = 3 pos = s1.find (s2, 1); // pos = 3 pos = s1.find ("jklmn", 0); // pos = -1 pos = s1.find (s3); // pos = -1 pos = s2.find (s1); // pozícia = -1

Príklad 2 Ukážka funkcie rfind ().

// typ reťazca, funkcie find () a rfind () reťazec s1 = "01234567890"; reťazec s2 = "345"; reťazec s3 = "abcd"; string s4 = "abcd --- abcd"; int poz; pos = s1.find (s2); // pos = 3 pos = s1.rfind (s2, 12); // poz = 3 poz = s1.rfind (s2, 3); // pos = 3 pos = s1.find (s2, 2); // pos = -1 pos = s2.rfind (s1); // pos = -1 pos = s1.rfind (s3, 0); // pozícia = -1 // rozdiel medzi nájsť funkcie() a nájsť () pos = s4.find (s3); // poz = 7 poz = s4.find (s3); // pozícia = 0
14. Porovnanie častí strún. Funkcia Porovnať (). Príklad

Keďže typ reťazca je trieda, môžete operáciu použiť na porovnanie dvoch reťazcov navzájom ‘= =’ ... Ak sú tieto dva reťazce rovnaké, porovnanie bude pravdivé. V opačnom prípade bude výsledok porovnania nepravdivý.

Ale ak potrebujete porovnať časť jedného reťazca s iným, potom je na to poskytnutá funkcia porovnanie ().

Prototyp porovnávacej () funkcie:

int porovnanie (size_type start, size_type num, const string & s) const;
  • s - reťazec na porovnanie s volajúcim reťazcom;
  • začiatok - pozícia (index) v reťazci s, od ktorej sa začnú prezerať znaky reťazca na porovnanie;
  • num je počet znakov v reťazci s na porovnanie s volajúcim reťazcom.

Funkcia funguje nasledujúcim spôsobom... Ak je volacia linka menej riadku s, potom funkcia vráti -1 (záporná hodnota). Ak je volacia linka viac riadku s, funkcia vráti 1 (kladná hodnota). Ak sú tieto dva reťazce rovnaké, funkcia vráti 0.

Príklad... Ukážka funkcie porovnanie ():

// typ reťazca, funkcia porovnanie (). reťazec s1 = "012345"; reťazec s2 = "0123456789"; int res; res = s1.porovnaj (s2); // res = -1 res = s1.compare ("33333"); // res = -1 res = s1.compare ("012345"); // res = 0 res = s1.compare ("345"); // res = -1 res = s1.compare (0, 5, s2); // res = -1 res = s2.compare (0, 5, s1); // res = -1 res = s1.compare (0, 5, "012345"); // res = -1 res = s2.compare (s1); // res = 1 res = s2.compare ("456"); // res = -1 res = s2.compare ("000000"); // res = 1
15. Získanie reťazca so znakom konca riadka '\ 0' (char *). Funkcia C_str (). Príklad

Ak chcete získať reťazec, ktorý končí znakom ‘\0’ používa sa funkcia c_str ().

Funkčný prototyp:

const char * c_str () const;

Funkcia je deklarovaná s modifikátorom const. To znamená, že funkcia nemôže modifikovať volajúceho (reťazca).

Príklad 1... Konverzia reťazca na const char *.

// typ reťazca, funkcia c_str () string s = "abcdef"; const char * ps; ps = s.c_str (); // ps = "abcdef"

Príklad 2

Nasledujúci text demonštruje preklad reťazca z reťazca do System :: Typ reťazca na jeho zobrazenie v ovládacom prvku typu Label.

V programe môžu byť reťazce definované takto:

  • ako reťazcové konštanty;
  • ako polia znakov;
  • cez ukazovateľ na typ znaku;
  • ako polia reťazcov.

Okrem toho musí existovať alokácia pamäte na uloženie reťazca.

Akákoľvek postupnosť znakov uzavretá v úvodzovkách "" sa považuje za reťazcová konštanta.

Pre správny výstup musí každý riadok končiť nulovým znakom "\ 0", ktorého celočíselná hodnota je 0. Pri deklarovaní reťazcovej konštanty sa k nej automaticky pridá nulový znak. Vloží sa teda postupnosť znakov reprezentujúcich reťazcovú konštantu Náhodný vstup do pamäťe počítača vrátane nulového bajtu.

Na ukladanie reťazca sú vyčlenené sekvenčné pamäťové bunky. Reťazec je teda pole znakov. Na uloženie kódu každého znaku v reťazci je pridelený 1 bajt.

Na umiestnenie niektorých servisných znakov do reťazcovej konštanty sa používajú symbolické kombinácie. Ak teda chcete do reťazca vložiť znak dvojitej úvodzovky, musí mu predchádzať znak spätnej lomky: ‚\‘‘.

Konštanty reťazca sú alokované v statickej pamäti. Počiatočná adresa postupnosti znakov v úvodzovkách sa považuje za adresu reťazca. Konštanty reťazca sa často používajú na komunikáciu s používateľom vo funkciách, ako je printf ().

Pri určovaní pole znakov je potrebné oznámiť kompilátoru požadovanú veľkosť pamäte.

čaro;

Kompilátor môže tiež nezávisle určiť veľkosť poľa znakov, ak je inicializácia poľa špecifikovaná pri jeho deklarovaní ako reťazcová konštanta:

char m2 =;
char m3 = ( "T", "and", "x", "and", "e", "", "d", "o", "l", "and", "n", "s", "", "p", "o", "l", "n", "s", "", "s", "v", "e", "g", "e", "y", "", "m", "g", "l", "o", "y", "\ 0"};

V tomto prípade sú názvy m2 a m3 ukazovatele na prvé prvky polí:

  • m2 sa rovná & m2
  • m2 sa rovná 'G'
  • m2 sa rovná 'o'
  • m3 sa rovná & m3
  • m3 je ekvivalentné 'x'

Pri deklarovaní poľa znakov a jeho inicializácii pomocou reťazcovej konštanty môžete explicitne určiť veľkosť poľa, ale špecifikovaná veľkosť poľa musí byť väčšia ako veľkosť inicializačnej reťazcovej konštanty:

char m2 = "Horské štíty spia v tme noci.";

Ak chcete zadať reťazec, môžete použiť ukazovateľ na typ postavy.

char * m4;

V tomto prípade môže byť deklarácii poľa k premennej m4 priradená adresa poľa:

m4 = m3;
* m4 je ekvivalentné m3 = "T"
* (m4 + 1) je ekvivalentné m3 = "a"

Tu je m3 konštanta ukazovateľa. Nemôžete zmeniť m3, pretože by to znamenalo zmenu pozície (adresy) poľa v pamäti, na rozdiel od m4.

Pre ukazovateľ môžete použiť operáciu zvýšenia (presun na ďalší znak):

Pole reťazcov znakov

Niekedy je v programoch potrebný popis pole znakové reťazce ... V tomto prípade môžete použiť index riadkov na prístup k viacerým rôznym riadkom.

char * básnik = ( "Básnik je mŕtvy!", "- otrok cti -",
"Kamarát," "ohováraný fámou ..."};

V tomto prípade je poet pole štyroch ukazovateľov na reťazce znakov. Každý reťazec znakov je pole znakov, takže existujú štyri ukazovatele na polia. Ukazovateľ básnika odkazuje na prvý riadok:
*básnik ekvivalentné k "NS",
* básnik [l] ekvivalentné k "-" .

Inicializácia sa vykonáva podľa pravidiel definovaných pre polia.
Citované texty sú ekvivalentné inicializácii každého reťazca v poli. Čiarka oddeľuje susedné
sekvencie.
Okrem toho môžete explicitne nastaviť veľkosť reťazcov znakov pomocou popisu, ako je tento:

char básnik;

Rozdiel je v tom, že tento tvar definuje „obdĺžnikové“ pole, v ktorom majú všetky čiary rovnakú dĺžku.

Voľné pole

Popis

сhar * básnik;


definuje voľné pole, kde dĺžka každého reťazca je určená ukazovateľom, ktorý tento reťazec inicializuje. Voľné pole neplytvá pamäťou.

Reťazcové operácie

Väčšina operácií s reťazcami v jazyku C funguje na ukazovateľoch. Ak chcete umiestniť reťazec znakov do pamäte RAM, musíte:

  • alokovať blok pamäte RAM pre pole;
  • inicializujte reťazec.

Na pridelenie pamäte na uloženie reťazca možno použiť funkcie dynamického prideľovania pamäte. V tomto prípade je potrebné vziať do úvahy požadovanú veľkosť riadku:

char * meno;
meno = (char *) malloc (10);
scanf ("% 9s", názov);

Na zadanie reťazca bola použitá funkcia scanf () a vstupný reťazec nemôže presiahnuť 9 znakov. Posledný znak bude obsahovať "\ 0".

Funkcie vstupu reťazca

Na zadanie reťazca možno použiť funkciu scanf (). Funkcia scanf () je však určená na získanie slova a nie reťazca. Ak na zadanie použijete formát "% s", reťazec sa zadá pred nasledujúcim prázdnym znakom (nie však vrátane), ktorým môže byť medzera, tabulátor alebo posun riadkov.

Ak chcete zadať reťazec vrátane medzier, použite funkciu

char * dostane (char *);


alebo jej ekvivalent

char * get_s (char *);

Ukazovateľ na vstupný reťazec sa odovzdá funkcii ako argument. Funkcia žiada používateľa, aby zadal reťazec, ktorý vloží do poľa, kým používateľ neklikne Zadajte.

Funkcie výstupu reťazca

Na zobrazenie riadkov môžete použiť vyššie uvedenú funkciu

printf ("% s", str); // str je ukazovateľ na reťazec

alebo v skrátenom formáte

printf (str);

Funkciu je možné použiť aj na zobrazenie čiar

int vloží (char * s);

ktorý vypíše reťazec s a presunie kurzor na Nový riadok(na rozdiel od printf ()). Na výstup možno použiť aj funkciu puts (). reťazcové konštanty v úvodzovkách.

Funkcia zadávania znakov

Na zadávanie znakov môžete použiť funkciu

char getchar ();


ktorý vráti hodnotu znaku zadaného z klávesnice. Zadaná funkcia použité v predchádzajúcich príkladoch na oneskorenie okna konzoly po spustení programu, kým sa nestlačí kláves.

Funkcia výstupu znakov

Na zobrazenie znakov možno použiť funkciu

char putchar (char);


ktorý vráti hodnotu znaku na zobrazenie a vypíše znak odovzdaný ako argument na obrazovku.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

#include
#include
#include
int main () (
char s, sym;
int počet, i;
systém ("chcp 1251");
systém ("cls");
printf ( "Zadajte reťazec: ");
dostane_s (s);
printf ( "Zadajte znak:");
sym = getchar ();
počet = 0;
pre (i = 0; s [i]! = "\ 0"; i ++)
{
if (s [i] == sym)
počítať ++;
}
printf ("On line \ n");
kladie (s); // Linkový výstup
printf ("znak");
putchar (sym); // Zobrazenie symbolu
printf ( "vyskytuje sa % d-krát", počítať);
getchar (); getchar ();
návrat 0;
}

Výsledok popravy

Základné funkcie štandardnej knižnice string.h

Hlavné funkcie štandardnej knižnice string.h sú uvedené v tabuľke.

Funkcia Popis

char * strcat (char * s1, char * s2)

spojí s2 s s1, vráti s1

char * strncat (char * s1, char * s2, int n)

pripojí najviac n znakov s2 k s1, reťazec ukončí "\ 0", vráti s1

char * strcpy (char * s1, char * s2)

skopíruje reťazec s2 do reťazca s1 vrátane "\ 0", vráti s1
);
strncpy (m3, m1, 6); // nepridáva "\ 0" na koniec riadku
kladie ( "Výsledok strncpy (m3, m1, 6)");
vloží (m3);
strcpy (m3, m1);
kladie ( "Výsledok strcpy (m3, m1)");
vloží (m3);
kladie ( "Výsledok strcmp (m3, m1) je");
printf ("% d", strcmp (m3, m1));
strncat (m3, m2, 5);
kladie ( "Strncat výsledku (m3, m2, 5)");
vloží (m3);
strcat (m3, m2);
kladie ( "Strcat výsledku (m3, m2)");
vloží (m3);
kladie ( "Počet znakov v reťazci m1 sa rovná strlen (m1):");
printf ("% d \ n", strlen (m1));
_strnset (m3, "f", 7);
kladie ( "Strnset výsledku (m3," f ", 7)");
vloží (m3);
_strset (m3, "k");
kladie ( "Strnset výsledku (m3," k ")");
vloží (m3);
getchar ();
návrat 0;
}

Výsledok popravy