|
Программирование >> Динамические структуры данных
Однако есть и более простое решение - использовать в таких случаях метод getl ine, который после прочтения строки не оставляет во входном потоке символ \п. Если в программе требуется ввести несколько строк, метод getl i ne удобно использовать в заголовке цикла, например: linclude <iostream.h> int main(){ const int n = 80; char s[n]; while (cin.getline(s. n)) { cout s endl: обработка строки return 0: Рассмотрим теперь способы ввода-вывода строк, перекочевавшие в С++ из языка С. Во-первых, можно использовать для ввода строки известную нам функцию scapf, а для вывода - printf, задав спецификацию формата %s: linclude <stdio.h> int main(){ const int n = 10: char s[n]: seanf( s . s): printf( s . s); return 0; Имя строки, как и любого массива, является указателем на его начало, поэтому использовавшаяся в предыдущих примерах применения функции seanf операция взятия адреса (&) опушена. Ввод будет выполняться так же, как и для классов ввода-вывода - до первого пробельного символа. Чтобы ввести строку, состоящую из нескольких слов, используется спецификация %с (символы) с указанием максимального количества вводимых символов, например: scanfClOc . S): Количество символов может быть только целой константой. При выводе можно задать перед спецификацией %s количество позиций, отводимых под строку: printfCnSs . S): Строка при этом выравнивается по правому краю отведенного поля. Если заданное количество позиций недостаточно для размещения строки, оно игнорируется, и строка выводится целиком. Спецификации формата описаны в Учебнике на с. 387, а сами функции семейства printf - на с. 411 и далее. Библиотека содержит также функции, специально предназначенные для ввода-вывода строк: gets и puts. Предыдущий пример с использованием этих функций выглядит так: linclude <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 на стандартное устройство вывода, заменяя завершающий О символом новой строки. Возвращает неотрицательное значение при успехе или EOF при ошибке. Функциями семейства pri ntf удобнее пользоваться в том случае, если в одном операторе требуется ввести или вывести данные различных типов. Если же работа выполняется только со строками, проще применять специальные функции для ввода-вывода строк gets и puts. Операции со строками Для строк не определена операция присваивания, поскольку строка является не основным типом данных, а массиюм. Присваивание выполняется с помощью функций стандартной библиотеки или посимвольно вручную (что менее предпочтительно, так как чревато ошибками). Например, чтобы присвоить строке р строку а, можно воспользоваться функциями strcpy или strncpy: char а[100] = Never trouble trouble ; char *p = new char [m]; strcpy(p. a): strncpy (p. a. strlen(a) + 1); Для использования этих функций к программе следует подключить заголовочный файл <string.h>. Функция strcpy (р. а) копирует все символы строки, указанной вторым параметром (а), включая завершающий О, в строку, указанную первым параметром (р). Функция strncpy (р. а. п) выполняет то же самое, но не более п символов, то есть числа символов, указанного третьим параметром. Если нуль-символ в исходной строке встретится раньше> копирование прекращается, а оставшиеся до п символы строки Р заполняются нуль-символами. В противном случае (если п меньше или равно длине строки а) завершающий нуль-символ в р не добавляется. Обе эти функции возвращают указатель на результирующую строку. Если области памяти, занимаемые строкой-назначением и строкой-источником, перекрываются, поведение программы не определено. Функция stг 1 en (а) возвращает фактическую длину строки а, не включая нуль-символ. Программист должен сам заботиться о том, чтобы в строке-приемнике хватило места для строки-источника (в данном случае при выделении памяти значение переменной m должно быть больше или равно 100), и о том, чтобы строка всегда имела завершающий нуль-символ. ВНИМАНИЕ-- Выход за границы строки и отсутствие нуль-символа являются распространенными причинами ошибок в программах обработки строк. Для преобразования строки в целое число используется функция atoi (str). Функция преобразует строку, содержащую символьное представление целого числа, в соответствующее целое число. Признаком конца числа служит первый символ, который не может быть интерпретирован как принадлежащий числу. Если преобразование не удалось, возвращает 0. Аналогичные функции преобразования строки в длинное целое число (long) и в вещественное число с двойной точностью (doubl е) называются atol и atof соответственно. Пример применения функций преобразования: char а[] - 10) Рост - 162 см. вес - 59.5 кг : int num: long height: double weight: num = atoi(a): height atol.(&a[ll]): weight = atof(&a[25]): cout num height weight: Библиотека предоставляет также различные функции для сравнения строк и подстрок, объединения строк, поиска в строке символа и подстроки и выделения из строки лексем. Эти функции описаны в Учебнике на с. 414-446. В процессе разбора задач мы рассмотрим некоторые из них. Работа с символами Для хранения отдельных символов используются переменные типа char. Их ввод-вывод также может выполняться как с помощью классов ввода-вывода, так и с помощью функций библиотеки. При использовании классов ввод-вывод осуществляется как с помощью операций помещения в поток и извлечения из потока , так и методов get() и get (char). Ниже приведен пример применения операций: linclude <iostream.h> int main(){ char с. d, e: cin c: cin d e: cout с d e endl: return 0: Вводимые символы могут разделяться или не разделяться пробельными символами, поэтому таким способом ввести символ пробела нельзя. Для ввода любого символа, включая пробельные, можно воспользоваться методами get() или get (с): finclude <iostream.h> int main(){ char с. d. e: с - cin.getO; cin.get(d): cin.get(e): cout с d e endl: return 0: Метод get () возвращает код извлеченного из потока символа или EOF, а метод get (с) записывает извлеченный символ в переменную, переданную ему в качестве аргумента, а возвращает ссылку на поток. В заголовочном файле <stdio. h> определена функция getchar() для ввода символа со стандартного ввода, а также putchar() для вывода: #include <stdio.h> int main(){ char с. d: c-getchar(): putchar(c): d = getcharO: putchar(d): return 0: В библиотеке также определен целый ряд функций, проверяющих принадлежность символа какому-либо множеству, например множеству букв (isal fa), разделителей (isspace), знаков пунктуации (ispunct), цифр (isdigit) и т. д. Описание этих функций приведено в Учебнике на с. 92 и с. 409-446. Перейдем теперь к рассмотрению задач. Задача 5.1. Поиск подстроки Написать программу, которая определяет, встречается ли в заданном текстовом файле заданная последовательность символов. Длина строки текста не превышает 80 символов, текст не содержит переносов слов, последовательность не содержит пробельных символов. На предыдущем семинаре на примере задачи 4.3 мы рассмотрели общий порядок действий при создании программы. Будем придерживаться его и впредь. I. Исходные данные и результаты Исходные данные: 1. Текстовый файл неизвестного размера, состоящий из строк длиной не более 80 символов. Поскольку по условию переносы отсутствуют, можно огра- кичиться поиском заданной последовательности в каждой строке отдельно. Следовательно, необходимо помнить только одну текущую строку файла. Для ее хранения выделим строковую переменную длиной 81 символ (дополнительный символ требуется для завершающего нуля). 2. Последовательность символов для поиска, вводимая с клавиатуры. Поскольку по условию задачи она не содержит пробельных символов, ее длина также не должна быть более 80 символов, иначе поиск завершится неудачей. Для ее хранения также выделим строковую переменную длиной 81 символ. Результатом работы программы является сообщение либо о наличии заданной последовательности, либо об ее отсутствии. Представим варианты сообщений в программе в виде строковых констант. Для хранения длины строки будем использовать именованную константу. Для работы с файлом потребуется служебная переменная соответствующего типа. П. Алгоритм решения задачи 1. Построчно считывать текст из файла. 2. Для каждой строки проверять, содержится ли в ней заданная последовательность. 3. Если да, напечатать сообщение о наличии заданной последовательности и завершить программу. 4. При нормальном выходе из цикла напечатать сообщение об отсутствии заданной последовательности и завершить программу. П1. Программа и тестовые примеры linclude <fstream.h> linclude <string.h> int main(){ const int len = 81: 1 char word[len]. line[len]: 2 cout Введите слово для поиска: : cin word: ifstream fin( text.txt . ios::in ios::nocreate): if (!fin) { cout Ошибка открытия файла. endl return 1; } 3 4 while (fin.getlinedine, len)) { if (strstrdine. word)) { cout Присутствует! endl: return 0: } cout Отсутствует! endl: return 0: 5 6 Рассмотрим помеченные операторы. В операторе 1 описывается константа, определяющая длину строки файла и длину последовательности. В операторе 2 опи- сывается переменная 1 ine для размещения очередной строки файла и переменная word для размещения искомой последовательности символов. В операторе 3 определяется объект fin класса входных потоков ifstream. С этим объектом можно работать так же, как со стандартными объектами cin и cout, то есть использовать операции помещения в поток и извлечения из потока , а также рассмотренные выше функции get, getl ine и другие. Предполагается, что файл с именем text. txt находится в том же каталоге, что и текст программы, иначе следует указать полный путь, дублируя символ обратной косой черты, так как иначе он будет иметь специальное значение, например: ifstream fin( c:\\prim\\cpp\\text.txt . ios::in ios::nocreate): 3 В операторе 4 проверяется успешность создания объекта f i п. Файлы, открываемые для чтения, проверять нужно обязательно! В операторе 5 организуется цикл чтения из файла в переменную line. Метод get! ine, описанный выше, при достижении конца файла вернет значение, завершающее цикл. Для анализа строки в операторе 6 применяется функция strstrdine. word). Она выполняет поиск подстроки word в строке line. Обе строки должны завершаться нуль-символами. В случае успешного поиска функция возвращает указатель на найденную подстроку, в случае неудачи - NULL. Если вторым параметром передается указатель на строку нулевой длины, функция возвращает указатель на начало строки 1 i ne. В качестве тестового примера приготовьте текстовый файл, состоящий из нескольких строк. Длина хотя бы одной из строк должна быть равна 80 символам. Для тестирования программы следует запустить ее по крайней мере два раза: введя с клавиатуры слово, содержащееся в файле, и слово, которого в нем нет. Даже такую простую программу мы рекомендуем вводить и отлаживать по шагам. Это умение пpигoдиf ся вам в дальнейшем. Предлагаемая последовательность отладки: 1. Ввести скелет программы (директивы #include, фзшкцию mainO, операторы 1-4). Добавить контрольный вывод введенного слова. Запустив программу, проверить ввод слова и успешность открытия файла. Выполнить программу, задав имя несуществующего файла, для проверки вывода сообщения об ошибке. Удалить контрольный вывод слова. 2. Проверить цикл чтения из файла: добавить оператор 5 с его завершающей фигурной скобкой, внутри цикла поставить контрольный вывод прочитанной строки: cout line endl: Удалить контрольный вывод строки. 3. Дополнить программу операторами проверки и вывода сообщений. Для полной проверки программы следует выполнить ее для нескольких последователь- Файл можно создать в любом текстовом редакторе, в том числе и в той оболочке, в которой вы работаете. Для правильного отображения русских букв при выводе на консоль вид код;1ровки должен быть ASCII. 4 Зак.784
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |