Приклад виконання завдання з обробки рядків
Ввести символьний рядок і розділити її на частини фіксованої довжини. Вивести на екран отримані частини рядка "в стовпчик", тобто кожну частину з нового рядка дисплея. Нехай в кожній частині рядка буде не більше трьох символів.
Текст програми:
/* Динамічні символьні масиви, покажчики і рядки */
#include <stdio.h>
#include <string.h>
void main()
{
int LenMax, Len = 0 ;
char *h, *input;
int ks; /* Кількість "частин" рядка */
/* Покажчик на масив покажчиків на частини: */
char **c;
int n = 0 ;
int j = 0;
int i ;
printf ("\n Введіть максимальний розмір рядкa : ");
scanf("%d", &LenMax);
/* Виділити пам'ять для рядка, що вводиться: */
input = (char *)malloc (LenMax);
printf ("\n Введіть рядок:");
/* Видалення символу '\n' з вхідного потоку: */
getchar() ;
/* Читання рядка: */
while ((*(input+Len++)=getchar()) !='\n');
Len --;
/* Len – кількість введених символів */
/* Додати ознаку кінця рядка: */
* (input+Len) =' \0 ';
/* Виділити пам'ять для введеного рядка: */
h=(char *)malloc(Len+1);
/* Копіюємо інформацію з початкового рядка */
while (* (h+j++)=* input++);
/* Видалення з пам'яті початкового рядка: */
free (input);
ks = (Len+2)/3; /* Кількість частин */
c = (char **)calloc (ks, sizeof(char *));
/* Ділення рядка на ks "частин" */
for(j = 0; j < ks; j++)
{ /* Пам'ять для частини: */
*(c+j) = (char *)malloc(4);
for (i = 0; (i < 3 && *(h+n) ); i++)
*(*(c+j) +i)= *(h+ n++);
*(*(c+j)+i)='\0';
}
/* Видалення з пам'яті обробленого рядка: */
free (h);
/* Виведення "частин" початкового рядка */
for (j = 0; j < ks; j++)
{
printf("\n %s", *(c+j) );
}
/* Звільнити пам'ять від динамічних масивів:*/
for (j = 0; j < ks; j++)
free (*(c+j)); free (c);
}
Приклад виконання програми:
Введіть максимальний розмір рядка: 60
Введіть рядок: World_Wide_Web!
Wor
ld_
Wid
e_W
eb!
В програмі необхідно звернути увагу на такі особливості.
Читання символів вхідного потоку виконується двома різними функціями. В циклі (закінченням якого служить поява символу '\ n ') за допомогою getchar( ) читається послідовність символів в область пам'яті, що адресується покажчиком char* input. Перед цим за допомогою функції scanf("%d",&LenMax) прочитується значення LenMax. Тут виникає одна незручність. Функція scanf() при введенні "залишає" у вхідному потоці ознаку '\n' кінця послідовності, що вводиться. Якщо потім йде введення за допомогою функції getchar(), то першим зчитаним значенням буде '\n'. Саме тому перед циклом за допомогою getchar() з вхідного потоку видаляється непотрібний символ '\n'.
Наступна особливість – відсутність індексованих змінних. Для доступу до елементів масивів, в яких розміщуються символи рядків, використовується розіменування покажчиків і виразів з покажчиками, наприклад: *(*(c+j)+i). Як вправа рекомендується написати варіант програми з індексованими змінними для доступу до окремих символів рядків.
Ще одна особливість – відсутність звернень до стандартних функцій для роботи з рядками. Програму можна спростити, якщо використовувати функції для визначення довжини рядків strlen(), для копіювання рядків strcpy() і ін.
Питання для самоконтролю.
Дайте визначення рядка? Який символ в С відмічає кінець рядка?
Що означає термін конкатенація?
Як записується символьна літеральна константа? Рядкова літеральна константа?
Що не пишеться в назві рядка, якщо вона передається якій-небудь функції обробки рядків.
Чому важливо очищувати вхідний буфер після форматного введення?
Напишіть оператор який створює змінну-рядок, яка може містити до 80 символів. Назвіть Line. Char Line[80];
Де знаходяться прототипи функцій обробки рядків?
Яка функція використовується для копіювання перших n символів із одного рядка в інший?
В чому різниця між функціями strchr() i strrchr()?
За допомогою якого ключового слова можна визначити синонім типу?