Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
учебное пособие ОАиП.doc
Скачиваний:
11
Добавлен:
25.04.2019
Размер:
2.63 Mб
Скачать

Символьные строки

Под строкой будем понимать совокупность непрерывно расположенных в памяти символов (ASCII-кодов). В С(С++) отсутствует тип данных символьная строка. Механизм работы со строками обычно реализуется через указатели типа char*:

char* str;

Это указатель на область памяти, каждый элемент которой имеет размер один байт. Как и обычный указатель, указатель на тип char может быть инициализирован при его описании. Для этого используется строковая константа, при этом адрес ее первого символа будет присвоен указателю, например:

char *str="строка";

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

Также можно создать массив указателей типа char (массив строк).

char *str[5]; // массив из 5-ти указателей

Инициализацию массива строк (массива указателей char*) можно выполнить следующим образом:

char str1[][8]={"строка1","строка2"};

char *str2[2];

str2[0]="строка1";

str2[1]="строка2”;

сhar *str3[2]={ "строка1","строка2"};

Строковая константа, как и любая другая константа в С(С++), может быть также определена с помощью директивы #define, например:

#define st1 "Минск"

#define st2 "каф. ЭВМ"

В чем состоит отличие объявления символьной строки через указатель на тип char и с использованием массива типа char. Эти два подхода имеют общие стороны: имя массива является адресом его начала, указатель также содержит адрес начала некоторой области памяти. В то же время имя массива (например, mas) является константным значением. То есть мы не можем изменить значение mas, так как это по существу означало бы изменение адреса массива в памяти. Следовательно, для доступа к очередному элементу массива можно использовать выражение вида mas+1, но не ++mas.

При использовании указателей происходит выделение в динамической памяти области для размещения в ней строки, а переменная str, являющаяся указателем на эту область (строку) размещается в статической памяти. При этом значение этой переменной может изменяться, таким образом, ++str будет указывать на следующий символ строки.

Ввод/вывод строк.

Ранее мы подробно останавливались на функциях ввода/вывода информации (scanf(), printf(), getchar(), putchar()). Они могут быть с успехом использованы для организации ввода/вывода символьных строк. Кроме этих функций, в С(С++) имеется еще пара функций (gets(), puts()), предназначенных для ввода/вывода символьных строк. Функция gets читает все символы до тех пор, пока во входном потоке не встретится символ '\n' ('\13') - нажатие клавиши Enter, после этого символ '\n' заменяется на ноль-символ ('\0') и функция gets передает введенную строку символов вызывающей функции. Ниже рассмотрен пример с несколькими вариантами использования функции gets():

#include <stdio.h>

void main() // функция определения длины строки

{ char s[5];

char *st;

// вариант 1 ввода строки s

gets(s); // ввод строки s

st=s; // st указывает на строку s

printf("\n s=%s *st=%s",s,st);

// вариант 2 ввода строки s

st=gets(s); // ввод строки s и указателя st на нее одновременно

printf("\n s=%s *st=%s",s,st);

}

Во втором варианте ввода сроки gets возвращает не только символьную строку s, но и инициализирует указатель на нее st. В первом варианте для получения адреса строки s в st выполняли st=s. Если в приведенном примере использовать в качестве аргумента в функции gets() указатель st, то он должен быть до этого инициализирован, например:

st=(сhar *) malloc(sizeof(char)*5); либо st=(сhar *) malloc(5);

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

Кроме того, функция gets() включает разряд проверки ошибки. То есть если произошла ошибка ввода или gets() встретила символ EOF, она возвращает нулевой адрес (NULL). Это упрощает контроль на EOF:

char s[10];

while(gets(s)!=NULL);

по сравнению с тем, как это выполняется при использовании функции getchar():

char s;

while((s=getchar())!=EOF);

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

fflush(stdin);

так как некоторые функции ввода считывают данные из буфера до символа '\13', оставляя его в буффере. А функция gets считывая его прекращает ввод информации. При этом строка может оказаться пустой. Поэтому желательно очистить буффер перед вводом в него информации.

Инициализацию строки можно выполнить и с помощью функции scanf используя указатель:

char *st ;

st=(сhar *) malloc(10);

scanf("%s",st);

ввод символьной строки завершается при встрече либо символа ' ',либо символа '\n'.

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

char st[5];

. . . ( тело функции )

puts(st);

Для правильной работы программы следует соблюдать следующие требования:

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

  • Копирование строк с использованием не проинициализированного указателя – является грубой ошибкой программирования.

  • При работе со строками, требуется обращать внимание на предупреждение типа " Подозрительное преобразование указателя " ( Suspicious pointer conversion ) или "Использование указателя до инициализации"(Possible use of...before deffinition).

  • При выделении места для строки-назначения следует предусмотреть место для признака конца строки ( ‘\0’ ).

При написании программ обычно необходимо производить разные манипуляции со строками: перемещать их с одного места памяти в другое, выполнять поиск в строке некоторой последовательности символов, объединять строки, вставлять одну строку в другую, удалять из строки часть информации и т.д. В С(С++) имеется набор функций обеспечивающих эти и другие действия.