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

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

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

Язык программирования C. Лекции и упражнения (6-е изд.) 2015 - описание и краткое содержание, автор Стивен Прата, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

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

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

Интервал:

Закладка:

Сделать

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

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.

Листинг 14.10. Программа names3.c

590 Глава 14 Ниже показан пример вывода Введите свое имя Васисуалий - фото 442

590 Глава 14

Ниже показан пример вывода Введите свое имя Васисуалий Введите свою фамилию - фото 443

Ниже показан пример вывода:

Введите свое имя.

Васисуалий

Введите свою фамилию.

Лоханкин

Васисуалий Лоханкин, ваше имя и фамилия содержат 18 букв.

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

Составные литералы и структуры (С99)

Средство составных литералов С99 доступно для структур, а также для массивов. Оно удобно, если требуется всего лишь временное значение структуры. Например, составные литералы можно применять для создания структуры, предназначенной для использования в качестве аргумента функции или для присваивания другой струк туре. Синтаксис составного литерала выглядит как заключенный в фигурные скобки список инициализаторов, которому предшествует имя типа в круглых скобках. Ниже представлен составной литерал типа struct book:

(struct book) {"Идиот", "Федор Достоевский", 6.99}

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

Листинг 14.11. Программа complit.c

Составные литералы можно использовать также как аргументы функций Если функция - фото 444

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

struct rect {double х; double у,();

double rect_area(struct rect r){return r.x * r.y;)

double area;

area = rect_area ( (struct rect) {10.5, 20.0});

592 глава 14

Это приводит к тому, что area присваивается значение 210.0.

Если функция ожидает адрес, то ей можно передать адрес составного литерала:

В результате переменная area получает значение 2100 Составные литералы - фото 445

В результате переменная area получает значение 210.0.

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

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

Интервал:

Закладка:

Сделать


Стивен Прата читать все книги автора по порядку

Стивен Прата - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




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


Отзывы читателей о книге Язык программирования C. Лекции и упражнения (6-е изд.) 2015, автор: Стивен Прата. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x