Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекция.docx
Скачиваний:
37
Добавлен:
28.03.2016
Размер:
2.79 Mб
Скачать

Лекция 6. Введение в обработку символов и строк

В этом разделе мы познакомимся с некоторыми типичными функциями стандартной библиотеки С, которые обеспечивают обработку строк. Обсуждаемая здесь техника подходит для разработки текстовых редакторов, лингвистических процессоров, программ верстки, систем компьютеризированного набора и других программных систем обработки текстов.

  1. Основы теории символов и строк

Символы – это фундаментальные стандартные блоки исходных программ на С++. Каждая программа составлена из последовательностей символов, которые, если их объединение в группу имеет смысл, интерпретируются компьютером как последовательности инструкций, используемых для выполнения задачи. Программа может содержать символьные константы. Символьная константа – это целое значение, представленное как символ в одинарных кавычках. Значение символьной константы – это целочисленное значение в наборе машинных символов. Например, 'z' представляет собой целое значение z, а '\n' представляет собой целое значение символа перехода на новую строку.

Строка – это последовательность символов, обрабатываемая как единый модуль. Строка может включать буквы, цифры и разнообразные специальные символы, такие как +, -, *, /, $ и другие. Литеральные константы или строковые константы записываются в С++ в двойных кавычках следующим образом:

"John Q.Doe" (имя)

"9999 Main Street" (адрес улицы)

"Waltham, Massachusetts" (город и штат)

"(201)555-1212" (номер телефона)

Строка в С++ – это массив символов, оканчивающийся нулевым символом ('\0'). Строка доступна через указатель на первый символ в строке. Значением строки является адрес ее первого символа. Таким образом можно сказать, что в С++ строка является указателем – указателем на первый символ строки. В этом смысле строки подобны массивам, потому что массив тоже является указателем на свой первый элемент.

Строка может быть объявлена либо как массив символов, либо как переменная типа char*. Каждое из объявлений

char color[] = "синий";

char *colorPtr = "синий";

присваивает переменной строке начальное значение «синий». Первое объявление создает массив из 6 элементов color содержащий символы ‘c’, ‘и’, ‘н’, ‘и’, ‘й’ и ‘\0\’. Второе объявление создает переменную указатель colorPtr, который указывает на строку «синий» где-то в памяти.

Когда переменная типа char* получает в качестве начального значения строковую константу, некоторые компиляторы могут поместить строку в такое место в памяти, где строка не может быть модифицирована. Если у вас может возникнуть необходимость модифицировать строковую константу, она должна храниться в массиве символов, чтобы обеспечить возможность ее модификации во всех системах.

Объявление char color[] = {"синий"} может быть записано

char color[ ] = {'c', 'и', 'н', 'и', 'й', '\0'};

Когда объявляется массив символов, содержащий строку, он должен быть достаточно большим, чтобы хранить строку и ее завершающий нулевой символ. Предыдущее объявление определяет размер массива автоматически, основываясь на количестве начальных значений в списке.

Типичная ошибка программирования: не выделяется достаточно места в массиве символов для хранения нулевого символа, завершающего строку.

Типичная ошибка программирования: создание или использование «строки», которая не содержит завершающего нулевого символа.

При хранении строки в массиве символов убедитесь, что массив достаточно велик, чтобы вместить наибольшую строку, которую потребуется хранить. В С++ допускается хранить строки любой длины. Если строка больше символьного массива, в котором она должна храниться, символы, выходящие за конец массива, будут изменять дан­ные в разделах памяти, следующих за массивом.

Строку можно присвоить массиву, используя операцию cin – взять из потока. Например, строку можно присвоить символьному массиву word[20] следующим оператором:

cin >> word;

Вводимая пользователем строка хранится в word. Предыдущий оператор считывает символы до тех пор, пока не встретится пробел, символ табуляции, символ новой строки или указатель конца файла. Заметим, что строка не должна быть длиннее 19 символов, чтобы оставить место для завершающего нулевого символа. Манипулятор потока setw можно использовать для гарантии того, что строка, считанная в word, не превысит размер массива. Например, оператор

cin >> setw(20) >> word;

указывает, что cin должен считать максимум 19 символов в массив word и оставить 20-й символ в массиве для хранения завершающего нулевого символа. Манипулятор потока setw применяется только к следующему вводимому значению символа.

Для ввода-вывода строк используются как уже известные нам объекты cin и cout, так и функции, унаследованные из библиотеки С. Первый способ:

#include <iostream.h>

int main()

{

const int n = 80;

char s[n];

cin >> s;

cout << s << endl; //ввод строки, состоящей из одного слова

return 0;

}

В данном случае ввод выполняется до первого пробельного символа (то есть пробела, знака табуляции или символа перевода строки “\n”).

Можно ввести слова входной строки в отдельные строковые переменные:

#include <iostream.h>

int main()

{

const int n = 80;

char s[n], t[n],r[n];

cin >> s » t >> r;

cout << s << endl << t << endl << r << endl;

return 0;

}

Если требуется ввести строку, состоящую из нескольких слов, в одну строковую переменную, используются методы getline или get класса iostream, объектом которого является cin.

#include <iostream.h>

int main(){

const int n = 80;

char s[n];

cin.getline(s, n); cout << s << endl;

cin.get(s, n); cout << s << endl;

return 0;

}

Метод getline считывает из входного потока n - 1 символов или менее (если символ перевода строки встретится раньше) и записывает их в строковую переменную s. Символ перевода строки также считывается (удаляется) из входного потока, но не записывается в строковую переменную, вместо него размещается завершающий 0. Если в строке исходных данных более n - 1 символов, следующий ввод будет выполняться из той же строки, начиная с первого несчитанного символа.

Метод get работает аналогично, но оставляет в потоке символ перевода строки. В строковую переменную добавляется завершающий 0.

В некоторых случаях желательно вводить в массив полную строку текста. С этой целью С++ снабжен функцией cin.getline. Функция cin.getline требует три аргумента – массив символов, в котором должна храниться строка текста, длина и символ-ограничитель. Например, фрагмент программы

char sentence[80];

cin.getline(sentence, 80, '\n');

объявляет маccив sentence из 80 символов, затем считывает строку текста с клавиатуры в этот массив. Функция прекращает считывание символов в случаях, если встречается символ-ограничитель ‘\n\’, если вводится указатель конца файла или если количество считанных символов оказывается на один меньше, чем указано во втором аргументе (последний символ в массиве резервируется для завершающего нулевого символа). Если встречается символ-ограничитель, он считывается и отбрасывается. Третий аргумент cin.getline имеет '\n' в качестве значения по умолчанию, так что предыдущий вызов функции мог бы быть написан в следующем виде:

cin.getline(sentence, 80);

Если в программе требуется ввести несколько строк, метод getline удобно использовать в заголовке цикла, например:

#include <iostream.h>

int main(){

const int n = 80;

char s[n];

while (cin.getline(s,n))

{

cout << s << endl; // обработка строки

}

return 0:

}

Можно использовать для ввода строки функцию scanf, а для вывода - printf, задав спецификацию формата %s:

#include <stdio.h>

int main(){

const int n = 10;

char s[n];

scanf(“%s”, s);

printf(“%s“, s);

return 0;

}

Ввод будет выполняться до первого пробельного символа. Чтобы ввести строку, состоящую из нескольких слов, используется спецификация %c (символы) с указанием максимального количества вводимых символов, например:

scanf(“%10c“, s);

Количество символов может быть только целой константой. При выводе можно задать перед спецификацией %s количество позиций, отводимых под строку:

printf(“%15s“, s):

Строка при этом выравнивается по правому краю отведенного поля. Если заданное количество позиций недостаточно для размещения строки, оно игнорируется, и строка выводится целиком.

Типичная ошибка программирования. Обработка одного символа как строки. Строка является указателем – это может быть достаточно большое целое. А символ – это небольшое целое (диапазон значений ASCII 0 – 255). Во многих системах это вызывает ошибку, потому что нижние адреса памяти зарезервированы для специальных целей, таких как обработчики прерываний операционной системы – так что происходит «несанкционированный доступ».

Библиотека содержит также функции, специально предназначенные для ввода-вывода строк: gets и puts. Предыдущий пример с использованием этих функций выглядит так:

#include <stdio.h>

int main(){

const int n = 10;

char s[n];

gets(s);

puts(s): return 0:

}

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

Функция puts (s) выводит строку s на стандартное устройство вывода, заменяя завершающий 0 символом новой строки. Возвращает неотрицательное значение при успехе или EOF при ошибке.