русс | укр

Мови програмуванняВідео уроки php mysqlПаскальСіАсемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование


Linux Unix Алгоритмічні мови Архітектура мікроконтролерів Введення в розробку розподілених інформаційних систем Дискретна математика Інформаційне обслуговування користувачів Інформація та моделювання в управлінні виробництвом Комп'ютерна графіка Лекції


Символьні масиви


Дата додавання: 2014-11-28; переглядів: 1037.


Найпоширенішим типом масивів у C являються масиви символів. Щоб проілюструвати використання символьних масивів і функцій для їхньої обробки, давайте напишемо програму, яка читає набір рядків тексту і друкує найдовший. Схема є доволі простою:

while (є ще один рядок)

if (він довший за попередній найдовший)

(зберегти його)

(зберегти його довжину)

вивести найдовший рядок

Ця схема робить зрозумілим, що програма природньо поділяється на частини. Одна частина добуває новий рядок, інша зберігає його, а решта керує процесом.

Оскільки речі можна так гарно розділити, було би непогано написати їх саме таким чином. Отже, напишімо спочатку окрему функцію getline, яка добуватме наступний рядок вводу. Ми спробуємо зробимо цю функцію корисною і в інших контекстах. Щонайменше, getlineповинна сигналізувати про можливий кінець вводу; краща конструкція повертала би довжину рядка або нуль, якщо досягнуто кінця вводу. Нуль є прийнятним вказівником кінця вводу, оскільки це ніколи не може бути чинною довжиною рядка. Будь-який рядок тексту має, принаймні, один знак, навіть рядок, що містить тільки символ нового рядка, матиме довжину 1.

Коли ми знайдемо рядок, довший за попередній найдовший, його треба буде десь зберегти. Це наводить на думку про другу функцію, copy, яка копіюватиме новий рядок у надійне місце.

І, нарешті, нам потрібна програма main, для керування getline і copy. Ось, що ми отримали в результаті.

#include <stdio.h>

#define MAXLINE 1000 /* максимальна довжина рядка вводу */

 

int getline(char line[], int maxline);

void copy(char to[], char from[]);

 

/* виводить найдовший рядок вводу */

main()

{

int len; /* довжина поточного рядка */

int max; /* найбільша знайдена довжина */

char line[MAXLINE]; /* поточний рядок вводу */

char longest[MAXLINE]; /* найдовший рядок буде збережено тут */

 

max = 0;

while ((len = getline(line, MAXLINE)) > 0)

if (len > max) {

max = len;

copy(longest, line);

}

if (max > 0) /* було знайдено рядок */

printf("%s", longest);

return 0;

}

 

/* getline: зчитує рядок у s, повертає довжину */

int getline(char s[],int lim)

{

int c, i;

 

for (i=0; i < lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)

s[i] = c;

if (c == '\n') {

s[i] = c;

++i;

}

s[i] = '\0';

return i;

}

 

/* copy: копіює from до to; припускає, що to досить великий */

void copy(char to[], char from[])

{

int i;

 

i = 0;

while ((to[i] = from[i]) != '\0')

++i;

}

Функції getline і copy оголошено на самому початку програми, яку, як ми припускаємо, розміщено в одному файлі.

main і getline комунікують через пару аргументів і повернене значення. В getline, аргументи оголошено рядком

int getline(char s[], int lim);

який вказує на те, що перший аргумент s є масивом, а другий, lim — цілим числом. Зміст вказівки розміру масиву під час оголошення полягає у тому, що це відводить місце для зберігання. Довжину масиву s не обов'язково вказувати в getline, оскільки розмір вже задано в main. getline використовує return, щоб передати значення назад викликачеві, так само як ми це бачили у функції power. У цьому рядку також зазначено, що getline повертає int; оскільки int — це стандартний тип повернення, його можна було би опустити.

Деякі функції повертають корисні значення — інші, такі як copy, використовуються тільки заради їхнього ефекту і не повертають жодних значень. Типом повернення copy є void, що явно вказує на те, що ніякого значення не повертається.

getline додає символ '\0' (нульовий символ, чиє ASCII-значення дорівнює нулю) вкінці створеного нею масиву, для позначення кінця символьного ланцюжка. Цe перетворення так само застосовується в C. Коли ланцюжкова стала на зразок

"hello\n"

з'являється в C-програмі, її збережено як символьний масив, що містить знаки ланцюжка і закінчується символом '\0', щоб позначити кінець ланцюжка.

+-----+-----+-----+-----+-----+------+------+

| h | e | l | l | o | \n | \0 |

+-----+-----+-----+-----+-----+------+------+

Вказівник формату %s функції printf очікує, що відповідний аргумент буде ланцюжком, представлений саме в цій формі. copy також покладається на той факт, що її аргумент вводу закінчується на '\0' і копіює цей знак до виводу.

Мимохідь варто зазначити, що навіть така маленька програма як ця представляє деякі складні проблеми розробки. Наприклад, що повинна зробити main у випадку, коли вона зустріне рядок, більший за встановлене обмеження? getline діє безпечно, через те, що вона перестає набирати знаки, коли масив повний, навіть якщо не було знака нового рядка. Перевіряючи довжину й останній повернений знак, main може визначити чи не був рядок занадто довгим, після чого обійтися з ним, як їй заманеться. Заради стислості, ми проігнорували це питання.

Користувач getline ніяк не може знати наперед, яким за довгим буде введений рядок, тож getline перевіряє на предмет переповнення. Напротивагу, користувач copy вже знає (або може дізнатися) довжину ланцюжків, тож ми вирішили перевірку на помилки до неї не додавати.

Вправа 1-16. Переробіть функцію main програми знаходження найдовшого рядка, щоб вона правильно друкувала довжину рядків вводу довільного розміру і, наскільки це можливо, цілого тексту.

Вправа 1-17. Напишіть програму виводу усіх введених рядків довжиною понад 80 знаків.

Вправа 1-18. Напишіть програму, яка би вилучала кінцеві пробіли і табуляцію з кожного рядка вводу й усувала повністю порожні рядки.

Вправа 1-19. Напишіть функцію reverse(s), яка б обертала символьний ланцюжок s задом на перед. Використайте її для створення програми для обертання свого вводу по одному рядкові за раз.


<== попередня лекція | наступна лекція ==>
Аргументи - виклик за значенням | Зовнішні змінні й область дії


Онлайн система числення Калькулятор онлайн звичайний Науковий калькулятор онлайн