Лекция: Дублирование строк

В больших программах с множеством строковых переменных слишком утомительно готовить специальные буферы для функции cgets(). Кроме того, эту функцию нельзя использовать под управлением Windows. Хо­рошо бы иметь такую функцию, которая выводила бы приглашение и возвращала строку, введенную с клавиа­туры. Желательно, чтобы эта строка запоминалась в куче, ее можно было бы обрабатывать под управлением Windows и она занимала бы ровно столько байтов, сколько требуется. Долой напрасные затраты памяти!

Листинги 6.3 и 6.4 образуют один маленький модуль с единственной функцией GetStringAt(), которая удовлетворяет этим требованиям, используя другую строковую функцию strdup() для того, чтобы сделать ко­пию вводимой строки. Другие программы в этой главе используют модуль GETS — хороший пример того, как обычные программы запоминания данных могут экономить время, усилия и дисковое пространство.

Файл GETS.H — заголовочный: он содержит только объявления для включения в другие модули. Файл GETS.С — это отдельный модуль, содержащий функцию (их может быть несколько), используемую в програм­ме. Ни один из этих файлов не является законченной программой, поэтому не пытайтесь компилировать и запус­кать их. Ниже будет объяснено, как скомпилировать и скомпоновать модуль GETS в законченную программу.

 

Листинг 6.3. GETS.H (заголовочный файл для GETS.С)

1: /* gets.h — заголовочный файл для gets.с */

2:

3: #define MAXLEN 256 /* Максимальный размер строки */

4:

5: char *GetStrlngAt(int x, int y, int size);

_____________________________________________________

Листинг 6.4. GETS.С (использование модуля получения строки)

1: #include <stdio.h>

2: #include <string.h>

3: #include <conio.h>

4: #include «gets.h»

5:

6: /* Замечание: это не полная программа. Вы должны

7: скомпоновать этот модуль с главной программой. */

8:

9: char *GetStringAt(int x, int y, int size)

10: {

11: static char buffer[MAXLEN]; /* Временный буфер ввода */

12: int i=0; /* Индекс буфера */

13: char с; /* Принимает каждый введенный символ */

14:

15: if ((size > MAXLEN) || (size <= 0)) /* Проверить размер */

16: size = MAXLEN;

17: gotoxy(x, у); /* Установка курсора */

18: while (--size > 0) { /* Ввод строки */

19: с = getchar();

20: if (с == EOF || с == '\n')

21: size = 0;

22: else

23: buffer[i++] = с;

24: }

25: buffer[i] = '\0'; /* Завершение строки нулем */

26: fflush(stdin); /* Опустить «возврат каретки» */

27: return strdup(buffer); /* Возвращение копии строки buffer */

28: }

29:

_______________________________________________________

Модуль в листинге 6.4 включает свой собственный заголовочный файл (строка 4), который определяет константу MAXLEN и объявляет прототип функции GetStringAt() (см. листинг 6.3). В строке 11 листинга 6.4 эта функция объявляет статическую строку buffer. Использование ключевого слова static создает пере­менную, которая постоянно хранится в сегменте данных, но доступна только внутри функции GetStringAt().

Статическая строка buffer служит для запоминания текста, введенного с помощью клавиатуры. Этот текст копируется в новую строку, возвращаемую функцией. Причиной использования именно статической перемен­ной buffer является требование, чтобы функции хватило места для запоминания ввода. Но один недостаток этого метода состоит в том, что буфер перезаписывается при каждом вызове функции, которую, следователь­но, нельзя вызывать рекурсивно. Применение статического буфера не является обязательным условием — вы могли бы написать функцию GetStringAt() с использованием локальной переменной или строки, запомненной в куче (упражнение 6.4).

Оператор if в строке 15 проверяет параметр size. Если его значение находится вне заданного диапазона, то ему присваивается значение MAXLEN.

После позиционирования курсора с помощью вызова функции gotoxy() в строке 17 цикл while в строках 18-24 вызывает функцию getchar(), которая ожидает, пока вы введете символ. Программа присваивает этот символ переменной с и проверяет на совпадение с EOF («end of file», т.е. конец файла, означающий, что ис­точник ввода закрыт) или с управляющим символом \п («новая строка», означающая, что вы нажали <Enter>). Если одно из этих условий оказалось выполненным, программа устанавливает параметр size рав­ным нулю, завершая тем самым цикл while. В противном случае программа присваивает значение переменной с элементу массива buffer с индексом i, инкрементированным оператором ++ для подготовки к вводу следую­щего символа.

В строке 25 добавляется нулевой символ (литеральное выражение '\0') за последним символом, запом­ненным в строке buffer. Строка 26 вызывает функцию fflush(), передавая ей аргумент stdin, который является встроенным символом, представляющим стандартный файл ввода (см. следующую главу). Вызов функции fflush() очищает «повисший» символ новой строки, который может привести к тому, что функция getchar() (и другие функции ввода) не будет делать паузу для ожидания ввода.

И, наконец, строка 27 возвращает результат функции GetStringAt(). Этот оператор передает строку buffer функции strdup(), которая создает копию символов и возвращает адрес дубликата строки.

Функция strdup() (ее название говорит само за себя) возвращает адрес дубликата строки, адресуемой ее аргументом. Строка создается с помощью вызова функции malloc() и занимает столько памяти, сколько необ­ходимо. Если переменная с имеет тип char *, то оператор

с = stгdup(«Двойная тревога»),

выделит ровно 16 байт памяти кучи, скопирует в эту область памяти 15-символьную строку «Двойная тревога» плюс завершающий нуль и возвратит адрес этой области. По окончании работы с этой строкой следует освобо­дить эту область памяти обычным способом:

free(c);

еще рефераты
Еще работы по информатике