Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
л_13_Строки у.ppt
Скачиваний:
23
Добавлен:
30.05.2020
Размер:
1.33 Mб
Скачать

Рядки, дії з рядками

Лекція

Рядки

У С + + відсутній спеціальний строковий тип.

У С + + використовуються два види рядків:

рядок як масив символів типу char (char *-рядка)

рядок як об'єкт класу string

рядок як масив символів типу char:

const int MAX = 80;

// розмір рядка

char str [MAX];

// сам рядок, її визначення схоже на визначення масиву типу char

cin >> str;

// введення рядка, наприклад, вводимо рядок “Minsk”

Останнім символом рядка (як масиву елементів типу char) Обов'язково повинен бути '\ 0' (нуль-символ), тому до довжини масиву завжди необхідно додавати 1.

У пам'яті:

M i

n

s

k

\0

 

 

 

 

 

строковий буфер str

 

невикористовувана частина строкового буфера

 

 

 

 

 

 

 

2

Рядки

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Приклади

 

 

 

 

 

 

 

 

 

 

 

 

 

«Сміття»

 

 

 

 

char str

[20] = “Good Morning”;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

cout << str;

// Good Morning

 

 

 

 

 

 

 

 

 

 

 

 

 

G o o d

 

M o r n i n g \0

 

 

 

 

 

 

 

 

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

strcpy(str, “Hello”);

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

cout << str; // Hello

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

H

e l l

o \0

o r n i

n

g

\0

 

 

 

 

 

 

 

 

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

strcpy(str,“”);

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

\0

e l l

o \0

o r n i

n

g

\0

 

 

 

 

 

 

 

 

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

// надрукує abcdef; т.к. \ - Символ продовження

Рядки

 

 

Як і інші типи даних,

Строкові константи

 

 

 

рядки можуть бути:

 

 

 

 

 

змінними і константами

 

 

 

 

У строковий літерал можна включати недруковані символи :

”abc\ndef” // символи будуть надруковані в два рядка ”abc\\ndef” //буде видано abc\ndef

Довгий строковий літерал передбачає запис :

”abc\ def”

рядка

але!!!

”abc<enter>

// error!!!

 

def”

Рядок "abc \ 000def" буде оброблятися як abc ('\ 0' - означає кінець рядка).

У строковому літералі можливе використання кількох рядків :

"текст1""текст2""текст3";

cout << "abc\\ndef" "aaa" "mmm"<< endl;

виведе рядок abc\ndefaaammm.

#define OTVET1 "odin"

// препроцесорний рядок-константа

const char str[3] ="dwa";

// типізований рядок-константа

 

 

Рядки

 

Визначення рядків :

 

 

 

 

 

1. рядок як масив символів:

 

 

 

 

// 0-символ додається автоматично

 

char string [ ] = “Minsk”;

 

char string1 [6] = “Minsk”;

// 0-символ додається автоматично

 

char string2 [6] = {‘M’, ‘i’, ‘n’, ‘s’, ‘k’, ‘\0’}; //0-символ додаємо самостійно

 

cout << sizeof (string1) << endl;

 

//розмір рядка дорівнює 6

cout << strlen (string1) << endl; // довжина рядка дорівнює 5, прототип функції в <string.h>

Ім'я рядка (як і для будь-яких інших масивів) - константних покажчик на неконстантние дані (на елемент з номером 0); тобто ім'я рядка завжди вказує на одну і ту ж комірку пам'яті, але використовуючи

це ім'я і індекси можна звертатися до всіх даних у рядку і змінювати їх: string [i] = * (string + i).

Відмінність від масивів! :

при виведенні покажчик автоматично разименовивается, і ми отримуємо рядок, що починається з елемента номер 0 і що закінчується 0-символом:

cout << string << endl;

cout << & string << endl; / / виводить адресу

Константні покажчики (покажчики, оголошені як const: int * const pi) повинні отримувати початкові значення при своєму визначенні.

string1++; неможно!!!

покажчик-константа

pi++ неможно!!!

string1 [i] = 5; //можно!!!

дані неконстантні

pi[2]=3; можно!!!

Рядки

Визначення рядків :

 

2. рядок як вказівник на char:

char *string4 = “Minsk”, *string5;

// ініціалізація вказівника string4

string5 = “design”;

// ініціалізація вказівника string5

У цьому випадку імена рядків - неконстантні вказівники на константні дані: тобто дані «тільки для читання».

char *s1= “pointer_of_simvol”;

//s1[3]='q'; !!!error, спроба змінити константні дані

s1++;

// OK!!!

cout << s1;

// ointer_of_simvol

Хороший стиль – оголошувати сonst char *string4 = “Minsk”;

Неконстантні вказівники string4 і string5 отримують початкові значення, рівні адресами перших елементів строкових літералів. Самі літерали у форматі С- рядки розташовуються в пам'яті програми.

Покажчик на char автоматично разіменовивається як і для рядка-масиву. В якості негативних наслідків :

char c=‘a’; char *pc=&c; cout << pc;

виводить з пам'яті все підряд з адреси символу 'a' і до «випадкового» символу ‘\0’.

!!!cout << sizeof (*string4) << endl; // виведе 1, нульовий елемент рядка cout << strlen (string4) << endl; // виведе 5, без '\ 0', прототип функції в <string.h>// виведе 4, розмір вказівникаcout << sizeof (string4) << endl;

Рядки

3. рядок як елемент масиву рядків

char den[ ][10]= {"poned", "vtor", "sreda", "chetv", "pjatn", "sub", "voskr"};

4. рядок як елемент масиву покажчиків на char char *otvet1[ ] = { ”odin”, “dwa” };

char str1[ ] = "string-array";

// рядок-масив: str1-константний вказівник

 

// на неконстантні дані, ініціалізується літералом

cout << str1 << endl;

//виведе: string-array

// str1++;

// ні, str1 – вказівник-константа

str1[0]='a';

// так, str1 – вказівник на неконстантні дані

cout << str1[0]<< endl;

// виведе перший елемент рядка : a

char* str2 = "string-pointer"; // рядок-вказівник: str2-неконстантний вказівник

 

// на строкову константу, ініціалізується її адресою

cout << str2 << endl;

//виведе: string- pointer

str2++;

// да, str2 – вказівник-змінна

// str2[1]='a';

// нет, str2 – вказівник на константу

cout << str2<< endl;

//виведе: tring-pointer

Для динамічного рядка описуємо вказівник на char і виділяємо пам'ять за

допомогою new или malloc.

 

 

Динамічні рядки, як і інші

 

char *p = new char[m];

 

динамічні масиви, не можна

 

char *q = (char *) malloc(m*sizeof(char));

ініціалізувати при створенні

 

 

 

 

Рядки.

Особливості роботи з C-рядками, описаними різними способами

//приклад 1: рядок - вказівник

#include <string.h>

#include <malloc.h> int main ( )

{char *name; // вказівник на символ name = (char*) malloc(10);

printf (“ name?\n“); // OK!!! scanf (“%s”, name); // або cin >> name;

char *name1; // вказівник на символ

name1 = “hello”; // OK!!! printf (“%s %s”, name, name1);

char *name2; // вказівник на символ

printf (“ name?“);

//scanf (“%s”, name2); error!!!

// місце під рядок не виділене

return 0;

}

//пример 2: рядок-масив

int main ( ) {

 

char name3 [10];

// рядок-масив

printf (“ name?“);

// OK!!!

scanf (“%s”, name3); //або cin >> name3;

char name4[10]; // рядок-масив strcpy (name4, “hello”); // OK!!! printf (“%s %s\n”, name3, name4);

char name5[10]; // рядок-масив

// name5 = “привіт”; error!!!

}// спроба змінити адресу рядка

char *string = ”Minsk”; char *string1 = ”Minsk”;

// рядки ініціалізуються однією адресою

8

Рядки

Особливості роботи з С-рядками

для представлення с - рядків використовуються масиви елементів типу char, що містять в кінці послідовності значущих символів код '\ 0 ‘

с -рядок обмежена розміром масиву , який виділений для її подання; розмір недінаміческой з -рядки повинен бути заданий тільки константним виразом;

строка може бути проініціалізувати як поелементно символьними значеннями, так і значенням строкового літерала , причому завершальний символ '\ 0 ' формується в цьому випадку в кінці рядка автоматично;

нульова рядок - це рядок , яка починається з 0 -символа '\ 0 ' (її довжина дорівнює нулю , але в пам'яті вона може займати більше одного байта ) ; нульовий вказівник на рядок ( char * p_str = NULL ;) не є еквівалентом нульової рядки;

поточна довжина рядка відстежується в процесі виконання дій над рядком;

при розміщенні у вихідний потік cout імені символьного масиву виводиться не адреса масиву (як для масивів з елементами іншого типу) , а його вміст (до завершального символу '\ 0 ');

для роботи з с- рядками використовуються бібліотечні функції мови С, описані в заголовках <string.h> і < сstring > , однак треба враховувати , що в цих функціях немає контролю за кордонами рядків.

Рядки і вказівники

s

a b c d \0

typedef char ar_char [5];

ar_char s ="abcd"; cout << s << endl; // abcd char *pchar = NULL;

pchar =s; cout << pchar << endl;

cout <<

*pchar << endl;

// a

cout <<

*(pchar +2);

// c

pchar

0

// abcd

parchar =&s

 

parchar

 

ar_char *parchar = NULL;

0

 

 

 

 

// parchar =s;

error!!!, convert from 'ar_char' to 'ar_char (*) '

// pchar =&s;

error!!!

 

 

 

parchar =&s;

// ok!!!

 

 

 

cout<< parchar << endl;

// адреса рядка-масиву

cout << * parchar << endl;

// abcd рядок-масив

cout << ** parchar << endl; // a перший символ рядка-масиву

Слайд не для всех!!!

Соседние файлы в предмете Объектно ориентированное программирование