Брайан Керниган - Язык программирования Си. Издание 3-е, исправленное

Тут можно читать онлайн Брайан Керниган - Язык программирования Си. Издание 3-е, исправленное - бесплатно полную версию книги (целиком) без сокращений. Жанр: comp-programming, издательство Невский Диалект, год 2001. Здесь Вы можете читать полную версию (весь текст) онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    Язык программирования Си. Издание 3-е, исправленное
  • Автор:
  • Жанр:
  • Издательство:
    Невский Диалект
  • Год:
    2001
  • Город:
    Санкт-Петербург
  • ISBN:
    0-13-110362-8
  • Рейтинг:
    4.11/5. Голосов: 91
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

Брайан Керниган - Язык программирования Си. Издание 3-е, исправленное краткое содержание

Язык программирования Си. Издание 3-е, исправленное - описание и краткое содержание, автор Брайан Керниган, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

Книга широко известных авторов, разработчиков языка Си, переработанная и дополненная с учетом стандарта ANSI для языка Си, 2-е английское издание которой вышло в 1988 году, давно стала классикой для всех изучающих и/или использующих как Си, так и Си++. Русский перевод этой книги впервые был выпущен изд- вом "Финансы и статистика" в 1992 г. и с тех пор пользуется неизменным спросом читателей.

Для настоящего третьего русского издания перевод заново сверен с оригиналом, в него внесены некоторые поправки, учитывающие устоявшиеся за прошедшие годы изменения в терминологии, а так же учтены замечания, размещенные автором на странице http://cm.bell-labs.com/cm/cs/cbook/2ediffs.html.

Для программистов, преподавателей и студентов.

Издание подготовлено при участии издательства "Финансы и статистика"

Язык программирования Си. Издание 3-е, исправленное - читать онлайн бесплатно полную версию (весь текст целиком)

Язык программирования Си. Издание 3-е, исправленное - читать книгу онлайн бесплатно, автор Брайан Керниган
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

#include ‹sys/stat.h› /* структура, возвращаемая stat */

#include "dirent.h"

void fsize(char *);

/* печатает размер файлов */

main(int argc, char **argv) {

if (argc == 1) /* по умолчанию берется текущий каталог */

fsize(".");

else

while (--argc › 0)

fsize(*++argv);

return 0;

}

Функция fsize печатает размер файла. Однако, если файл - каталог, она сначала вызывает dirwalk , чтобы обработать все его файлы. Обратите внимание на то, как используются имена флажков S_IFMT и S_IFDIR из ‹sys/stat.h› при проверке, является ли файл каталогом. Здесь нужны скобки, поскольку приоритет оператора & ниже приоритета оператора ==.

int stat(char *, struct stat *);

void dirwalk(char *, void (*fcn)(char *));

/* fsize: печатает размер файла "name" */

void fsize(char *name)

{

struct stat stbuf;

if (stat(name, &stbuf) == -1) {

fprintf(stderr, "fsize: нет доступа к %s\n", name);

return;

}

if ((stbuf.st_mode & S_IFMT) == S_IFDIR)

dirwalk(name, fsize);

printf("%8ld%s\n", stbuf.st_size, name);

}

Функция dirwalk - это универсальная программа, применяющая некоторую функцию к каждому файлу каталога. Она открывает каталог, с помощью цикла перебирает содержащиеся в нем файлы, применяя к каждому из них указанную функцию, затем закрывает каталог и осуществляет возврат. Так как fsize вызывает dirwalk на каждом каталоге, в этих двух функциях заложена косвенная рекурсия.

#define MAX_PATH 1024

/* dirwalk: применяет fcn ко всем файлам из dir */

void dirwalk(char *dir, void (*fcn)(char *))

{

char name[MAX_PATH];

Dirent *dp;

DIR *dfd;

if ((dfd = opendir(dir)) == NULL) {

fprintf(stderr, "dirwalk: не могу открыть %s\n", dir);

return;

}

while ((dp = readdir(dfd)) != NULL) {

if (strcmp(dp-›name, ".") == 0 || strcmp(dp-›name, "…") == 0)

continue; /* пропустить себя и родителя */

if (strlen(dir)+strlen(dp-›name) + 2 › sizeof(name))

fprintf(stderr, "dirwalk: слишком длинное имя %s/%s\n", dir, dp-›name);

else {

sprintf(name, "%s/%s", dir, dp-›name);

(*fcn) (name);

}

}

closedir(dfd);

}

Каждый вызов readdir возвращает указатель на информацию о следующем файле или NULL, если все файлы обработаны. Любой каталог всегда хранит в себе информацию о себе самом в файле под именем "." и о своем родителе в файле под именем "…": их нужно пропустить, иначе программа зациклится. Обратите внимание: код программы этого уровня не зависит от того, как форматированы каталоги. Следующий шаг - представить минимальные версии opendir , readdir и closedir для некоторой конкретной системы. Здесь приведены программы для систем Version 7 и System V UNIX. Они используют информацию о каталоге, хранящуюся в заголовочном файле ‹sys/dir.h›, который выглядит следующим образом:

#ifndef DIRSIZ

#define DIRSIZ 14

#endif

struct direct /* элемент каталога */

{

ino_t d_ino; /* номер inode */

char d_name[DIRSIZ]; /* длинное имя не имеет '\0' */

};

Некоторые версии системы допускают более длинные имена и имеют более сложную структуру каталога.

Тип ino_tзадан с помощью typedef и описывает индекс списка узлов node . В системе, которой пользуемся мы, этот тип есть unsigned short , но в других системах он может быть иным, поэтому его лучше определять через typedef . Полный набор "системных" типов находится в ‹sys/types.h›.

Функция opendir открывает каталог, проверяет, является ли он действительно каталогом (в данном случае это делается с помощью системного вызова fstat , который аналогичен stat , но применяется к дескриптору файла), запрашивает пространство для структуры каталога и записывает информацию.

int fstat(int fd, struct stat *);

/* opendir: открывает каталог для вызовов readdir */

DIR *opendir(char *dirname)

{

int fd;

struct stat stbuf;

DIR *dp;

if ((fd = open(dirname, O_RDONLY, 0)) == -1 || fstat(fd, &stbuf) == -1 || (stbuf.st_mode & S_IFMT) != S_IFDIR || (dp = (DIR *) malloc(sizeof(DIR))) == NULL)

return NULL;

dp-›fd = fd;

return dp;

}

Функция closedir закрывает каталог и освобождает пространство.

/* closedir: закрывает каталог, открытый opendir */

void closedir(DIR *dp) {

if (dp) {

close(dp-›fd);

free(dp);

}

}

Наконец, readdir с помощью read читает каждый элемент каталога. Если некий элемент каталога в данный момент не используется (соответствующий ему файл был удален), то номер узла inode у него равен нулю, и данная позиция пропускается. В противном случае номер inode и имя размещаются в статической ( static ) структуре, и указатель на нее выдается в качестве результата. При каждом следующем обращении новая информация занимает место предыдущей.

#include ‹sys/dir.h› /* место расположения структуры каталога */

/* readdir: последовательно читает элементы каталога */

Dirent *readdir(DIR *dp) {

struct direct dirbuf; /* структура каталога на данной системе */

static Dirent d; /* возвращает унифицированную структуру */

while (read(dp-›fd, (char *)&dirbuf, sizeof (dirbuf)) == sizeof(dirbuf)) {

if (dirbuf.d_ino == 0) /* пустой элемент, не используется */

continue;

d.ino = dirbuf.d_ino;

strncpy(d.name, dirbuf.d_name, DIRSIZ);

d.name[DIRSIZ] = '\0'; /* завершающий символ '\0' */

return &d;

}

return NULL;

}

Хотя программа fsize - довольно специализированная, она иллюстрирует два важных факта. Первый: многие программы не являются "системными"; они просто используют информацию, которую хранит операционная система. Для таких программ существенно то, что представление информации сосредоточено исключительно в стандартных заголовочных файлах. Программы включают эти файлы, а не держат объявления в себе. Второе наблюдение заключается в том, что при старании системно-зависимым объектам можно создать интерфейсы, которые сами не будут системно-зависимыми. Хорошие тому примеры ~ функции стандартной библиотеки.

Упражнение 8.5. Модифицируйте fsize таким образом, чтобы можно было печатать остальную информацию, содержащуюся в узле inode .

8.7 Пример. Распределитель памяти

В главе 5 был описан простой распределитель памяти, основанный на принципе стека. Версия, которую мы напишем здесь, не имеет ограничений: вызовы mallocи freeмогут выполняться в любом порядке: malloc делает запрос в операционную систему на выделение памяти тогда, когда она требуется. Эти программы иллюстрируют приемы, позволяющие получать машинно-зависимый код сравнительно машинно-независимым способом, и, кроме того, они могут служить примером применения таких средств языка, как структуры, объединения и typedef.

Никакого ранее скомпилированного массива фиксированного размера, из которого выделяются куски памяти, не будет. Функция malloc запрашивает память у операционной системы по мере надобности. Поскольку и другие действия программы могут вызывать запросы памяти, которые удовлетворяются независимо от этого распределителя памяти, пространство, которым заведует malloc , необязательно представляет собой связный кусок памяти. Поэтому свободная память хранится в виде списка блоков. Каждый блок содержит размер, указатель на следующий блок и само пространство. Блоки в списке хранятся в порядке возрастания адресов памяти, при этом последний блок (с самым большим адресом) указывает на первый.

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

Интервал:

Закладка:

Сделать


Брайан Керниган читать все книги автора по порядку

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




Язык программирования Си. Издание 3-е, исправленное отзывы


Отзывы читателей о книге Язык программирования Си. Издание 3-е, исправленное, автор: Брайан Керниган. Читайте комментарии и мнения людей о произведении.


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

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