Восьмое занятие по С++: cтроки в стиле Си

Что такое строка?

Как ты уже знаешь, чтобы хранить в памяти символы (а значит и буквы) в с++ используется тип char. А в языке слово, это всего лишь множество букв. Как ты думаешь, как можно хранить последовательно идущие символы? Правильно! Можно использовать массив элементов типа char!

Тогда можно будет работать с буквами в слове также, как мы работали с числами в целочисленных массивах. Предположим у нас если размер массива 8, а нам надо положить в него слово «привет» . Тогда часть памяти будет использована, а последние две ячейки будут свободны. Чтобы помнить, сколько действительно букв в нашем слове, помимо массива, нам понадобится хранить еще и реальный размер слова в нем. Выглядеть это будет вот так:

Но не проще ли было что-нибудь придумать, чтобы вместо цикла для ввода и вывода использовать более простую конструкцию? Можно! Для решения этой проблемы придумали символ ‘’, который означает конец строки.

Строка в стиле Си — массив символов, оканчивающийся символом ‘’.
Строка отличается от обычного массива символов наличием символа ‘’ после последней буквы.

Теперь нам не обязательно запоминать реальный размер строки, в процессе прохода по массиву мы сможем сразу понять, где надо остановиться:

Разработчики С++ уже реализовали это идею в библиотека ввода и вывода, поэтому для работы со строками можно просто писать:

char str[255];

cin >> str; //вводим слово (читает все до пробела) и автоматически ставит  в конце
cout << str; //выводит все до символа 

Почему мы взяли такой большой массив? Для того чтобы памяти наверняка хватило для любого адекватного слова. Если то, что мы введем будет длиннее 254 (слово + ) символов, произойдет выход за границе массива и программа выдаст ошибку в процессе выполнения.

Почему мы не ставим в конце? cin — умный. Он сам поставит символ окончания строки в конце. А вот если мы формируем строку вручную, это нужно сделать самостоятельно! 🙂

char word[10];
word[0] = 'H';
word[1] = 'e';
word[2] = 'y';
word[3] = '!';
word[4] = ''; //обрати внимание на одинарные кавычки!

cout << word; //выведет "Hey!"

А что будет если не поставить символ окончания строки? Вывод в cout будет работать по следующему принципу:

int i = 0;
while(word[i] != '') cout << word[i];

Такой код будет выводить все, что лежит в памяти, пока не встретит символ конца строки любой другой (чужой) строки. Например он может вывести что-то такое:

 Hey!ММММ,ш±

Так же как и обычные массивы строки можно создавать динамически, выделяя только нужное кол-во памяти. Но не забывай, что cin автоматически память выделять не умеет, ему надо давай только указатели, в которые заранее выделено достаточное количество памяти!

Некоторые функции для работы со строками

В си++ уже встроены многие функции (все они определены в cstring), которые могут тебе пригодится, вот некоторые из низ них:

1. Определение длины

Очень часто тебе понадобится вычислять реальную длину строки. Это можно сделать вот так:

char str[255];
cin >> str;
int length = 0; //длина строки
for (length = 0; str[length] != ''; ++length ); //фигурных скобок нет, т.к. в них ничего делать не надо

А можно использовать готовую функция strlen из файла cstring:

char str[255];
cin >> str;
int length = strlen(str);

2. Сравнение строк

Как ты помнишь, название массива это указатель на первый элемент, а значит число. Поэтому если написать str1 > str2, компьютер будет сравнивать не строки, как это было бы логично и удобно, а указатели на первые элементы. По этой причине строки придется сравнивать посимвольно.

Как ты знаешь у каждого символа есть свой номер, причем буквы и цифры стоят по порядку, поэтому ‘a'<‘b’ — верное утверждение. Единственная проблема заключается в том, что все английские буквы считаются больше русских (что логично), а любая строчная буква считается меньше любой ПРОПИСНОЙ (что уже совсем не логично).

То есть символы в кодировке располагаются вот так:

...0-9...A-Z...a-z...А-Я...а-я...

Сравнение по такому принципу называется лексикографическим. Именно по нему располагаются слова в словаре.

Для лексикографического сравнение в C в файле cstring есть функция strcmp. Она принимает два указателя на строки, возвращает 0,  если строки равны, отрицательное число если первая строчка меньше и положительное, если больше.

int a = strcmp("banan", "abrikos"); //первое слово меньше - вернет отрицательное число
a = strcmp("Z", "a"); //первое больше (т.к ПРОПИСНОЕ), вернет положительное число
a = strcmp("korova", "korova"); //вернет 0
a = strcmp("Korova", "korova"); //вернет положительное, т.к. 'K' и 'k' - разные символы

3. Копирование строк.

Допустим, нам скопировать строку, чтобы внести в нее какие — то изменения, а оригинал оставить. Если мы просто скопируем указатель и будем вносить изменение, то так как в памяти на самом деле ничего не изменилось, то оригинал так же будет изменяться. Старый указатель указывает на этот же участок памяти. Поэтому самый простой вариант в этой ситуации — посимвольно скопировать строку в другой массив. Для этого существует функция strcpy, она принимает указатель на строку в которую копируем, и строку которую будем копировать. Пример:

char str1[255];
char * str2; //можно создать и обычный массив, ничего не поменяется

cin >> str1;
str2 = new char[strlen(str1)+1]; //+1 - ячейка для 
strcpy(str2, str1); //теперь str2 - полная копия str
cout << str2;

4. Объединение (конкатенация) строк

Строки не получится складывать, как числа =( Чтобы склеить две строки придется посимвольно дописывать к первой строке вторую. Для этого уже готова функция strcat,  первый параметр — строка к которой мы что-то дописываем, второй — то, что мы дописываем. Функция возвращает первый параметр (указатель на строку), если все хорошо и NULL, если в первом массиве не хватает памяти.

Обрати внимание: strcat память не выделяет, в первой строке должно хватать места, чтобы приписать туда вторую строку.

char str[80];
str[0] = '';
strcat(str, "Hello");
char* str2 = " world!";
strcat(str, str2);
cout << str;

 

Описание всех функций работы со строками можно найти тут.

 

Задачи для самостоятельного решения

6.1 Написать функцию concatenate(), которая объединяет две строки и возвращает результат. Не использовать strcat() =) (5 баллов).

6.2. Написать функцию, которая переворачивает (инвертирует) строку, вводимую пользователем. (5 баллов).

6.3 Написать программу, которая определяет, является ли вводимая пользователем строка палиндромом.

6.4.1 Написать программу, которая принимает строку типа: 2+3+4-9+1… состоящую только из чисел от 0 до 9 и знаков + и -, вычисляет значение и выводит его на экран. (5 баллов).

6.4.2. Расширить программу 6.4.1 таким образом, чтобы она поддерживала целые числа, состоящие из произвольного количества количества цифр, а также целочисленное деление и умножение (10 баллов).

6.5. Написать функцию, которая меняет местами две строки разной длинны наиболее эффективным способом. (до 10 баллов).

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *