Як дізнатися кількість символів у рядку CЯк дізнатися кількість символів у рядку C

0 Comment

C++. Масиви. Частина 4. Приклади розв’язування задач на рядки символів

Масиви. Частина 4. Приклади розв’язування задач на рядки символів

У даній темі розв’язуються деякі задачі з використанням рядків символів. При розв’язку цих задач використовуються деякі стандартні функції з бібліотеки “ string.h “.

Тема продовжує вивчення тем: одновимірні масиви та багатовимірні масиви .

Зміст

  • 1. Задачі на пошук символу в рядку. Приклади
  • 2. Задачі на заміну символів. Приклади
  • 3. Задачі на визначення позиції заданого символу. Приклади
  • 4. Задачі на перетворення тексту. Приклади
  • 5. Задачі на підрахунок кількості символів в тексті. Приклади
  • 6. Сортування рядків символів методом вставки. Приклад
  • Зв’язані теми

Пошук на інших ресурсах:

1. Задачі на пошук символу в рядку. Приклади

Приклад 1. Задано рядок символів. Визначити, чи є заданий символ c в цьому рядку символів.

// пошук символу в рядку char S[50]; // рядок символів char c; // шуканий символ int i; bool f_is; // f_is=true - символ є в рядку, інакше f_is=false // ввід рядка S // . // ввід символу c // . for (i=0; iif (S[i]==c) < f_is = true; // символ c є в рядку S break; > if (f_is) label1->Text = "Символ " + c.ToString() + " є в рядку"; else label1->Text = "Символу " + c.ToString() + "немає в рядку";

У даному прикладі для визначення довжини рядка S використовується функція

Ця функція повертає кількість символів у рядку без врахування останнього символу ‘\0’ . Щоб використовувати цю функцію в Visual C++ потрібно на початку файлу перед задаванням простору імен підключити одну з бібліотек або . Для цього потрібно набрати один з рядків:

Приклад 2. Нехай задано деякий текст. Обчислити, скільки разів повторюється наперед заданий символ a .

// знаходження кількості входжень символу в рядку char S[50]; // рядок символів char a; // заданий символ int i; int k; // результат - кількість входжень символу a в рядку S // ввід рядка S // . // ввід символу a // . k = 0; // на початку обнулити лічильник k for (i=0; iif (S[i]==a) k++; // збільшити лічильник на 1

Приклад 3. У даному тексті порахувати кількість символів ‘+’ та ‘‘ .

// підрахунок кількості символів у рядку char str[50]; // заданий текст int i; int n_p; // результат - кількість символів '+' int n_m; // результат - кількість символів '-' // ввід масиву str // . n_p = 0; n_m = 0; for (i=0; iif (str[i] == '+') n_p++; if (str[i] == '-') n_m++; >
2. Задачі на заміну символів. Приклади

Приклад 1. У заданому тексті замінити всі символи ‘+’ на ‘-‘ .

// заміна символів char str[50]; // заданий текст int i; // ввід тексту // . for (i=0; iif (str[i] == '+') str[i] = '-';

Приклад 2. Задано декілька рядків тексту (двовимірний масив символів). Замінити всі символи ‘+’ на ‘-‘ .

// заміна символів в масиві рядків char str[5][50]; // заданий масив, що містить 5 рядків int i, j; // ввід масиву з 5 рядків // . for (i=0; ifor (j=0; jif (str[i][j] == '+') str[i][j] = '-';

Приклад 3. У заданому тексті замінити всі символи ‘+’ на ‘+++’ .

Дана задача легко вирішується з допомогою введення допоміжного масиву у текст програми.

// заміна символів '+' на '+++' char str[50]; // заданий текст int i, j; char str2[150]; // допоміжний масив // ввід масиву str // . j = 0; // поточна позиція в масиві str2 for (i=0; iif (str[i] == '+') < str2[j++] = '+'; str2[j++] = '+'; str2[j++] = '+'; > else < str2[j] = str[i]; j++; >// додати символ кінця рядка str2[j] = '\0'; strcpy(str, str2); // скопіювати str2 в str 

Приклад 4. У заданому тексті замінити послідовність символів ‘…’ на ‘ . ‘ .

// заміна символів '. ' на '.' char str[50]; // заданий текст int i, j; char str2[50]; // допоміжний масив int d; // ввід масиву str // . j = 0; // поточна позиція в масиві str2 d = strlen(str); // довжина рядка str for (i=0; iif (iif ((str[i]=='.')&&(str[i+1]=='.')&&(str[i+2]=='.')) < str2[j++] = '.'; i+=2; > else < str2[j++] = str[i]; >> else < str2[j++] = str[i]; >// додати символ кінця рядка str2[j] = '\0'; strcpy(str, str2); // скопіювати допоміжний масив у вихідний

Так само, як і в попередньому прикладі вводиться допоміжний масив. У вихідному масиві відбувається перевірка на послідовність символів ‘…’

if ((str[i]=='.')&&(str[i+1]=='.')&&(str[i+2]=='.'))

Якщо така послідовність знайдена, то в допоміжному масиві додається ‘ . ‘

В іншому випадку, символ з вихідного масиву копіюється у допоміжний.

У лістингу використовується функція strcpy() з бібліотеки (або cstring ), яка копіює один рядок в інший.

3. Задачі на визначення позиції заданого символу. Приклади

Приклад 1. Задано деякий рядок символів. У заданому тексті визначити позицію першої крапки ‘ . ‘ . Вважати, що перший символ в рядку має позицію 1.

// пошук першого входження символу в тексті char str[50]; // заданий текст int i; int pos; // шукане значення - позиція // ввід масиву str // . pos = -1; for (i=0; iif (str[i]=='.') < pos = i+1; // запам'ятати позицію break; // вихід з циклу, подальше виконання циклу не має сенсу > if (pos == -1) label2->Text = "Символ відсутній в тексті."; else label2->Text = pos.ToString();

Приклад 2. Задано деякий рядок символів. Визначити позиції останньої крапки ‘ . ‘ в тексті.

// пошук останнього входження символу в тексті char str[50]; // заданий текст int i; int pos; // шукане значення - позиція // ввід масиву str // . pos = -1; for (i=strlen(str)-1; i>=0; i--) // перегляд рядка з кінця до початку if (str[i]=='.') < pos = i+1; // запам'ятати позицію break; // вихід з циклу, подальше виконання циклу не має сенсу > if (pos == -1) label2->Text = "Символ відсутній в тексті."; else label2->Text = pos.ToString();
4. Задачі на перетворення тексту. Приклади

Приклад 1. Задано деякий рядок символів. Створити новий рядок, який утворено із даного читанням з кінця до початку.

// обернення рядка char str[50]; // заданий рядок char str2[50]; // результуючий рядок int i; int d; // ввід масиву str // . d = strlen(str); for (i=0; i// додати символ кінця рядка str2[d] = '\0';

Приклад 2. Задано слово. Перевірити, чи читається це слово зліва направо і навпаки.

// перевірка рядка char str[50]; // заданий рядок int i; int d; bool f_yes; // результуюча змінна // ввід масиву str // . d = strlen(str); f_yes = true; for (i=0; i// перегляд рядка з кінця до початку if (str[i] != str[d-i-1]) f_yes = false; if (f_yes) label1->Text = "Рядок читається зліва направо і навпаки"; else label1->Text = "Рядок не читається зліва направо і навпаки";

Приклад 3. Перевірити, чи є дані слова оберненими одне до одного, тобто перше читається зліва направо так само, як друге справа наліво.

// перевірка на оберненість двох слів char str1[50]; // рядок 1 char str2[50]; // рядок 2 int i; int d1, d2; bool f_yes; // результуюча змінна // ввід масивів str1, str2 // . d1 = strlen(str1); d2 = strlen(str2); f_yes = true; if (d1 == d2) // перевірка довжин рядків на співпадіння < for (i=0; iif (str1[i] != str2[d1-i-1]) f_yes = false; > else f_yes = false; if (f_yes) label1->Text = "Слова є оберненими один до одного"; else label1->Text = "Слова не є оберненими один до одного";
5. Задачі на підрахунок кількості символів в тексті. Приклади

Приклад 1. Задано рядок символів. Підрахувати кількість символів ‘+’ у цьому рядку.

// підрахунок кількості символів '+' у рядку char str[50]; int i; int k; // результат - кількість символів // ввід рядка str // . k = 0; // онулити лічильник for (i=0; iif (str[i] == '+') k++; // вивід результату label1->Text = k.ToString();

Приклад 2. Задано декілька рядків символів. Підрахувати кількість символів ‘ – ‘ у цих рядках.

// підрахунок кількості символів '-' у масиві з 6 рядків char s[6][50]; int i, j; int k; // результат - кількість символів // ввід рядків s // . k = 0; // онулити лічильник // обчислення k for (i=0; ifor (j=0; jif (s[i][j] == '-') k++; // вивід результату label1->Text = k.ToString();

Приклад 3. Задано рядок символів. Підрахувати кількість слів у цьому рядку. Вважати, що слова розділяються одним з символів ‘ ‘ (пробіл), ‘ , ‘ (кома), ‘ . ‘ (крапка).

// підрахунок кількості слів у рядку char s[50]; // рядок символів int i; int k; // результат - кількість слів bool f; // допоміжна змінна - визначає кінець попереднього слова // ввід рядку s // . k = 0; // онулити лічильник f = true; // обчислення k for (i=0; iif ((s[i] == ' ')||(s[i]==',')||(s[i]=='.')) < f = true; // кінець слова > else < if (f) < // початок нового слова k++; f = false; > > // вивід результату label1->Text = k.ToString();

У вищенаведеному прикладі з допомогою допоміжної змінної f визначається кінець попереднього слова. Якщо

тоді був кінець попереднього слова. Інакше, починається нове слово і лічильник k збільшується на 1.

Приклад 4. Задано декілька рядків символів (двовимірний масив символів). Підрахувати кількість слів, що починаються з літер ‘a’ або ‘A’ . Вважати, що слово закінчується на один з символів ‘ ‘ (пробіл), ‘ . ‘ (крапка) або ‘ , ‘ (кома).

// підрахунок кількості слів у масиві рядків char s[5][50]; // масив рядків символів int i, j; int k; // результат - кількість слів bool f; // допоміжна змінна - визначає кінець попереднього слова // ввід масиву рядків s // . k = 0; // онулити лічильник // обчислення k for (i=0; i// перебір рядків < f = true; for (j=0; jif ((s[i][j] == ' ')||(s[i][j]==',')||(s[i][j]=='.')) < f = true; // кінець слова > else < if (f) < // початок нового слова if ((s[i][j]=='a')||(s[i][j]=='A')) k++; f = false; > > > // вивід результату label1->Text = k.ToString();
6. Сортування рядків символів методом вставки. Приклад

Приклад. Задано декілька рядків символів. Посортувати ці рядки в алфавітному порядку.

// сортування масиву рядків методом вставки char s[5][50]; // масив рядків символів int i, j; char ts[50]; // допоміжний рядок // ввід масиву рядків s // . for (i=0; ifor (j=i; j>=0; j--) if (strcmp(s[j],s[j+1])>0) < // обміняти рядки місцями strcpy(ts, s[j]); strcpy(s[j], s[j+1]); strcpy(s[j+1], ts); >

У вищенаведеному лістингу для порівняння рядків у лексикографічному порядку використовується функція strcmp() з бібліотеки ( cstring ). Функція має загальну форму:

int strcmp(string1, string2);

де string1 , string2 – рядки, що порівнюються.

Функція повертає число:

  • >0 , якщо string1 слідує після string2 в лексикографічному порядку;
  • =0 , якщо рядки однакові;
  • , якщо string1 слідує перед string2 в лексикографічному порядку.

Зв’язані теми

Урок №82. Рядки C-style

На уроці №60 ми визначили термін «рядок», як набір послідовних символів (наприклад, Hello, world! ). Рядки — це основний спосіб роботи з текстом в мові C++, а std::string спрощує цю взаємодію.

Сучасний C++ підтримує два різних типи рядків:

std::string (як частина Стандартної бібліотеки мови С++);

рядки C-style (успадковані від мови Cі).

std::string реалізований за допомогою рядків C-style.

Рядки C-style

Рядок C-style — це простий масив символів, який використовує нуль-термінатор. Нуль-термінатор — це спеціальний символ (ASCII-код якого дорівнює 0 ), який використовується для позначення кінця рядку.

Для визначення рядку C-style необхідно просто оголосити масив типу char і ініціалізувати його літералом (наприклад, string ):

Хоча string має лише 6 букв, мова C++ автоматично додає нуль-термінатор в кінець рядку (нам не потрібно додавати його вручну). Відповідно, довжина масиву mystring дорівнює 7!

Як приклад розглянемо наступну програму, яка виводить довжину рядка, а потім ASCII-коди всіх символів літералу string :

Результат виконання програми:

string has 7 characters.
115 116 114 105 110 103 0

Нуль в кінці є ASCII-кодом нуль-термінатора, який був доданий в кінець рядка.

При такому оголошенні рядків рекомендується використовувати квадратні дужки [] , щоб дозволити компілятору визначати довжину масиву самостійно. Таким чином, якщо ви зміните рядок пізніше, вам не доведеться вручну змінювати значення довжини масиву.

Зверніть увагу, що рядки C-style слідують всім тим же правилам, що і масиви. Це означає, що ви можете ініціалізувати рядок при створенні, але після цього не зможете присвоювати йому значення за допомогою оператора присвоювання:

Це те ж саме, якби ми зробили наступне:

Оскільки рядки C-style є масивами, то ви можете використовувати оператор [] для зміни окремих символів в рядку:

Результат виконання програми:

При виведенні рядка C-style, std::cout виводить символи до тих пір, поки не зустріне нуль-термінатор. Якби ви випадково перезаписали нуль-термінатор в кінці рядка (наприклад, присвоївши що-небудь для mystring[6] ), то ви б не тільки отримали всі символи рядка, але std::cout також вивів би все, що знаходиться в сусідніх комірках пам’яті до тих пір, поки він не дійшов би до 0!

Зверніть увагу, що це нормально, якщо довжина масиву більше рядка, якого він (масив) зберігає:

char name [ 15 ] = “Max” ; // використовується тільки 4 символи (3 букви + нуль-термінатор)

В цьому випадку рядок Max виведеться на екран, а std::cout зупиниться на нуль-термінаторі. Решта символів в масиві будуть проігноровані.

Рядки C-style і std::cin

Є багато випадків, коли ми не знаємо заздалегідь, наскільки довгим буде наш рядок. Наприклад, розглянемо проблему написання програми, де ми просимо користувача ввести своє ім’я. Наскільки довгим воно буде? Це невідомо доти, доки користувач його не введе!

У такому випадку ми можемо оголосити масив розміром більше, ніж нам потрібно:

char name [ 255 ] ; // оголошуємо достатньо великий масив (для зберігання 255 символів)

У вищенаведеній програмі ми оголосили масив з 255 символів, припускаючи, що користувач не введе ім’я більше 255 символів. Хоча це і поширена практика, але вона не дуже ефективна, оскільки користувачу нічого не перешкоджає ввести ім’я, яке містить більше 255 символів (випадково або навмисно).

Набагато краще зробити наступне:

char name [ 255 ] ; // оголошуємо достатньо великий масив (для зберігання 255 символів)

Виклик cin.getline() прийматиме до 254 символів в масив name (залишаючи місце для нуль-термінатора!). Будь-які зайві символи будуть проігноровані. Таким чином, ми можемо гарантувати, що масив не буде переповнено!

Керування рядками C-style

Мова C++ надає безліч функцій для керування рядками C-style, які підключаються за допомогою заголовкового файлу cstring. Ось декілька найбільш корисних функцій:

Функція strcpy_s() копіює вміст одного рядка в інший. Найчастіше це використовується для присвоювання значень рядку:

Тим не менше, використання функції strcpy_s() може легко викликати переповнення масиву, якщо не бути обережним! У наступній програмі довжина масиву dest менше довжини рядка, який ми копіюємо, тому в результаті ми отримаємо переповнення масиву:

char dest [ 5 ] ; // зверніть увагу, що довжина масиву dest всього 5 символів!

Функція strlen() повертає довжину рядка C-style (не враховуючи нуль-термінатор):

char name [ 15 ] = “Max” ; // використовується тільки 4 символи (3 букви + нуль-термінатор)
std :: cout << name << " has " << sizeof ( name ) << " characters in the array.\n" ;

Результат виконання програми:

My name is Max
Max has 3 letters.
Max has 15 characters in the array.

Зверніть увагу на різницю між функцією strlen() і оператором sizeof. Функція strlen() виводить кількість символів ДО нуль-термінатора, тоді як оператор sizeof повертає розмір цілого масиву, незалежно від того, що в ньому знаходиться.

Ось ще декілька корисних функцій керування рядками C-style:

функція strcat() — додає один рядок до іншого (небезпечно);

функція strncat() — додає один рядок до іншого (з перевіркою розміру місця призначення);

функція strcmp() — порівнює два рядки (повертає 0 , якщо вони рівні);

функція strncmp() — порівнює два рядки до певної кількості символів (повертає 0 , якщо до вказаного символу не було відмінностей).