Программирование на языке С++ Строки |
|||||||||
|
Символьный тип char Для хранения символьных данных предназначен тип char. Переменную типа char можно рассматривать двояко: как целое число, занимающее 1 байт и способное принимать значения от 0 до 255 (тип unsigned char) или от -128 до 127 (тип signed char) и как один текстовый символ. Таким образом, данные типа char можно складывать, вычитать, умножать, делить, а можно выводить на экран в виде одного символа. Именно это и происходит при выводе символа через объект cout. Если же нужно вывести числовое значение символа (также называемый ASCII-кодом), то значение символа необходимо преобразовать к типу int. Например: #include <iostream> using namespace std; int main() { char c='A'; // Константы типа char заключаются в одинарные кавычки cout<<c<<" "<<(int)c<<endl; c=126; // char можно присвоить и числовое значение cout<<c<<" "<<(int)c<<endl; return 0; } В этом примере переменной с типа char присваивается значение, равное символу 'A' (константы типа char записываются как символы в одинарных кавычках), затем на экран выводится значение c, как символа и его ASCII-код, потом переменной c присваивается значение 126 (то есть символ с ASCII-кодом 126) и снова выводится на экран символ и его ASCII-код. Организовать последовательное посимвольное считывание всего входного потока можно при помощи цикла while: #include <iostream> using namespace std; int main() { char c; while(cin>>c) // Цикл пока считывание успешно { // Делаем необходимые действия } return 0; } В этом примере программа будет посимвольно считывать входной поток (по умолчанию -- ввод с клавиатуры), пока не встретит признак конца файла. Для того, чтобы сообщить программе о завершении файла при вводе с клавиатуры необходимо нажать клавиши Ctrl-d. Эта программа при считывании данных будет игнорировать символы-разделители: пробелы, символы новой строки и табуляции. Если нужно, чтобы в переменную c считывались все символы, в том числе и разделители, то необходимо для потока ввода cin установить манипулятор noskipws при помощи инструкции cin>>noskipws;. C-строки Строка в языке C -- это обычный массив символов, то есть массив данных типа char. Если объявить строку S в виде char S[100], то для хранения этой строки будет отведено 100 байт памяти. К каждому символу строки можно обращаться, как к элементу массива: S[0], S[1] и т.д. При этом длина строки может быть и меньше 100 символов. Признаком окончания строки является символ с нулевым ASCII-кодом, то есть если в строке S записано слово С++, то S[0]=='C', S[1]=='+', S[2]=='+', S[3]==0, а во всех остальных элементах массива S могут быть записаны произвольные символы. Таким образом, максимальная длина строки, объявленной как char S[n] может быть n-1 символ, поскольку один символ требуется для хранения нулевого символа, завершающего строку. При работе со строками надо быть аккуратными и не вылезать за границы массива-строки, поскольку язык C++ не контролирует подобные ошибки. Ввод и вывод текстовых строк осуществляется так же, как и ввод-вывод чисел: cin>>S; // считать строку S с клавиатуры cout<<S; // вывести строку S на экран При выводе на экран строки выводятся все символы строки вплоть до завершающего нулевого символа. Нулевой символ на экран не выводится. При считывании строк из входного потока считываются все символы, кроме символов-разделителей, которые являются границами между строками. Например, если при выполнении следующей программы char S1[100], S2[100], S3[100]; // объявили 3 строки cin>>S1>>S2>>S3; ввести строку Мама мыла раму (с произвольным количеством пробелов между словами), то в массив S1 будет записана строка "Мама", в S2 -- "мыла", в S3 -- "раму". При этом каждая строка будет дополнена завершающим нулевым символом. Таким образом, организовать считывание всего файла по словам, можно следующим образом: char S[1000]; // Максимально возможный размер слова while(cin>>S) { // Выполнить необходимые действия } Заметим, что если во входном массиве будет слово, которое не помещается в массиве S, то программа будет работать некорректно (например, завершит свою работу с ошибкой типа Segmentation fault). Часто бывает необходимо считывать данные из входного потока не по словам, а по строкам, считая, что строки разделены символом перевода строки. Тогда нужно использовать метод getline потока cin в следующем виде: const int n=1000; // константа - максимальный размер строки char S[n]; // массив-строка из n элементов while(cin.getline(S,n)) // считываем не более n символов { // Сделать необходимые действия } У метода getline два аргумента. Первый аргумент -- идентификатор массива-строки, в который будет записан результат ввода. Второй аргумент: максимальное число символов, которое будет считано. Таким образом, метод getline является более безопасным, поскольку задав параметр n мы можем избежать проблемы переполнения строки. В файле cstring описано большое количество функций, позволяющих работать со строками: копирование, конкатенация, поиск подстроки, выделение подстроки и т.д. Подключить этот файл можно при помощи инструкции препроцессора #include Строки в языке C++ На языке C++ программист должен постоянно проверять, не произошло ли переполнение строки при различных операциях типа копирования или считывания строки со стандартного ввода или из файла. Кроме того, для копирования строк необходимо было вызывать специальную функцию strcpy. Поэтому в C++ были добавлены новые строки: объекты класса string. Для этих объектов определен оператор конкатенации +, оператор присваивания = и при работе с таким строками автоматически проходит проверка переполнения строки и увеличение ее размера при необходимости. Основные приемы работы с объектами string проиллюстрированы в программе: string S, S1, S2; // Объявление трех строк cin>>S1; // Считали строку S1 S2="Привет, "; // Присвоили строке значение S=S2+S1; // Использование конкатенации cout<<S<<endl; // Вывод строки на экран cout<<S.length(); // Длина строки S Обращаться к отдельному символу строки string можно как и к отдельному элементу массива: S[0], S[1] и т.д. Если необходимо преобразовать объект string к C-строке, необходимо вызвать для него метод c_str(): S.c_str(). Как и в случае C-строк, при считывании строки при помощи cin>>> S строка считывается до появления первого пробельного символа, при этом все пробельные символы игнорируются. Если необходимо считывать строку вместе с пробелами до появления символа конца строки, нужно использовать функцию getline, указав в качестве первого параметра - имя входного потока, в качестве второго параметра - идентификатор строки: getline(cin,S1); Упражнения Если в упражнении сказано "дана строка", то ее можно считать при помощи инструкции вида cin>> S или при помощи функции getline. Если сказано "дан текст", то текст надо считывать со стандартного входа до появления признака конца файла. Можно ограничить длину всех используемых строк 1000 байтов. 1. Даны две строки. Определите, совпадают ли они сравнив их посимвольно. 2. Выведите на экран все возможные символы и их ASCII-коды. Сделайте то же самое дома на компиляторе MinGW в системе Windows. Сравните результаты (обратите внимание на расположение русских букв). 3. Дана строка. Найдите, сколько раз в ней встречается буква a. А сколько в ней гласных букв? 4. Даны две строки. Определите, является ли первая строка подстрокой второй строки. 5. Дан текст. Найдите, сколько в нем слов. 6. Дан текст. Подсчитайте для него частотную таблицу, то есть для каждого символа определите, его частоту появления в тексте (число таких символов в тексте деленное на общее число символов в тексте). 7. Дана строка, содержащее 16-ричное число, то есть состоящая из символов '0', ..., '9', 'a', ..., 'f'. Определите сумму всех его десятичных цифр (т.е. цифр из интервала '0', ..., '9'). 8. Дан текст. Найдите в нем самое длинное слово. 9. Дан текст. Найдите в нем все слова-палиндромы. 10. Дан текст. Замените в нем все подстроки мама на а) папа; б) дедушка. Все остальные символы не менять. 11. Юный хакер Костя Яблочкин хочет узнать пароль системного администратора. Он знает, что пароль состоит из 8 символов, первые 5 из которых -- строчные буквы латинского алфавита, а последние 3 -- цифры. 1. Сколько существует таких паролей? 2. Напишите программу, которая выводит список всех таких паролей. 3. Если все эти пароли записать в файл через пробел, какой будет размер этого файла? 4. Запишите в текстовый файл первые 10000 таких паролей в лексикографическом (алфавитном) порядке. наверх |