Главная · Поиск книг · Поступления книг · 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 ... 25 26 27 28 29 30 31  32 33 34 35 36 37 38 ... 87
    #define getchar()    getc(stdin)
    #define fileno(fp)   ((fp)->file)
    #define feof(fp)     (((fp)->flag & IOEOF) != 0)
    #define ferror(fp)   (((fp)->flag & IOERR) != 0)
    #define clearerr(fp) ((void) ((fp)->flag &= ~(IOERR | IOEOF)))

    #define getc(fp)    (--(fp)->cnt < 0 ? \
            filbuf(fp) : (int) *(fp)->ptr++)
    #define putc(x, fp) (--(fp)->cnt < 0 ? \
            flsbuf((uchar) (x), (fp)) :    \
            (int) (*(fp)->ptr++ = (uchar) (x)))

    int fputc(int c, FILE *fp){ return putc(c, fp); }
    int fgetc(       FILE *fp){ return getc(fp);    }

____________________
NULL.
____________________
   [**] Ссылка на управляющий терминал процесса  хранится  в  u-area  каждого  процесса:
u_ttyp,  u_ttyd, поэтому ядро в состоянии определить какой настоящий терминал следует
открыть для вас.  Если разные процессы открывают /dev/tty, они могут открыть в  итоге
разные  терминалы,  т.е.   одно  имя приводит к разным устройствам!  Смотри главу про
UNIX.

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

    /* Открытие файла */
    FILE *fopen(char *name, char *how){
       register FILE *fp; register i, rw;
       for(fp = iob, i=0; i < _NFILE; i++, fp++)
            if(fp->flag == 0) goto found;
       return NULL; /* нет свободного слота */
    found:
       rw = how[1] == '+';
       if(*how == 'r'){
          if((fp->file = open(name, rw ? O_RDWR:O_RDONLY)) < 0)
              return NULL;
          fp->flag = IOREAD;
       } else {
          if((fp->file = open(name, (rw ? O_RDWR:O_WRONLY)| O_CREAT |
             (*how == 'a' ? O_APPEND : O_TRUNC), 0666 )) < 0)
               return NULL;
          fp->flag = IOWRT;
       }
       if(rw) fp->flag = IORW;
       fp->bufsiz = fp->cnt = 0; fp->base = fp->ptr = NULL;
       return fp;
    }

    /* Принудительный сброс буфера */
    void fflush(FILE *fp){
       uchar *base; int full= 0;
       if((fp->flag & (IONBF|IOWRT)) == IOWRT &&
          (base = fp->base) != NULL && (full=fp->ptr - base) > 0){
            fp->ptr = base; fp->cnt = fp->bufsiz;
            if(write(fileno(fp), base, full) != full)
               fp->flag |= IOERR;
       }
    }

    /* Закрытие файла */
    void fclose(FILE *fp){
       if((fp->flag & (IOREAD|IOWRT|IORW)) == 0 ) return;
       fflush(fp);
       close(fileno(fp));
       if(fp->flag  & IOALLOC) free(fp->base);
       fp->base = fp->ptr = NULL;
       fp->cnt  = fp->bufsiz = fp->flag = 0; fp->file = (-1);
    }

    /* Закрытие файлов при exit()-е */
    void _cleanup(){
       register i;
       for(i=0; i < _NFILE; i++)
           fclose(iob + i);
    }

    /* Завершить текущий процесс */
    void exit(uchar code){
       _cleanup();
       _exit(code); /* Собственно системный вызов */
    }

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

    /* Прочесть очередной буфер из файла */
    int filbuf(FILE *fp){
       static uchar smallbuf[_NFILE];

       if(fp->flag & IORW){
          if(fp->flag & IOWRT){ fflush(fp); fp->flag &= ~IOWRT; }
          fp->flag |=   IOREAD;   /* операция чтения */
       }
       if((fp->flag & IOREAD) == 0 || feof(fp)) return EOF;

       while( fp->base == NULL )   /* отвести буфер */
          if( fp->flag & IONBF ){  /* небуферизованный */
              fp->base = &smallbuf[fileno(fp)];
              fp->bufsiz = sizeof(uchar);
          } else if( fp == stdin ){ /* статический буфер */
              fp->base   =        sibuf;
              fp->bufsiz = sizeof(sibuf);
          } else if((fp->base = malloc(fp->bufsiz = BUFSIZ)) == NULL)
               fp->flag |= IONBF;   /* не будем буферизовать */
          else fp->flag |= IOALLOC; /* буфер выделен         */

       if( fp == stdin && (stdout->flag & IOTTY)) fflush(stdout);
       fp->ptr = fp->base;        /* сбросить на начало буфера */

       if((fp->cnt = read(fileno(fp), fp->base, fp->bufsiz)) == 0 ){
           fp->flag |= IOEOF; if(fp->flag & IORW) fp->flag &= ~IOREAD;
           return EOF;
       } else if( fp->cnt < 0 ){
           fp->flag |= IOERR; fp->cnt = 0; return EOF;
       }
       return getc(fp);
    }

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

    /* Вытолкнуть очередной буфер в файл */
    int flsbuf(int c, FILE *fp){
       uchar *base; int full, cret = c;

       if( fp->flag & IORW ){
           fp->flag &= ~(IOEOF|IOREAD);
           fp->flag |=   IOWRT;  /* операция записи */
       }
       if((fp->flag & IOWRT) == 0) return EOF;
    tryAgain:
       if(fp->flag & IONBF){ /* не буферизован */
          if(write(fileno(fp), &c, 1) != 1)
            { fp->flag |= IOERR; cret=EOF; }
          fp->cnt = 0;
       } else {   /* канал буферизован */
          if((base = fp->base) == NULL){ /* буфера еще нет */
              if(fp == stdout){
                  if(isatty(fileno(stdout))) fp->flag |=  IOTTY;
                  else                       fp->flag &= ~IOTTY;
                  fp->base = fp->ptr = sobuf; /* статический буфер */
                  fp->bufsiz =  sizeof(sobuf);
                  goto tryAgain;
              }
              if((base = fp->base = malloc(fp->bufsiz = BUFSIZ))== NULL){
                     fp->bufsiz = 0; fp->flag |= IONBF;  goto tryAgain;
              } else                 fp->flag |= IOALLOC;
          } else if ((full = fp->ptr - base) > 0)
              if(write(fileno(fp), fp->ptr = base, full) != full)
              { fp->flag |= IOERR; cret = EOF;                  }
          fp->cnt = fp->bufsiz - 1;
          *base++ = c;
          fp->ptr = base;
       }
       return cret;
    }

    /* Вернуть символ в буфер */
    int ungetc(int c, FILE *fp){
       if(c == EOF || fp->flag & IONBF || fp->base == NULL) return EOF;
       if((fp->flag & IOREAD)==0 || fp->ptr <= fp->base)
          if(fp->ptr == fp->base && fp->cnt == 0) fp->ptr++;
          else       return EOF;
       fp->cnt++;
       return(* --fp->ptr = c);
    }

    /* Изменить размер буфера */
    void setbuffer(FILE *fp, uchar *buf, int size){
       fflush(fp);
       if(fp->base && (fp->flag & IOALLOC)) free(fp->base);
       fp->flag &= ~(IOALLOC|IONBF);
       if((fp->base = fp->ptr = buf) == NULL){
           fp->flag |= IONBF;  fp->bufsiz = 0;
       } else                  fp->bufsiz = size;
       fp->cnt = 0;
    }

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

    /* "Перемотать" файл в начало */
    void rewind(FILE *fp){
       fflush(fp);
       lseek(fileno(fp), 0L, 0);
       fp->cnt = 0; fp->ptr = fp->base;
       clearerr(fp);
       if(fp->flag & IORW) fp->flag &= ~(IOREAD|IOWRT);
    }

    /* Позиционирование указателя чтения/записи */
    #ifdef COMMENT
            base  ptr                       случай IOREAD
            |     |<----cnt---->|
     0L     |б  у |ф  е  р      |
    |=======######@@@@@@@@@@@@@@======== файл file
    |             |<-p->|<-dl-->|
    |<----pos---->|     |       |
    |<----offset(new)-->|       |
    |<----RWptr---------------->|

    где      pos = RWptr - cnt;  // указатель с поправкой
    offset = pos + p = RWptr - cnt + p = lseek(file,0L,1) - cnt + p
    отсюда:  (для SEEK_SET)
             p = offset+cnt-lseek(file,0L,1);
    или      (для SEEK_CUR)  dl = RWptr - offset = p - cnt
             lseek(file, dl, 1);
    Условие, что указатель можно сдвинуть просто в буфере:
    if( cnt > 0 && p <= cnt && base <= ptr + p ){
            ptr += p; cnt -= p;                 }
    #endif /*COMMENT*/

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

    int fseek(FILE *fp, long offset, int whence){
       register resync, c; long p = (-1);
       clearerr(fp);
       if( fp->flag & (IOWRT|IORW)){
           fflush(fp);
           if(fp->flag & IORW){
              fp->cnt = 0; fp->ptr = fp->base; fp->flag &= ~IOWRT;
           }
           p = lseek(fileno(fp), offset, whence);
       } else if( fp->flag & IOREAD ){
           if(whence < 2 && fp->base && !(fp->flag & IONBF)){
              c = fp->cnt; p = offset;
              if(whence == 0) /* SEEK_SET */
                 p +=   c - lseek(fileno(fp), 0L, 1);
              else offset -= c;
              if(!(fp->flag & IORW) &&
                 c > 0 && p <= c && p >= fp->base - fp->ptr
              ){ fp->ptr += (int) p; fp->cnt -= (int) p;
                 return 0;  /* done */
              }
              resync = offset & 01;
           } else resync = 0;
           if(fp->flag & IORW){
              fp->ptr = fp->base; fp->flag &= ~IOREAD; resync = 0;
           }
           p = lseek(fileno(fp), offset-resync, whence);
           fp->cnt = 0;       /* вынудить filbuf(); */
           if(resync) getc(fp);
       }
       return (p== -1 ? -1 : 0);
    }

    /* Узнать текущую позицию указателя */
    long ftell(FILE *fp){
       long tres; register adjust;
       if(fp->cnt < 0) fp->cnt = 0;
            if(fp->flag &  IOREAD)       adjust = -(fp->cnt);
       else if(fp->flag & (IOWRT|IORW)){ adjust = 0;
            if(fp->flag & IOWRT &&
               fp->base && !(fp->flag & IONBF)) /* буферизован */
                    adjust = fp->ptr - fp->base;
       } else return (-1L);
       if((tres = lseek(fileno(fp), 0L, 1)) < 0) return tres;
       return (tres + adjust);
    }

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

5.  Структуры данных.
     Структуры ("записи") представляют собой агрегаты разнородных данных (полей  раз-
ного типа); в отличие от массивов, где все элементы имеют один и тот же тип.

    struct {
            int x, y;   /* два целых поля */
            char s[10]; /* и одно - для строки */
    } s1;

Структурный тип может иметь имя:

    struct XYS {
            int x, y;     /* два целых поля */
            char str[10]; /* и одно - для строки  */
    };

Здесь мы объявили тип, но не отвели ни одной переменной этого типа (хотя  могли  бы).
Теперь опишем переменную этого типа и указатель на нее:

    struct XYS s2, *sptr = &s2;

Доступ к полям структуры производится по имени поля (а не по индексу,  как  у  масси-
вов):

    имя_структурной_переменной.имя_поля
    указатель_на_структуру  ->> имя_поля

то есть

          не                        а
    #define ВЕС  0            struct { int вес, рост; } x;
    #define РОСТ 1            x.рост = 175;
    int x[2]; x[РОСТ] = 175;

Например

    s1.x = 13;
    strcpy(s2.str, "Finish");
    sptr->y = 27;

Структура может содержать структуры другого типа в качестве полей:

    struct XYS_Z {
            struct XYS xys;
            int z;
    } a1;
    a1.xys.x = 71; a1.z = 12;

Структура того же самого типа не может содержаться  в  качестве  поля  -  рекурсивные
определения  запрещены.   Зато нередко используются поля - ссылки на структуры такого
же типа (или другого). Это позволяет организовывать списки структур:

    struct node {
            int value;
            struct node *next;
    };

Очень часто используются массивы структур:

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

    struct XYS array[20]; int i = 5, j;
    array[i].x = 12;
    j = array[i].x;

Статические структуры можно описывать с инициализацией, перечисляя значения их  полей
в {} через запятую:

    extern struct node n2;
    struct node n1 = { 1, &n2  },
                n2 = { 2, &n1  },
                n3 = { 3, NULL };

В этом примере n2 описано предварительно для того, чтобы &n2 в  строке  инициализации
n1 было определено.
     Структуры одинакового типа можно присваивать целиком (что соответствует присваи-
Предыдущая страница Следующая страница
1 ... 25 26 27 28 29 30 31  32 33 34 35 36 37 38 ... 87
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 

Реклама