ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 22.12.2021

Просмотров: 115

Скачиваний: 2

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

Доповнення до лекції „РЯДКИ”.


Задачі системного програмування часто пов’язані з обробкою символьних масивів (рядків) невизначеної довжини. Саме для їх обробки частіше всього використовуються покажчики.

Символьний рядок – це масив типу char, який закінчується символом \0.

В мові Сі є ряд засобів оголошення, ініціалізації і присвоєння нових значень рядкам. Розглянемо деякі з них.

При оголошенні рядків можна використовувати:

  1. за зоною дії рядків: зовнішні (оголошені в програмному файлі) і внутрішні (оголошені в функції) масиви;

  2. покажчики – константи і покажчики – змінні;

  3. масиви символьних значень одновимірні і багатовимірні;

  4. межі масивів символьних даних і масивів покажчиків на дані типу char, задані явно (значення) і непрямо (пусті).

Приклад різних засобів оголошення рядків і масивів рядків поданий у лістингу. В ньому значення рядків виводяться за допомогою масиву покажчиків р і функцій виведення: printf і puts.

/* засоби оголошення і ініціалізації символьних масивів*/

#include <stdio.h>

#include <conio.h>

#define n20

//зовнішні змінні:

char S1[n] = “рядок1”; //масив з явною межею

char S2[ ] = “рядок2”; //масив з неявною межею

char *S3 = “рядок3”; //скалярний покажчик

void main()

{ int i;

//внутрішні змінні:

static char S4[n] = “рядок4”; //м-в з явною межею

static char S5[ ] = “рядок5; //м-в з неявною межею

char *S6 = “рядок6 //скалярний покажчик

//Одновимірний масив покажчиків на рядки з явною межею:

char *S7[3]={“РядокS7_0”,“ РядокS7_1”,“ РядокS7_2”};

//Одновимірний масив покажчиків на рядки з неявною межею:

char *S8[ ]={“ РядокS8_0”,“ РядокS8_1”,“ РядокS8_2”};

//Двовимірний масив покажчиків на рядки з явною межею:

char *S9[2][2]={{“ РядокS9_0,0”,“ РядокS9_0,1”},

{“РядокS9_1,0”,“ РядокS9_1,1”}};

//Двовимірний масив покажчиків на рядки з неявною межею:

char *S10[][2]={{“ РядокS10_0,0”,“ РядокS10_0,1”},

{“РядокS10_1,0”,“ РядокS10_1,1”}};

char *S11; //неініціалізований покажчик;

char *p[21]; //неініціалізований масив покажчик;

S11 = “Рядок11”; //присвоєння значення покажчику.

clrscr();

//Заповнення р-масива покажчиків значеннями:

p[0]=S1; p[1]=S2; p[2]=S3; p[3]=S4; p[4]=S5; p[5]=S6; p[6]=S7[0]; p[7]=S7[1]; p[8]=S7[2];

p[9]=S8[0]; p[10]=S8[1]; p[11]=S8[2];

p[12]=S9[0][0]; p[13]=S9[0][1]; p[14]=S9[1][0]; p15=S9[1][1];

p[16]=S10[0][0]; p[17]=S10[0][1]; p[18]=S10[1][0];

p[19]=S10[1][1]; p[20]=S11;


printf (“\nПочаток виведення”);

puts (“Рядків\n”);

for (i=0;i<21;i++){

printf(“%S”,p[i]);

puts(p[i]);}

printf(“\nДля завершення програми натисніть будь-яку клавішу\n”);

getch();

}

В програмі використовуються: S1, S2, S3 зовнішні змінні, інші – внутрішні (локальні). В масивах S1, S4, S7, S9, p межі задано явно, а в масивах S2,S3,S5,S6,S8 – непрямо; S3,S6,S11 – скалярні покажчики – змінні на дані типу char.

Масив S7 – одновимірний вільний символьний масив (масив покажчиків) із заданою кількістю його рядків (покажчиків). Масив S9 – двовимірний вільний символьний масив (масив покажчиків) з кількість рядків і стовпців, заданих явно при його оголошенні.

Масив S10 – двовимірний вільний символьний масив (масив покажчиків) з кількістю рядків, заданих неявно при ініціалізації значень його рядків.



Об’єм ОП для покажчиків і рядків визначається таким чином:

  1. Для символьних масивів, межі яких задані явно, виділяється ОП, яка дорівнює запрошеній кількості символів масиву, в програмі це масиви S1 і S4;

  2. Для символьних масивів, в яких межі не вказані, виділяється ОП, яка визначається кількістю символів і ініціалізацією рядка ( в програмі – S2, S5);

  3. Якщо заданий скалярний покажчик на дані типу char і ініціалізовано значення рядка (S3, S6), ОП виділяється для покажчика і для значення рядка;

  4. Для неініціалізованого скалярного покажчика виділяється ОП тільки для самого покажчика, можна виділити ОП для рядка і при цьому сформувати значення покажчика за допомогою функції malloc або привласненням покажчику значення адреси конкретної рядкової константи ( в тексті – S11);

  5. Для масиву покажчиків з заданою кількістю елементів і ініціалізованими значеннями рядків (S7, S9) ОП виділяється:

    • для масиву покажчиків;

    • для ініціалізованих значень рядків;

  6. Для масивів покажчиків, в яких межі (кількість елементів масиву) не вказані і значення рядків ініціалізовані (S8, S10), ОП виділяється:

    • для масивів покажчиків, кількість елементів якого дорівнює кількості ініціалізованих значень рядків;

    • для ініціалізованих значень рядків;

7.Для масиву покажчиків з заданою кількістю елементів (це масив р), в якому значення рядків не ініціалізовані, ОП виділяється тільки для покажчиків.

Ініціалізовані рядкові константи розміщуються статично в ОП в тому випадку, якщо рядок розташований в якості фактичного параметра функції. Наприклад:

printf (“\nПочаток виведення”); puts (“строк\n”);

Це визначення рядка аналогічно використанню в списку даних функцій виведення імені покажчика ініціалізованого рядка. Наприклад: printf(“%S”,p[i]); puts(p[i]);

При оголошенні символьного масиву (без використання *-символа покажчика) ім’я масиву є покажчиком-константою; це масиви S1, S2, S4, S5. Це синоніми адреси 0-го елемента масиву, наприклад:

S1==&S1[0]; значення цих констант (S1, S2 і т.д.) не можна змінювати в процесі виконання програми.

Тобто, недопустимо S1=S4; S2=S5; S1++;

Але можна використовувати це значення в арифметичних виразах. Наприклад, для отримання адреси визначеного символа масиву:

S1+1; S1+i.

При оголошенні символьних масивів за допомогою скалярних покажчиків ім’я покажчика (S3,S6,S11) є покажчиком–змінною. Його можна використовувати в виразах і в правій частині операторів присвоєння. Тобто, для них допустимі, наприклад:

S3=S1; S3=S2; S6=S1; S11=S2; S3++;

Ім’я статичного масиву покажчиків – це покажчик-константа: S7, S8, S9, S10,p. В масиві покажчиків елементи масиву – це покажчики – змінні. Наприклад: S7[i], S8[i], S9[i][j], S10[i][j], P[2]. Їх значення можна змінювати.

До елементів рядків можна звернутись як до елементів масиву символів. Наприклад, привласнити елементам нові значення можна в вигляді: S6[3]=’A’; *(S6+3)=’A’; S8[0][1]=’C’; S9[0][0][3]=’B’.


Вільні масиви рядків.

ВІЛЬНИЙ МАСИВце двовимірний масив (матриця), розмір кожного рядка якого може бути різним. Вільні масиви формуються за допомогою масивів покажчиків. Масиви покажчиків можуть бути статичними або динамічними.

Наприклад, зовнішній (глобальний) або локальний вільні масиви можна оголосити у вигляді:

char *mes[]={“январь”, “февраль”, “март”, ... “декабрь”};

main ()

{ static char *mn[]={“Анна”, “Мария”, “Надежда”};

char *name_list[20];

В прикладі кількість зовнішнього масиву покажчиків mes і локального mn визначається кількістю ініціалізованих рядків, а кількість елементів одновимірного масиву покажчиків name_list задано явно.

При цьому зовнішній масив mes і локальний масив mn ініціалізовані рядковими константами різної довжини. Цим масивам виділяється ОП:

  • Для одновимірного масиву покажчиків; кількість елементів цього масиву визначається при його ініціалізації – за кількістю його символьних рядків; кожен покажчик містить адресу початку відповідної символьного рядка;

  • Для двовимірного символьного масиву з рядками різної довжини. Такі масиви можна розглядати як одновимірні масиви, які складаються із рядків різної довжини. Наприклад, масив mes можна розглядати як одновимірний масив із 12 рядків різної довжини.

При оголошенні масиву name_list виділяється ОП лише для розміщення 20 покажчиків на рядки. Ці покажчики не містять значень – адрес початку відповідних рядків.

ОП для рядків не виділена. В процесі виконання програми вона може бути виділена, наприклад, за допомогою функції malloc. name_list[i]=(char*)malloc(m);

де, iномер покажчика в масиві покажчиків name_list;

mкількість символів в рядку, на яку вказує name_list[i].

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

Схематично взаємозв’язок покажчиків і рядків масиву mn можна подати у вигляді:

&mn

mn[i]


Рядки змінної довжини

mn

mn[0]


А

Н

Н

А

0


mn+1

mn[1]


М

А

Р

И

Я

0


mn+2

mn[2]


Н

А

Д

Е

Ж

Д

А

0

адреса mn[i] значення mn[i]

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

Таким чином, виділення ОП даним вільних масивів рядків може бути при їх оголошенні і ініціалізації або динамічно, в процесі виконання програми, за допомогою функції malloc.

Приклад програми з динамічним виділенням ОП масиву вільних рядків. За допомогою цієї програми формується масив вільних рядків за допомогою *tab[10] – статичного масиву покажчиків на рядки. За запитом з клавіатури вводяться значення:


-kкількість введених рядків;

-str імена за допомогою функції scanf;

#include<stdio.h>

#include<alloc.h>

#include<string.h>

#include<conio.h>

void main()

{ int k, i, res; //tab – статичний масив покажчиків

char *str = (char*)malloc(80), * tab[10];

clrscr();

printf(“\nВкажіть кількість імен, не більше 10:”);

scanf(“%d”, &k); //введення кількості імен

printf(“Кількість імен=%d\n”,k); // виведення кількості імен

for(i=0; i<k; i++)

{ printf (“Введіть %d-e ім’я: ”,i+1);

res = scanf(“%s, str”); //введення рядка

if (res==1) //контроль успішності введення рядка

{ tab[i]=(char*) malloc(strlen(str)+1); //виділення ОП рядку

strcopy (tab[i], str); //копіювання рядка в динамічний масив

}

}

printf(“\n Введені такі імена:\n”);

for(i=0; i<k; i++)

{ printf(“%s”, tab[i]); //виведення і-го рядка

free(tab[i]);} //вивільнення ОП і-го рядка

free(str); //вивільнення ОП str

printf(“\n Для завершення натисніть будь-яку клавішу\n”);

getch();

}

В програмі використовуються змінні:

- tab – ім’я статичного масиву із 10 покажчиків на дані типу char

- tab[i] – елемент масиву tab буде зберігати значення покажчика на початок значення і-го рядка

- str – скалярний покажчик-змінна на дані типу char

- i – змінна для перебору номерів рядків масиву tab

- k – кількість рядків динамічного масиву

- res – змінна для визначення вдалого введення рядка.

Для створення вільного масиву рядків в режимі діалогу з клавіатури вводиться значення k – кількість рядків вільного масиву. Воно повинно бути не більше 10-ти – кількість елементів tab – масиву покажчиків. Потім воно виводиться на екран. Для формування масиву із k вільних рядків організується перебір номерів рядків по і від 0 до (k-1). Для кожного і-го рядка:

  1. в режимі діалогу змінну str вводиться чергове ім’я;

  2. для формування чергового і-го рядка вільного масиву:

А. з допомогою функції malloc виділяється ОП на кількість введеного рядка str, яке визначається за допомогою функції strlen.

Б. адреса розміщення елементів і-го рядка розміщується в tab[i] – елемент масиву покажчиків за допомогою функції malloc.

В. в ОП, виділену для і-го рядка, копіює значення str чергового введеного рядка за допомогою функції strcopy.

Після завершення створення вільного масиву рядків відбувається виведення його значень на екран і вивільнення ОП, виділеної кожному і – му рядку. Для цього перебираються значення і-номерів рядків масиву від 0 до (k-1). Кожне значення виводиться на екран за допомогою printf(“%s”, tab[i]); для кожного і-го рядка ОП вивільняється за допомогою оператора free(tab[i]).

6