Студопедия.Орг Главная | Случайная страница | Контакты | Мы поможем в написании вашей работы!  
 

Операции с текстовыми строками

Массивы

Массив - это совокупность элементов данных одного и того же типа, объединенных общим именем и расположенных в непрерывной области памяти ЭВМ так, что к каждому элементу массива можно получить доступ, зная его порядковый номер или индекс.

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

int a[100], ab[2*40];

double c[200], speed[100];

char name[20];

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

Имя массива с квадратными скобками, в которых записано индексное выражение целого типа, обозначает значение соответствующего элемента массива. В языке Си нумерация элементов массива начинается с нуля, то есть для массива d из пяти элементов допустимы следующие обозначения: d[0], d[1], d[2], d[3], d[4].

Индексированные переменные могут использоваться в любых выражениях в тех местах, где допускается применение переменных соответствующих типов.

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

Язык Си не имеет встроенных средств для ввода-вывода массива целиком, поэтому массив вводят и выводят поэлементно с помощью циклов, как, например, в следующей программе:

#include <stdio.h>

void main(void) {

double a[100];

int n, i;

printf("Введите количество чисел n = ");

scanf("%d", &n);

if(n>(sizeof a)/sizeof(double))

printf("Слишком много элементов\n");

for(i=0; i<n; i++)

{ printf("a[%d] = ", i);

scanf("%lf", &a[i]);

}

}

Во многих случаях удобно возложить на программу подсчет числа элементов, вводимого массива, при этом ввод завершается при появлении во входном потоке признака конца данных. Таким признаком в следующей программе служит число большее 1.0e300

#include <stdio.h>

void main(void) {

double a[100], temp;

int n, end;

for(end=n=0; n<(sizeof a)/sizeof(double); n++)

{ printf("a[%d] = ", n);

scanf("%lf", &temp);

if(temp>=1.0e300)

{ end=1;

break; }

a[n] = temp;

}

if(end)

{/* Операторы, обрабатывающие массив */ }

else

printf("Переполнение массива\n");

}

Вывод массива, содержащего большое количество элементов желательно производить в несколько строк с остановом после заполнения экрана.

Следующий фрагмент программы выводит массив строками по 5 элементов. После вывода 120 элементов программа останавливается для просмотра выдачи. Очередные
120 элементов выводятся после нажатия на любую клавишу.

for (i=0; i<n; i++)

{ printf("%10.3lf ", a[i]);

if((i+6) % 5 == 0)

printf("\n");

if((i+121) % 120 == 0)

{ getch();

clrscr(); }

}

Здесь стандартная функция clrscr() очищает экран.

Инициализация – присвоение значений вместе с описанием данных. Ранее была рассмотрена инициализация простых переменных, например:

int a = 5;

Для инициализации массива за его именем располагают знак присваивания и список инициализации, который представляет собой заключенные в фигурные скобки и разделенные запятыми инициализирующие значения. Ниже приведен пример инициализации массива:

int a[4]={ 15, 21, 1, 304 };

индексы элементов ® 0 1 2 3

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

int c[] = { 1, 15, 18, 11, 20 };

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

char s[] = { 'A', 'B', 'C', 'D', '\0' };

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

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

char s[] = "ABCD";

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

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

#include <stdio.h>

void main (void) {

int len;

char str[81];

printf("Введите строку: ");

scanf("%s", str);

for(len=0; str[len]; len++);

printf("Длина строки = %d\n", len);

}

В этой программе используется цикл for с пустым оператором тела цикла. Цикл будет выполняться до тех пор, пока в строке не встретится нуль-символ, то есть пока выражение str[len] будет отлично от нуля. После окончания цикла переменная len станет равной количеству символов строки str, исключая нуль-символ.

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

int StrLen (char str[])

{ int len;

for(len=0; str[len]; len++);

return len;

}

При наличии функции StrLen последний оператор предыдущей программы можно заменить на printf("Длина строки = %d\n", StrLen(str));

Элементом массива может быть и массив. Таким образом, мы приходим к понятию двумерного массива или матрицы. Описание двумерного массива строится из описания одномерного путем добавления второй размерности, например:

int a[4][3];

Переменная a является массивом из четырех элементов, что следует из первой части описания a[4]. Каждый элемент a[i] этого массива в свою очередь является массивом из трех элементов типа int, что следует из второй части описания.

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

Массив а Столбец 0 Столбец 1 Столбец 2
Строка 0      
Строка 1      
Строка 2      
Строка 3      

Имя двумерного массива без квадратных скобок за ним имеет значение адреса первого элемента этого массива, то есть значение адреса первой строки – одномерного массива из трех элементов. При использовании в выражениях тип имени двумерного массива преобразуется к типу адреса строки этого массива. В нашем примере тип имени массива a в выражениях будет приведен к типу адреса массива из трех элементов типа int и может использоваться во всех выражениях, где допускается использование соответствующего адреса.

Имя двумерного массива с одним индексным выражением в квадратных скобках за ним обозначает соответствующую строку двумерного массива и имеет значение адреса первого элемента этой строки. Например, в нашем случае a[2] является адресом величины типа int, а именно ячейки, в которой находится число 30, и может использоваться везде, где допускается использование адреса величины типа int.

Имя двумерного массива с двумя индексными выражениями в квадратных скобках за ним обозначает соответствующий элемент двумерного массива и имеет тот же тип. Например, в нашем примере a[2][1] является величиной типа int, а именно ячейкой, в которой находится число 52, и может использоваться везде, где допускается использование величины типа int.

В соответствии с интерпретацией описания двумерного массива (слева-направо) элементы массива располагаются в памяти ЭВМ по строкам. Инициализация двумерного массива также проводится по строкам, например, для того чтобы получить вышеописанный массив a, можно было бы провести следующую инициализацию

int a[][3] = {

{ 18, 21, 5 },

{ 6, 7, 11 },

{ 30, 52, 34 },

{ 24, 4, 67 } };

Здесь первый размер массива будет определен компилятором. Следует отметить, что второй размер массива должен быть всегда указан. Это необходимо для того, чтобы сообщить компилятору размер строки массива, без которого компилятор не может правильно разместить двумерный массив в памяти ЭВМ. Для инициализации двумерного массива символов можно использовать упрощенный синтаксис инициализации строк:

char s[][17] = {

"Строка 1",

"Длинная строка 2",

"Строка 3"

}

Размер памяти, заказанный под каждую строку в этом случае должен быть равным длине самой длинной строки с учетом нуль-символа. При этом для части строк (строка 1 и строка 3) будет выделено излишнее количество памяти. Таким образом, хранение строк различной длины в двумерном массиве символов недостаточно эффективно с точки зрения использования памяти.

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

for (i=0; i<n; i++)

{ for (j=0; j<m; j++)

{ printf("a[%d][%d] = ", i, j);

scanf ("%lf", &a[i][j]);

}

}

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

for (i=0; i<n; i++)

{ for (j=0; j<m; j++)

{ printf ("%9.3lf ", a[i][j]);

printf("\n"); }

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

Операции с текстовыми строками

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

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

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

Рис. 1. Последовательность действий при выполнении операции вставки символа

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

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

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

Рис. 2. Последовательность действий при выполнении операции удаления символа

Текст представляет собой двумерный массив символов, содержащий строки. Недостатки такого примитивного способа хранения данных:

- неэффективное использование памяти;

- необходимость перемещения большого объема информации при добавлении и удалении строк.

-

Стандартные функции для обработки строк

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

Описания строковых функций находятся в заголовочном файле string.h, который необходимо подключить директивой #include в начале программы..

Рассмотрим функции, которые используются наиболее часто.

Функция strcat добавляет одну строку к другой. Функция объявлена следующим образом:

char *strcat(char *dest, const char *src);

Функция добавляет копию строки src в конец dest и возвращает указатель на результирующую строку.

Функция strchr ищет в строке первое вхождение заданного символа. Функция объявлена следующим образом:

char *strchr(const char *s, int c);

Функция ищет первое вхождение символа с в строку s. Она возвращает указатель на первое вхождение символа с в строку s; если c не обнаружен, то strchr возвращает NULL.

Функция strcmp сравнивает одну строку с другой. Функция объявлена следующим образом:

int strcmp(const char *s1, const char *s2);

Функция strcmp осуществляет сравнение строк s1 и s2, начиная с первого символа каждой строки, до тех пор, пока очередные соответствующие символы в строках не будут различны или пока не будут достигнуты концы строк. Функция возвращает отрицательное значение, если s1 меньше чем s2, ноль, если s1 равна s2, и положительное значение, если s1 больше чем s2

Функция strcpy копирует одну строку в другую. Функция объявлена следующим образом:

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

Функция копирует строку src в dest и возвращает dest.

Функция strlen вычисляет длину строки. Функция объявлена следующим образом:

size_t strlen(const char *s);

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

Функция strstr ищет в строке вхождение заданной подстроки. Функция объявлена следующим образом:

char *strstr(const char *s1, const char *s2);

Функция осуществляет поиск в s2 первого вхождения подстроки s1. Функция возвращает указатель на элемент в строке s1, с которого начинается s2. Если s2 не обнаружена в s1, функция возвращает NULL.


Дата публикования: 2015-11-01; Прочитано: 333 | Нарушение авторского права страницы | Мы поможем в написании вашей работы!



studopedia.org - Студопедия.Орг - 2014-2024 год. Студопедия не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования (0.014 с)...