У візуальному режимі С++ Builder зазвичай використовуються рядки типу AnsiString,що визначені у бібліотеці візуальних компонентів (VCL), яка автоматично підключається до програмного модуля користувача.
Описувати їх можна, використовуючи службове слово AnsiString, або String (з великої літери). Наприклад, ідентичними будуть описи:
AnsiString str;
та
String str;.
В описі рядка його можна відразу ініціювати, наприклад:
AnsiString str = “Это текстовая строка”;.
Для доступу до символів використовуються індекси, підрахунок яких починається з одиниці, а не з нуля (як у символьних масивах). Наприклад, якщо для вищенаведеного рядка написати str[l], то це буде літера «Э».
Рядки можна об’єднати в масиви, наприклад, у записі
AnsiString s[20];
буде масив з 20 рядків.
Доступ до символів масиву здійснюється за допомогою двох індексів. Перший указує номер рядка в масиві, а другий — номер символа в рядку. Наприклад, s[5][l] — це перший символ у п’ятому рядку.
Для цих рядків визначені операції присвоювання «=», «+=», операція конкатенації(«склеювання») «+» і операції відношення (порівняння): «-=>, «!=», «>», «>=», «<», *<=*>. Порівняння відбувається з урахуванням регістра. При порівнянні двох рядків ця операція здійснюється зліва направо для символів з однаковими індексами обох рядків. Порівнюються коди символів. Якщо ці коди виявилися однаковими, то відбувається порівняння наступних двох символів, доки не будуть зафіксовані два символи з різними кодами. Більшим є те слово, код символа якого має більше значення. Коди символів збільшуються в міру віддалення символа від початку алфавіту, наприклад, у стандартахANSI. Заголовні латинські літери від А до Z мають коди від 65 до 90, рядкові — від 97 до122. Російські заголовні літери мають коди від А до Я 192-223, а рядкові — від 224 до 255. Тому при порівнянні слів «Стол» і «Стул» буде більше слово «Стул», тому що перші дві пари літер у них однакові, а в третій парі код літери «у» = 243 більше коду літери «о» = 238.
Тип AnsiString використовується в багатьох властивостях компонентів C++Builder,наприклад, Text, Caption тощо.
Для роботи з цими рядками визначено низку функцій. Основні з них такі:
- int st.Lengbt() — повертає число символів у рядку st;
- bool st.IsEmptyO — повертає «true», якщо рядок st порожній;
- st.SetLenght(n) — усікає рядок st до п символів;
- st.Insert(str,k) — вставляє в рядок st підрядок str, починаючи з позиції kрядка st;
- st.Delete(k,n) — видаляє з рядка st п символів, починаючи з k позиції;
- int st.Pos(str) — повертає індекс першого символа першого входження підрядка str у рядок st;
- st.SubString(k,n) — повертає підрядок рядка st, що починається ізсимвола в позиції k і містить п символів;
- st.c_str() — перетворює рядок st до символьного масиву типу char;
- st.trim() — відкидає в рядку st усі початкові і кінцеві проміжки;
- bool st.IsDelimiter(dl,i) — повертає true, якщо символ з індексом і збігся з одним із символів-роздільників, зазначених у рядку dl типу AnsiString;
- Int st.LastDelimiter(dl) — повертає індекс останнього символа рядка st,що збігся з одним із символів рядка-роздільників dl. У цій функції рядок dl типуAnsiString являє собою набір символів-роздільників, на які реагує ця функція. Наприклад, якщо введемо рядок st = “c:\\filename.txt” і напишемо функцію int і= st.LastDelimiter(“\\.:”);, то результатом буде і = = 12. Тут рядок dlпредставлено своїм значенням. Символи, зазначені в dl, — це символи, які користувач визначив як символи-роздільники. Функція видала такий результат (і= 12) тому, що останнім символом у слові st, який збігається хоча б з одним символом-роздільником, є крапка. Вона в слові st має індекс, рівний 12 (‘W — це один символ). Функцію IsDelimiter() зручно використовувати для розбиття тексту на лексеми, наприклад, на слова.
Наведемо приклади використання деяких з цих функцій.
Приклад 14.1. Ввести речення, розбити його на слова і вивести таке повідомлення:
— порядковий номер слова;
— саме слово;
— кількість символів у кожному слові.
Речення ввести за допомогою компонентів Edit, а виведення результатів виконання програми здійснити за допомогою компонента Меmо. Розбиття текста на слова реалізовати функцією IsDelimiter().
Форми, програмний код та результат розв’язання задачі мають вигляд:
//----------------------------------------------------------------------------- void_ fastcall TForm1::BitBtn1Click(TObject *Sender) { AnsiString str, s1, st; int i, k=0; str = Edit1->Text; Memo1->Lines->Clear(); for (і = 1; і < str.Length(); i++) if (!str.IsDelimiter(" ,.!", i)) s1 = sl+str[i]; else { k++; st = IntToStr(k)+". слово " + ""+s1 + "" + " содержит " +IntToStr(s1.Length())+" символов\n"; Memo1->Lines->Add(st); s1 = ""; }
Приклад 14.2. У введеному реченні виправити помилку, замінивши частину слів. Для цього використати рядкові функції Length(), Pos(), Delete(), Insert().
Введення помилкового речення здійснити з використанням компонента Label, а виведення виправленого речення реалізувати компонентом Edit.
Форма і програмний код додатка мають такий вигляд:
//-------------------------------------------------------------------- void fastcall TForm1::BitBtn1Click(TObject *Sender) { AnsiString s1=Label1->Caption; s2 = "и был октябрь"; s3 = "стоял ноябрь "; int k = s1.Pos(s2); if(k) { s1.De!ete( k, s2.Length()); s1.Insert(s3, k+1); Edit1->Text = s1; } else Edit1->Text="Строки ошибки нет!"; }
Приклад 14.3. Розв’язати попередній приклад (приклад 14.2) за допомогою функціїSubString().
Форма і програмний код реалізації мають вигляд:
//------------------------------------------------------------------------------------------------------- void_ fastcall TForm1::BitBtn1Click(TObject *Sender) { AnsiString s1=Label1->Caption; s2 = "и был октябрь"; int k = s1.Pos(s2); if(k) Edit1->Text = s1.SubString(i,k-1) + "стоял ноябрь" + s1.SubString(k +s2.Length(),12); }
Приклад 14.4. Ввести список прізвищ та вивести його за такими ознаками:
— за заданим закінченням прізвища;
— за заданою першою літерою прізвища;
— для випадку, коли дві попередні ознаки діють одночасно, тобто задається перша літера прізвища і його закінчення.
Для введення списку використано функцію InputBox(), а для введення ознак —компоненти Edit1 і Edit2. Виведення вихідного списку і списку прізвищ, що мають задані ознаки, здійснити компонентом Label1.
Перед початком написання програмного коду треба включити заголовний файлDialogs.hpp. Масив прізвищ тут має ім’я sp, закінчення привласнюється змінній okn, st і s— допоміжні рядки, а для введення першого символа прізвища використовується операторAnsiString p=Edit1->text. Програмний код має вигляд:
void_ fastcall TForm1::BitBtn1Click(TObject *Sender) { const n=7; AnsiString sp[n], st, okn, s; int i, k, m; k = okn.Length(); Label6->Caption = ""; for (і = 0; і < n; i++) { sp[i]=InputBox("Bвод списка", "Введите "+ IntToStr(і+1)+" фамилию"," "); Label6->Caption=Label6->Caption+IntToStr(i+1)+ ""+sp[i]+'\n'; } AnsiString p = Edit1->Text; okn = Edit2->Text; k = okn.Length(); m = 0; Label4->Caption=" "; for (і = 0; і < n; i++) { s = sp[i]; st = sp[i].SubString(sp[i].Length()-k+1,k); if (p.IsEmpty()) if (st == okn) { m++; Label4->Caption = Label4->Caption+IntToStr(m) +“ ” + sp[i]+ '\n'; } if (okn.IsEmpty()) { if (s.SetLength(1) == p) { m++; Label4->Caption=Label4->Caption+IntToStr(m) +" " + sp[i] + '\n'; } } else if ((s.SetLength(1) == p) && (st == okn)) { m++; Label4->Caption=Label4->Caption+IntToStr(m) +“" + sp[i] +'\n'; } } }
Результати виконання прикладу наведено на формах:
Приклад 14.5. Ввести список прізвищ (рядків) і відсортувати його за алфавітом.
Для введення списку використати функцію InputBox(), для виведення вихідного списку— компонент Label, а виведення відсортованого списку здійснити компонентом Меmо. Сортування масиву рядків виконати за допомогою операцій відношення.
Процес сортування при розв’язанні даної задачі здійснено з використанням методу «пухирця», алгоритм якого наведено у прикладі 1.4 (частина І), а варіант програмної реалізації заданої задачі представлено у прикладі 6.11 (частина І).
Створена форма і розроблений програмний код мають вигляд:
//------------------------------------------------------------------------------------------ void_ fastcall TForm1::BitBtn1Click(TObject *Sender) { const n=7; AnsiString spis[n], buf; int і, k; Label2->Caption=" "; for (і = 0; і < n; і++) { spis[i] = InputBox("Ввод списка","Введите " + IntToStr(i+1) + " фамилию"," "); LabeI2->Caption = Label2->Caption + IntToStr(i+1) + " " + spis [і] + '\n'; } //----------------------------------------------------------- сортировка массива фамилий for (k = 1; k <n; k++) for (і = 0; і < n-k; i++) if (spis[i] > spis[i+1]) { buf=spis[i]; spis[i]=spis[i+1]; spis[i+1]=buf; } //-------------------------------------------------------- вывод отсортированного списка Memo1->Lines->Clear( ); Memo1->lines->Add("Отсортированный список"); for (і = 0; і < n; i++) Memo1->Lines->Add(IntToStr(i+1) + ". " + spis[i]); }
З наведених прикладів видно, що застосовуючи властивості рядкових даних, припустимі операції та вбудовані функції, можна робити різні перетворення і розв’язувати різноманітні задачі.