Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Строки полностью.doc
Скачиваний:
10
Добавлен:
18.07.2019
Размер:
131.58 Кб
Скачать

ЛЕКЦИЯ 19

С-строки

В языке С++ нет специального строкового типа. Строка представляет собой массив символов, заканчивающийся нуль-символом. Нуль-символ — это символ с кодом, равным 0, который записывается в виде управляющей последовательности ‘\0’. По положению нуль-символа определяется фактическая длина строки.

В С++ есть две возможности работы со строками: функции, унаследованные из библиотеки С (заголовочный файл <string.h>), и библиотечный класс C++ string, предоставляющий более широкие возможности.

Строки string не обязательно должны состоять из символов типа char. Это позволяет использовать любой набор символов (не только ASCII), но для произвольного набора следует определить собственную операцию копирования, что может снизить эффективность работы.

Память под строки, как и под другие массивы, может выделяться либо на этапе компиляции (обычные строки), либо непосредственно в программе (динамические сроки).

Длина обычной строки может быть только константным выражением. Чаще всего она задается частным случаем константного выражения – константой:

const int len_str = 80;

char str[len_str];

При задании длины необходимо учитывать завершающий нуль-символ (в приведенной выше строке можно хранить только 79 символов).

Строку можно инициализировать строковым литералом (нуль-символ формируется автоматически):

char str[10] = "Vasia"; // выделено 10 элементов с номерами от 0 до 9

// первые элементы – ‘V’, ‘а’, ‘s’, ‘i’, ‘а’, ‘\0’

В данном случае под строку выделяется 10 байт, 5 из которых занято под символы строки, а шестой — под нуль-символ.

Если строка при определении инициализируется, то размерность можно опускать (компилятор сам выделит соответствующее количество байт):

char str[ ] = "Vasia"; // выделено и заполнено 6 байт

Для размещения строки в динамической памяти надо описать указатель на char, а затем выделить необходимый объем памяти:

char *str = new char [m] или char *str = (char *)malloc(m*sizeof(char));

При этом длина строки может быть переменной и задаваться на этапе выполнения программы.

Динамические строки, как и другие динамические массивы, нельзя инициализировать при создании. Оператор

char *str = "Vasia"

создает не строковую переменную, а указатель на строковую константу, изменить которую невозможно (к примеру, оператор str[1]='o' не допускается).

Знак равенства перед строковым литералом означает инициализацию, а не присваивание. Операция присваивания одной строки другой не определена (поскольку строка является массивом) и может выполняться с помощью цикла или функций стандартной библиотеки.

Ввод/вывод строк и символов

Для ввода/вывода строк и символов используются либо функции, унаследованные из языка С, либо потоки С++.

Пример: ввод/вывод строк с помощью функций языка С.

#include <sdtio.h>

int main ( ) {

const int n = 20;

char s[n];

printf (“Введите строку\n”);

scanf (“%s”, s);

printf (“\nВы ввели строку\n”)

printf (“%s”, s);

return 0;

}

Здесь используются функции scanf и printf со спецификацией %s (строка). Ввод при этом будет выполняться до первого пробельного символа. Для ввода строк из нескольких слов, используется спецификация %с (символы) с указанием максималного количества вводимых символов, например:

scanf (“%50c”, s);

Количество символов может быть только целой константой.

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

printf (“%50s”, s);

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

В стандартной библиотеке имеются также функции языка С, специально предназначенные для ввода/вывода строк и символов (заголовочный файл stdio.h).

Чтение символа из стандартного потока ввода

int getchar(void);

Возвращает очередной символ в форме int из стандартного потока ввода. Если символ не может быть прочитан, то возвращается значение EOF.

EOF – константа, сообщающая об окончании файла, представляет собой отрицательное целое число (заголовочный файл stdio.h).

Чтение символа с клавиатуры до появления символа новой строки.

char *gets(char *s);

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

Вывод символа на стандартное устройство вывода

int putchar (int ch);

Выводит символ ch на стандартное устройство вывода. Если вывод успешен, возвращается значение ch, иначе возвращается значение EOF.

Вывод строки на стандартное устройство вывода

int puts(char *s);

Выводит строку S на стандартное устройство вывода, добавляя в конце символ новой строки. Возвращает неотрицательное значение при успехе или EOF — при ошибке.

Функции для работы с многобайтовыми символами

Для работы с многобайтовыми символами предназначены функции getwchar и putwcchar.

Данные функции аналогичны функциям для работы с однобайтовыми символами, но вместо типа int используется тип wint_t. Этот тип является целочисленным типом для хранения символов расширенного набора (заголовочный файл wctype.h).

Например, функция getwchar имеет формат, аналогичный формату функции getchar, и отличается только типом возвращаемого значения:

wint_t getwchar(void);

Пример: ввод/вывод строк с использованием специалных функций стандартной библиотеки.

#include <sdtio.h>

int main ( ) {

const int n = 50;

char s[n];

printf (“Введите строку\n”);

gets (s);

printf (“\nВы ввели строку\n”)

puts (s);

return 0;

}

Функциями scanf и printf удобнее пользоваться, когда в одном операторе требуется ввести или вывести данные различных типов. Если выполняется работа только со строками, проще применять функции puts и gets.

Пример: ввод/вывод строк с помощью потоков С++.

#include <iostream.h>

int main ( ) {

const int n = 20;

char s[n];

cout << “Введите строку: ”;

cin >> s;

cout << endl << “Вы ввели строку: ” << s;

return 0;

}

Ввод в данном случае также будет выполняться до первого пробельного символа. Если необходимо ввести строку из нескольких слов, можно использовать для каждого слова отдельные строковые переменные:

#include <iostream.h>

int main ( ) {

const int n = 20;

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

cout << “Введите строку: ”;

cin >> s >> t >> r;

cout << endl << “Вы ввели строку: ” << s << “ ”<< t << “ ” << r;

return 0;

}

Чтобы ввести строку из нескольких слов в одну строковую переменную, используются методы getline или get класса istream, объектом которого является поток cin (классы и потоковые классы будут изучены позже):

#include <iostream.h>

int main ( ) {

const int n = 50;

char s[n];

cout << “Введите строку: ”;

cin.getline(s,n);

cout << endl << “Вы ввели строку: ” << s << endl;

cout << “Введите вторую строку: ”;

cin.get(s,n);

cout << endl << “Вы ввели строку: ” << s;

return 0;

}

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

Метод get работает аналогично, но оставляет в потоке символ перевода строки и только после этого добавляет нуль-символ.

Нельзя повторно обращаться к методу get с двумя аргументами не удалив символ \n из входного потока:

сin.get(s,n); // 1 – считывание 1-ой строки

cout << s << endl; // 2 – вывод 1-ой строки

сin.get(s,n); // 3 – считывание 2-ой строки

cout << s << endl; // 4 – вывод 2-ой строки

После выполнения этого фрагмента на экран будет выведена только первая строка, т.к. первый символ, который считает метод get при повторном вызове – символ конца строки, оставленный во входном потоке от первого вызова метода.

Решить эту проблему можно, удалив символ \n их входного потока, вызвав метод get без параметров:

сin.get(s,n); // 1 – считывание 1-ой строки

cin.get(); // 2 – удаление символа новой строки

cout << s << endl; // 3 – вывод 1-ой строки

сin.get(s,n); // 4 – считывание 2-ой строки

cout << s << endl; // 5 – вывод 2-ой строки

Хотя лучше использовать в таких случаях метод getline, удаляющий символ \n из входного потока.

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

#include <iostream.h>

int main ( ) {

const int n = 50;

char s[n];

while (cin.getline(s,n)) { /* обработка строки*/}

return 0;

}

Пример: ввод/вывод символов с помощью потоков С++

#include <iostream.h>

int main ( ){

char с,d;

cout << “Введите два символа: ”

cin >> с >> d;

cout << endl << “Вы ввели: ”с << “ ” << d;

return 0;

}

Вводимые символы должны разделяться пробелmysvb символами, поэтому таким способом ввести такие символы нельзя. Для ввода любого символа можно пользоваться методами get() или get(c):

#include <iostream.h>

int main ( ){

char с,d;

cout << “Введите два символа: ”

с = cin.get(); cin.get(d);

cout << endl << “Вы ввели: ”с << “ ” << d;

return 0;

}

Метод get() возвращает код извлеченного из потока символа или EOF, а метод getc() записывает извлеченный символ в переменную, переданную ему в качестве аргумента, а возвращает ссылку на поток.

Пример: ввод/вывод символов (включая пробельные) с использованием функций языка С

#include <stdio.h>

int main ( ){

char с;

printf(“Введите символ: ”);

с = getchar();

printf(“\nВы ввели: “);

putchar ();

return 0;

}