Главная · Поиск книг · Поступления книг · Top 40 · Форумы · Ссылки · Читатели

Настройка текста
Перенос строк


    Прохождения игр    
Demon's Souls |#13| Storm King
Demon's Souls |#11| Мaneater part 2
Demon's Souls |#10| Мaneater (part 1)
Demon's Souls |#9| Heart of surprises

Другие игры...


liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня
Rambler's Top100
Образование - Богатырев А. Весь текст 1009.15 Kb

Хрестоматия по программированию на Си в Unix

Предыдущая страница Следующая страница
1 ... 52 53 54 55 56 57 58  59 60 61 62 63 64 65 ... 87
            if  ( strcmp (key, TREE -> data.key) < 0 )
            {
                    /*  добавить в левое поддерево    */
                    if ( TREE -> l == NULL ){
                            /* нет левого дерева  */
                            TREE -> l = newNode(key);
                            return;
                    }
                    else addnode( & TREE ->l , key);
            }

А. Богатырев, 1992-95                  - 303 -                              Си в UNIX

            else{
                    /* добавить в правое дерево  */
                    if ( TREE -> r == NULL ){
                            /* нет правого поддерева */
                            TREE -> r = newNode(key);
                            return;
                    }
                    else addnode ( & TREE ->r, key) ;
            }
    }

    /* Процедура удаления из дерева по ключу. */
    typedef struct node *NodePtr;
    static NodePtr delNode;    /* удаляемая вершина */

    void delete(key, tree)
      char *key;          /* ключ удаляемого элемента */
      NodePtr *tree;      /* из какого дерева удалять */
    {
         extern void doDelete();
         if(*tree == NULL){
              printf( "%s не найдено\n", key ); return;
         }
         /* поиск ключа */
         else if(strcmp(key, (*tree)->data.key) < 0)
              delete( key, &(*tree)->l );
         else if(strcmp(key, (*tree)->data.key) > 0)
              delete( key, &(*tree)->r );
         else{  /* ключ найден */
              delNode = *tree;  /* указатель на удаляемый узел */
              if(delNode->r == NULL)      *tree = delNode->l;
              else if(delNode->l == NULL) *tree = delNode->r;
              else doDelete( & delNode->l );
              free(delNode);
         }
    }

    static void doDelete(rt) NodePtr *rt;
    {
            if( (*rt)->r != NULL )    /* спуск по правой ветви */
                doDelete( &(*rt)->r );
            else{
                /* перенос данных в другой узел */
                delNode->data = (*rt)->data;

                delNode = *rt;         /* для free() */
                *rt = (*rt)->l;
            }
    }

А. Богатырев, 1992-95                  - 304 -                              Си в UNIX

    void main(){
            extern char *gets(); char *s;
            while (gets(buf) != NULL){      /* пока не конец файла */
                    lines++;
                    addnode( & root, buf );
            }
            prTree(root);

            /* удалим строку */
            freopen("/dev/tty", "r", stdin);
            do{
                printf( "что удалить ? " );
                if((s = gets(buf)) == NULL) break;
                delete(buf, &root);
                prTree( root );
            } while( s && root );

            printf("Bye-bye.\n");
            exit(0);
    }

7.37.  Напишите программу, которая читает со стандартного ввода 10 чисел либо слов, а
затем распечатывает их. Для хранения введенных данных используйте объединение.

    #include 
    #include 
    #define INT 'i'
    #define STR 's'
    struct data {
      char tag;  /* тэг, пометка. Код типа данных. */
      union {
            int i;
            char *s;
      } value;
    } a[10];
    int counter = 0; /* счетчик */
    void main(){
      char word[128]; int i; char *malloc(unsigned);

      /* Чтение: */
      for(counter=0; counter < 10; counter++){
        if( gets(word) == NULL ) break;
        if( isdigit((unsigned char) *word)){
            a[counter].value.i = atoi(word);
            a[counter].tag     = INT;
        } else {
            a[counter].value.s = malloc(strlen(word)+1);
            strcpy(a[counter].value.s, word);
            a[counter].tag     = STR;
        }
      }
      /* Распечатка: */
      for(i=0; i < counter; i++)
        switch(a[i].tag){
        case INT: printf("число %d\n", a[i].value.i);
                  break;
        case STR: printf("слово %s\n", a[i].value.s);
                  free(a[i].value.s);
                  break;
       }

А. Богатырев, 1992-95                  - 305 -                              Си в UNIX

    }

7.38.  Рассмотрим задачу написания функции,  которая  обрабатывает  переменное  число
аргументов,  например  функцию-генератор  меню.  В такую функцию надо подавать строки
меню и адреса функций, вызываемых при выборе каждой из строк.   Собственно  проблема,
которую  мы  тут  обсуждаем  -  как передавать переменное число аргументов в подобные
функции? Мы приведем три программы использующие три различных  подхода.  Предпочтение
не отдано ни одному из них - каждый из них может оказаться эффективнее других в опре-
деленных ситуациях.  Думайте сами!

7.38.1.  Массив

    /* Передача аргументов в функцию как МАССИВА.
     * Следует явно указать число аргументов в массиве.
     */

    #include               /* printf(), NULL */
    #include              /* strdup() */
    #include              /* malloc() */

    #define A_INT           1
    #define A_STR           2
    #define A_NULL          0

    typedef struct arg {
            int type;
            union jack {
                    char *s;
                    int   d;
            } data;
            struct arg *next;
    } Arg;

    void doit(Arg args[], int n){
            int i;

            for(i=0; i < n; i++)
                    switch(args[i].type){
                    case A_INT:
                            printf("%d", args[i].data.d);
                            break;
                    case A_STR:
                            printf("%s", args[i].data.s);
                            break;
                    default:
                            fprintf(stderr, "Unknown type!\n");
                            break;
                    }
    }

А. Богатырев, 1992-95                  - 306 -                              Си в UNIX

    /* При инициализации union надо использовать тип
     * первого из перечисленных значений.
     */
    Arg sample[] = {
            { A_INT, (char *) 123 },
            { A_STR, (char *) " hello, " },
            { A_INT, (char *) 456 },
            { A_STR, (char *) " world\n" }
    };

    int main(int ac, char *av[]){
            doit(sample, sizeof sample / sizeof sample[0]);
            return 0;
    }

7.38.2.  Список

    /* Передача аргументов в функцию как СПИСКА.
     * Достоинство: список можно модифицировать
     * во время выполнения программы: добавлять и
     * удалять элементы. Недостаток тот же: список надо
     * построить динамически во время выполнения,
     * заранее этого сделать нельзя.
     * Недостатком данной программы является также то,
     * что список не уничтожается после использования.
     * В C++ эта проблема решается при помощи использования
     * автоматически вызываемых деструкторов.
     */

    #include               /* printf(), NULL */
    #include              /* strdup() */
    #include              /* malloc() */

    #define A_INT           1
    #define A_STR           2
    #define A_NULL          0

    typedef struct arg {
            int type;
            union jack {
                    char *s;
                    int   d;
            } data;
            struct arg *next;
    } Arg;

А. Богатырев, 1992-95                  - 307 -                              Си в UNIX

    void doit(Arg *arglist){
            for( ; arglist; arglist=arglist->next)
                    switch(arglist->type){
                    case A_INT:
                            printf("%d", arglist->data.d);
                            break;
                    case A_STR:
                            printf("%s", arglist->data.s);
                            break;
                    default:
                            fprintf(stderr, "Unknown type!\n");
                            break;
                    }
    }

    Arg *new_int(int n, Arg *next){
            Arg *ptr = (Arg *) malloc(sizeof(Arg));
            ptr->type   = A_INT;
            ptr->data.d = n;
            ptr->next   = next;
            return ptr;
    }

    Arg *new_str(char *s, Arg *next){
            Arg *ptr = (Arg *) malloc(sizeof(Arg));
            ptr->type   = A_STR;
            ptr->data.s = strdup(s);
            ptr->next   = next;
            return ptr;
    }

    int main(int ac, char *av[]){
            doit(
                    new_int(123,
                    new_str(" hello, ",
                    new_int(456,
                    new_str(" world\n",
                            NULL))))
            );
            return 0;
    }

7.38.3.  Функция с переменным числом параметров

    /* Передача аргументов в функцию как СПИСКА АРГУМЕНТОВ
     * ФУНКЦИИ с признаком конца списка.
     */

    #include               /* printf(), NULL */
    #include              /* va_...   */

    #define A_INT           1
    #define A_STR           2
    #define A_NULL          0

А. Богатырев, 1992-95                  - 308 -                              Си в UNIX

    void doit(...){         /* переменное число аргументов */
            va_list args;

            /* второй параметр - аргумент, предшествующий ...
             * Если такого нет - ставим запятую и пустое место!
             */
            va_start(args, );

            for(;;){
                    switch(va_arg(args, int)){
                    case A_INT:
                            printf("%d", va_arg(args, int));
                            break;
                    case A_STR:
                            printf("%s", va_arg(args, char *));
                            break;
                    case A_NULL:
                            goto breakloop;
                    default:
                            fprintf(stderr, "Unknown type!\n");
                            break;
                    }
            }
    breakloop:
            va_end(args);
    }

    int main(int ac, char *av[]){
            doit(
                    A_INT, 123,
                    A_STR, " hello, ",
                    A_INT, 456,
                    A_STR, " world\n",
                    A_NULL
            );
            return 0;
    }

7.39.  Напишите несколько функций для работы с упрощенной базой данных. Запись в базе
данных содержит ключ - целое, и строку фиксированной длины:

    struct data {
           int  b_key;             /* ключ */
           char b_data[ DATALEN ]; /* информация */
    };

     Напишите:
-    добавление записи
-    уничтожение по ключу
-    поиск по ключу (и печать строки)
-    обновление по ключу.
Файл организован как несортированный массив записей без  дубликатов  (т.е.  ключи  не
могут  повторяться).   Поиск  производить линейно. Используйте функции fread, fwrite,
fseek. Последняя функция позволяет вам позиционироваться к n-ой записи файла:

    fseek( fp, (long) n * sizeof(struct data), 0 );

Перепишите эту программу, объявив ключ как строку, например

А. Богатырев, 1992-95                  - 309 -                              Си в UNIX

    char b_key[ KEYLEN ];

Если строка-ключ короче KEYLEN  символов,  она  должна  оканчиваться  '\0',  иначе  -
используются все KEYLEN букв и '\0' на конце отсутствует (так же устроено поле d_name
в каталогах файловой системы).  Усовершенствуйте алгоритм доступа, используя  хеширо-
вание  по  ключу  (hash  - перемешивание, см. пример в приложении).  Вынесите ключи в
отдельный файл. Этот файл ключей состоит из структур

    struct record_header {
      int  b_key   ;    /* ключ */
      long b_offset;    /* адрес записи в файле данных */
      int  b_length;    /* длина записи (необязательно) */
Предыдущая страница Следующая страница
1 ... 52 53 54 55 56 57 58  59 60 61 62 63 64 65 ... 87
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 

Реклама