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

9

Тема 7. Строки, потоки, файлы.

1. Строки.

В С и С++ отсутствуют встроенные строковые типы в том смысле, в котором они есть в языках типа Basic и Pascal. И присущая этим языкам легкость оперирования строковыми переменными (присвоение, сравнение) в С недоступна. Что же такое строка в С?

Для начала разберемся, что такое строка в жизни. Очевидно, что строка – это последовательность символов. В С – как в жизни. С-строка — это последовательность символов. Как известно, последовательности в С представляются массивами или указателями.

Как известно:

- массив можно привести к указателю на его первый элемент, что неявно происходит при передаче массивов в функции, ожидающие указатели;

- информация о размере массива переданного таким образом в функцию теряется;

- в С не существует способа передать массив по значению с сохранением его размера;

- указателя на первый элемент массива достаточно для работы со всем массивом, при условии, что нам известна его длина.

То есть в С строка – это массив элементов типа char, ограниченный символом с кодом 0, называемом нуль-терминатором. Напомню, что c массивом элементов типа char связан указатель на char, поэтому С-строка– это еще и указатель типа char* на область памяти, заканчивающуюся символом с кодом 0.

1.1. Создание строк

char str1[10];

Строка - массив из 10 символов. Начальное значение символов не определено.

char str2[10]="Hello";

Используется инициализация. В первые 5 символов записывается “Hello”, в 6 – нуль-терминатор, значение трех последних не определено.

char str3[10]={'H', 'e', 'l', 'l', 'o', '\0'};

Эквивалентно предыдущему.

char str4[10]="Very long line";

Ошибка. Массив из 10 элементов нельзя инициировать более длинной последовательностью.

char str5[]="Very long line";

Компилятор автоматически определяет длину массива (в нашем случае 15) и инициализирует его последовательностью символов

char* str6;

Строка - указатель на символ. В большинстве случаев для ее использования потребуется выделить память.

1.2. Присваивание строк

Примеры неправильного присваивания строк:

char str1[10], str2[10];

str1="Hello";

str2=str1;

Одна и та же ошибка в обоих операторах “=”, имя массива нельзя использовать в левой части оператора присваивания.

Эта ошибка относительно безопасна, так как приводит к сбою на этапе компиляции. Есть и гораздо более опасная ошибка.

char str1[10]= "Hello";

char* str2;

str2=str1;

str2[1]='u';

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

Еще один рискованный вариант присваивания указателей – присваивание их строковым литералам. Тип строкового литерала – const char*. Стандарт С++ разрешает присваивание без спецификации const. Что может иметь неприятные последствия:

char* str;

str="Hello";

str[3]=’p’;

str[4]=’!’;

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

Вопросы неправильного и рискованного присваивания строк мы рассмотрели. Теперь о правильном присваивании или копировании строк.

Первый и самый очевидный способ присваивания строк – присваивание отдельных символов. Например,

str1[0]=’H’;

str1[1]=’e’;

str1[2]=’l’;

str1[3]=’l’;

str1[4]=’o’;

str1[5]=’\0’;

Однако, это совершенно неудобно.

Для копирования строк существуют несколько библиотечных функций, наиболее общеупотребительной из которых является функция strcpy (библиотека string.h).

char* strcpy(char* dest, char* src)

Функция посимвольно копирует содержимое строки, на которую указывает src в строку, на которую указывает dest и возвращает dest. Так как массив может быть преобразован в указатель, такой вызов функции абсолютно легален:

char str1[10], str2[10];

strcpy(str1, "Hello");

strcpy(str2, str1);

При использовании этой функции следует соблюдать осторожность. Опасность заключается в том, что даже если исходная строка окажется больше, чем память, выделенная для второй строки (программистом через malloc или компилятором при использовании массивов), функция strcpy никак про это узнать не сможет и продолжит копирование в невыделенную память. Разумеется, последствия будут катастрофическими.

Снизить риск такого развития событий способна функция

char* strncpy(char* dest, char* src, int count)

Последний параметр – максимальное количество копируемых символов. Таким образом, передавая туда размер приемника, вы гарантируете, что функция никогда не выйдет за пределы выделенной памяти. Однако, если исходная строка будет скопирована не полностью, нуль-терминатор не появится в результирующей строке. Его придется записать самостоятельно.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]