Доповнення до лекції „рядки”.
Задачі системного програмування часто пов’язані з обробкою символьних масивів (рядків) невизначеної довжини. Саме для їх обробки частіше всього використовуються покажчики.
Символьний рядок – це масив типу char, який закінчується символом \0.
В мові Сі є ряд засобів оголошення, ініціалізації і присвоєння нових значень рядкам. Розглянемо деякі з них.
При оголошенні рядків можна використовувати:
за зоною дії рядків: зовнішні (оголошені в програмному файлі) і внутрішні (оголошені в функції) масиви;
покажчики – константи і покажчики – змінні;
масиви символьних значень одновимірні і багатовимірні;
межі масивів символьних даних і масивів покажчиків на дані типу 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 – двовимірний вільний символьний масив (масив покажчиків) з кількістю рядків, заданих неявно при ініціалізації значень його рядків.
Об’єм ОП для покажчиків і рядків визначається таким чином:
Для символьних масивів, межі яких задані явно, виділяється ОП, яка дорівнює запрошеній кількості символів масиву, в програмі це масиви S1 і S4;
Для символьних масивів, в яких межі не вказані, виділяється ОП, яка визначається кількістю символів і ініціалізацією рядка ( в програмі – S2, S5);
Якщо заданий скалярний покажчик на дані типу char і ініціалізовано значення рядка (S3, S6), ОП виділяється для покажчика і для значення рядка;
Для неініціалізованого скалярного покажчика виділяється ОП тільки для самого покажчика, можна виділити ОП для рядка і при цьому сформувати значення покажчика за допомогою функції malloc або привласненням покажчику значення адреси конкретної рядкової константи ( в тексті – S11);
Для масиву покажчиків з заданою кількістю елементів і ініціалізованими значеннями рядків (S7, S9) ОП виділяється:
для масиву покажчиків;
для ініціалізованих значень рядків;
Для масивів покажчиків, в яких межі (кількість елементів масиву) не вказані і значення рядків ініціалізовані (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’.