Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015

Здесь есть возможность читать онлайн «Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Год выпуска: 0101, Издательство: Вильямс, Жанр: Старинная литература, на русском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.

Язык программирования C. Лекции и упражнения (6-е изд.) 2015: краткое содержание, описание и аннотация

Предлагаем к чтению аннотацию, описание, краткое содержание или предисловие (зависит от того, что написал сам автор книги «Язык программирования C. Лекции и упражнения (6-е изд.) 2015»). Если вы не нашли необходимую информацию о книге — напишите в комментариях, мы постараемся отыскать её.

Язык программирования C. Лекции и упражнения (6-е изд.) 2015 — читать онлайн бесплатно полную книгу (весь текст) целиком

Ниже представлен текст книги, разбитый по страницам. Система сохранения места последней прочитанной страницы, позволяет с удобством читать онлайн бесплатно книгу «Язык программирования C. Лекции и упражнения (6-е изд.) 2015», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Символьные массивы или указатели на char в структурах

В рассмотренных ранее примерах для хранения строк в структуре применялись символьные массивы. Вероятно, вас интересует, можно ли вместо них использовать указатели на char? Например, в листинге 14.3 имеется следующее объявление:

#define LEN 20

struct names {

char first[LEN]; char last[LEN];

};

Можно ли вместо этого поступить так?

struct pnames { char * first; char * last;

};

Ответ — да, это возможно, но могут возникнуть проблемы, если вы не обдумаете все последствия. Взгляните на показанный ниже код:

struct names veep = {"Talia", "Summers"};

struct pnames treas = {"Brad", "Fallingjaw"};

printf("%s и %s\n", veep.hrst, treas.hrst);

588 Глава 14

Этот код допустим, и он работает, однако рассмотрим, где хранятся строки. В случае переменной veep типа struct names строки хранятся внутри структуры; для хранения двух имен структура выделяет всего 40 байтов. Тем не менее, в переменной treas типа struct pnames строки хранятся там, где компилятор сохраняет строковые константы. Все, что содержит данная структура — это два адреса, которые в нашей системе в целом занимают 16 байтов. В частности, структура struct pnames не выделяет память для хранения строк. Она может применяться только со строками, для которых память была выделена где-то в другом месте, такими как строковые константы или строки в массивах. Короче говоря, указатели в структуре struct pnames должны использоваться только для управления строками, которые были созданы с выделением под них памяти в другом месте программы.

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

struct names accountant;

struct pnames attorney;

puts("Введите фамилию вашего бухгалтера );

scanf("%s", accountant.last);

puts("Введите фамилию вашего адвоката:");

scanf("%s", attorney.last); /* здесь скрыта опасность */

С точки зрения синтаксиса этот код допустим. Но куда сохраняются входные данные? Фамилия бухгалтера записывается в последний член переменной accountant; эта структура содержит массив для хранения строки. В случае фамилии адвоката функция scanf() получает указание поместить строку фамилии но адресу, заданному как attorney. last. Из-за того, что эта переменная не инициализирована, адрес может иметь произвольное значение, и программа может попытаться поместить фамилию куда угодно. Если повезет, то программа будет работать, по крайней мере, некоторое время, либо сразу же аварийно завершится. Однако если программа работает, то вам на самом деле не повезло, т.к. в ней присутствует катастрофическая ошибка, о которой вы не знаете.

Таким образом, если вам необходима структура для хранения строк, то проще применять члены типа символьных массивов. Использование указателей на char в отдельных случаях допускается, но потенциально сопряжено с серьезными проблемами.

Структура, указатели и malloc()

Применение в структуре указателя, поддерживающего строку, имеет смысл, когда с помощью функции malloc() для строки выделяется область памяти и указатель используется, чтобы сохранить адрес этой области. Преимущество такого подхода заключается в том, что malloc() позволяет выделить ровно столько памяти, сколько необходимо для строки. Вы можете запросить 4 байта для сохранения строки "Joe" и 18 байтов для строки с мадагаскарским именем "Rasolofomasoandro". Код в листинге 14.9 совсем нетрудно адаптировать под этот подход. Два основных изменения касаются определения структуры с целью применения указателей вместо массивов и предоставления новой версии функции getinfo().

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

struct namect {

char * fname; // использование указателей вместо массивов char * lname; int letters;

};

Структуры и другие формы данных 589

Новая версия getinfo() будет читать входные данные во временный массив, использовать malloc() для выделения пространства памяти и копировать в него строку. Она будет делать это для каждого имени:

void getinfo (struct namect * pst)

{

char temp[SLEN];

printf("Введите свое имя.\n");

s_gets(temp, SLEN);

// выделение памяти для хранения имени pst->fname = (char *) malloc(strlen(temp) + 1);

// копирование имени в выделенную память strcpy(pst->fname, temp); printf("Введите свою фамилию.\n"); s_gets(temp, SLEN);

pst->lname = (char *) malloc(strlen(temp) + 1); strcpy(pst->lname, temp);

}

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

Однако, согласно совету из главы 12, вы должны уравновешивать вызовы malloc() вызовами free() , поэтому в программу добавлена новая функция по имени cleanup(), которая освобождает память, когда программа завершает пользоваться ею. Вы найдете эту новую функцию и оставшуюся часть программы в листинге 14.10.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Похожие книги на «Язык программирования C. Лекции и упражнения (6-е изд.) 2015»

Представляем Вашему вниманию похожие книги на «Язык программирования C. Лекции и упражнения (6-е изд.) 2015» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.


Отзывы о книге «Язык программирования C. Лекции и упражнения (6-е изд.) 2015»

Обсуждение, отзывы о книге «Язык программирования C. Лекции и упражнения (6-е изд.) 2015» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.

x