Главная · Поиск книг · Поступления книг · 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 ... 58 59 60 61 62 63 64  65 66 67 68 69 70 71 ... 87
    #define TOKEN(v)        (*v)->token
    #define TYPE(v)         (*v)->type
    #define eq(str1, str2)  (!strcmp(str1, str2))
    jmp_buf breakpoint;
    #define ERR(msg,val) { printf("%s\n", msg);longjmp(breakpoint, val+1);}

    typedef struct {
         char *name;        /* Имя переменной      */
         int value;         /* Значение переменной */
         int isset;         /* Получила ли значение ? */
    } Var;
    #define MAXV 40
    Var vars[MAXV];

    /* Получить значение переменной */
    int getVar(char *name){ Var *ptr;
       for(ptr=vars; ptr->name; ptr++)
           if(eq(name, ptr->name)){
              if(ptr->isset) return ptr->value;
              printf("%s: ", name); ERR("variable is unbound yet", 0);
           }
       printf("%s: ", name); ERR("undefined variable", 0);
    }

    /* Создать новую переменную       */
    Var *internVar(char *name){ Var *ptr;
       for(ptr=vars; ptr->name; ptr++)
           if(eq(name, ptr->name)) return ptr;
       ptr->name = strdup(name);
       ptr->isset = 0; ptr->value = 0; return ptr;
    }

    /* Установить значение переменной */
    void setVar(Var *ptr, int val){ ptr->isset = 1; ptr->value = val; }

    /* Распечатать значения переменных */
    void printVars(){ Var *ptr;
         for(ptr=vars; ptr->name; ++ptr)
             printf("\t%s %s %d\n", ptr->isset ? "BOUND  ":"UNBOUND",
                          ptr->name, ptr->value);
    }

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

    /* Синтаксический разбор и одновременное вычисление ----------- */
    /* Вычисление встроенных функций */
    int apply(char *name, int args[], int nargs){
        if(eq(name, "power2")){
            if(nargs != 1) ERR("power2: wrong argument count", 0);
            return (1 << args[0]);
        } else if(eq(name, "min")){
            if(nargs != 2) ERR("min: wrong argument count", 0);
            return (args[0] < args[1] ? args[0] : args[1]);
        } else if(eq(name, "max")){
            if(nargs != 2) ERR("max: wrong argument count", 0);
            return (args[0] < args[1] ? args[1] : args[0]);
        } else if(eq(name, "sum")){ register i, sum;
            for(i=0, sum=0; i < nargs; sum += args[i++]);
            return sum;
        } else if(eq(name, "rand")){
            switch(nargs){
            case 0:  return rand();
            case 1:  return rand() % args[0];
            case 2:  return args[0] + rand() % (args[1] - args[0] + 1);
            default: ERR("rand: wrong argument count", 0);
            }
        }
        ERR("Unknown function", args[0]);
    }

    /* Вычислить выражение из списка лексем.        */
    /* Синтаксис задан праворекурсивной грамматикой */
    int expr(Token *t){ int val = 0;
        if(val = setjmp(breakpoint)) return val - 1;
        val = expression(&t);
        if(t){ printlex(NULL, t); ERR("Extra tokens", val); }
        return val;
    }

    /*  =     |
                          ";"           */
    int expression(Token **v){ int arg = expass(v);
        if(*v && TYPE(v) == SMC ){
            NEXT(v); return expression(v);
        } else return arg;
    }

    /*  =       <ПЕРЕМЕННАЯ> "="  |
                                                      */
    int expass(Token **v){ int arg;
        if(*v && (*v)->next && (*v)->next->type == OP &&
           eq((*v)->next->token, "=")){ Var *ptr;
               /* присваивание (assignment) */
               if( TYPE(v) != ID ) /* слева нужна переменная */
                    ERR("Lvalue needed", 0);
               ptr = internVar(TOKEN(v));
               NEXT(v); NEXT(v); setVar(ptr, arg = expass(v)); return arg;
        }
        return exp0(v);
    }

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

    /*   =    |    "||"   */
    int exp0(Token **v){ int arg = exp1(v);
        if(*v && TYPE(v) == OP && eq(TOKEN(v), "||")){
              NEXT(v); return(exp0(v) || arg );
              /* помещаем arg ВТОРЫМ, чтобы второй операнд вычислялся
               * ВСЕГДА (иначе не будет исчерпан список токенов и
               * возникнет ошибка в expr(); Это не совсем по правилам Си.
               */
        } else return arg;
    }

    /*   =    |    "&&"      */
    int exp1(Token **v){ int arg = exp2(v);
        if(*v && TYPE(v) == OP && eq(TOKEN(v), "&&")){
              NEXT(v); return(exp1(v) && arg);
        } else return arg;
    }

    /*   =    |    "|"     */
    int exp2(Token **v){ int arg = exp2a(v);
        if(*v && TYPE(v) == OP && eq(TOKEN(v), "|")){
              NEXT(v); return( arg | exp2(v));
        } else return arg;
    }

    /*   =    |    "^"   */
    int exp2a(Token **v){ int arg = exp2b(v);
        if(*v && TYPE(v) == OP && eq(TOKEN(v), "^")){
              NEXT(v); return( arg ^ exp2a(v));
        } else return arg;
    }

    /*   =    |    "&"   */
    int exp2b(Token **v){ int arg = exp2c(v);
        if(*v && TYPE(v) == OP && eq(TOKEN(v), "&")){
              NEXT(v); return( arg & exp2b(v));
        } else return arg;
    }

    /*   =    |    "==" 
                           |    "!="     */
    int exp2c(Token **v){ int arg = exp3(v);
               if(*v && TYPE(v) == OP && eq(TOKEN(v), "==")){
               NEXT(v); return( arg == exp3(v));
        } else if(*v && TYPE(v) == OP && eq(TOKEN(v), "!=")){
               NEXT(v); return( arg != exp3(v));
        } else return arg;
    }

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

    /*   =    |    ">"  
                           |    "<"  
                           |    ">=" 
                           |    "<="     */
    int exp3(Token **v){ int arg = exp3a(v);
              if(*v && TYPE(v) == OP && eq(TOKEN(v), ">")){
              NEXT(v); return( arg && exp3(v));
        }else if(*v && TYPE(v) == OP && eq(TOKEN(v), "<")){
              NEXT(v); return( arg && exp3(v));
        }else if(*v && TYPE(v) == OP && eq(TOKEN(v), ">=")){
              NEXT(v); return( arg && exp3(v));
        }else if(*v && TYPE(v) == OP && eq(TOKEN(v), "<=")){
              NEXT(v); return( arg && exp3(v));
        } else return arg;
    }

    /*   =    |    "<<" 
                           |    ">>"     */
    int exp3a(Token **v){ int arg = exp4(v);
              if(*v && TYPE(v) == OP && eq(TOKEN(v), "<<")){
              NEXT(v); return( arg << exp3a(v));
        }else if(*v && TYPE(v) == OP && eq(TOKEN(v), ">>")){
              NEXT(v); return( arg && exp3a(v));
        } else return arg;
    }

    /*   =    |    "+" 
                          |    "-"        */
    int exp4(Token **v){ int arg = exp5(v);
              if(*v && TYPE(v) == OP && eq(TOKEN(v), "+")){
              NEXT(v); return( arg + exp4(v));
        }else if(*v && TYPE(v) == OP && eq(TOKEN(v), "-")){
              NEXT(v); return( arg - exp4(v));
        } else return arg;
    }

    /*   =    |    "*" 
                          |    "/" 
                          |    "%"        */
    int exp5(Token **v){ int arg = exp6(v), arg1;
              if(*v && TYPE(v) == OP && eq(TOKEN(v), "*")){
              NEXT(v); return( arg * exp5(v));
        }else if(*v && TYPE(v) == OP && eq(TOKEN(v), "/")){
              NEXT(v); if((arg1 = exp5(v)) == 0) ERR("Zero divide", arg);
              return( arg / arg1);
        }else if(*v && TYPE(v) == OP && eq(TOKEN(v), "%")){
              NEXT(v); if((arg1 = exp5(v)) == 0) ERR("Zero module", arg);
              return( arg % arg1);
        } else return arg;
    }

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

    /*   = "!" | "~" | "-"
А. Богатырев, 1992-95                  - 280 -                              Си в UNIX
         |  <ИМЯФУНКЦИИ> "(" [  [ ","  ]... ] ")"
         |  <ЧИСЛО>
         |                             */
    int exp6(Token **v){ int arg;
        if( !*v) ERR("Lost token", 0);
        if(TYPE(v) == OP && eq(TOKEN(v), "!")){
            NEXT(v); return !exp6(v);
        }
        if(TYPE(v) == OP && eq(TOKEN(v), "~")){
            NEXT(v); return ~exp6(v);
        }
        if(TYPE(v) == OP && eq(TOKEN(v), "-")){
            NEXT(v); return -exp6(v);    /* унарный минус */
        }
        if(TYPE(v) == OPEN){
            NEXT(v); arg = expression(v);
            if( !*v || TYPE(v) != CLOSE) ERR("Lost ')'", arg);
            NEXT(v); return arg;
        }
        if(TYPE(v) == NUM){  /* изображение числа */
            arg = atoi(TOKEN(v)); NEXT(v); return arg;
        }
        if(TYPE(v) == ID){
            char *name = (*v)->token; int args[20], nargs = 0;
            NEXT(v);
            if(! (*v && TYPE(v) == OPEN)){  /* Переменная */
               return expvar(v, name);
            }
            /* Функция */
            args[0] = 0;
            do{ NEXT(v);
                if( *v && TYPE(v) == CLOSE ) break; /* f() */
                args[nargs++] = expression(v);
            }   while( *v && TYPE(v) == COMMA);

            if(! (*v && TYPE(v) == CLOSE)) ERR("Error in '()'", args[0]);
            NEXT(v);
            return apply(name, args, nargs);
        }
        printlex(TOKEN(v), *v); ERR("Unknown token type", 0);
    }

    /*   =   <ПЕРЕМЕННАЯ>      |
                            <ПЕРЕМЕННАЯ> "++" |
                            <ПЕРЕМЕННАЯ> "--"
     Наши операции ++ и -- соответствуют ++x и --x из Си         */
    int expvar(Token **v, char *name){
        int arg = getVar(name); Var *ptr = internVar(name);
        if(*v && TYPE(v) == OP){
          if(eq(TOKEN(v), "++")){ NEXT(v); setVar(ptr, ++arg); return arg; }
          if(eq(TOKEN(v), "--")){ NEXT(v); setVar(ptr, --arg); return arg; }
        }
        return arg;
    }

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

    /* Головная функция ------------------------------------------- */
    char input[256];
    Token *head, *tail;

    void main(){
        do{ printf(": "); fflush(stdout);
          if( !gets(input)) break;
          if(!*input){ printVars(); continue; }
          if(eq(input, "!!")) ; /* ничего не делать, т.е. повторить */
          else{ if(head) freelex(&head); lex(&head, &tail, input); }
          printf("Result: %d\n", expr(head));
        } while(1); putchar('\n');
    }

7.69.  Напишите программу, выделяющую n-ое поле из каждой строки файла. Поля разделя-
ются  двоеточиями. Предусмотрите задание символа-разделителя из аргументов программы.
Используйте эту программу для выделения поля "домашний каталог" из файла /etc/passwd.
Для выделения очередного поля можно использовать следующую процедуру:

    main(){
       char c, *next, *strchr(); int nfield;
       char *s = "11111:222222222:333333:444444";

       for(nfield=0;;nfield++){
         if(next = strchr(s, ':')){
            c= *next; *next= '\0';
         }
         printf( "Поле #%d: '%s'\n", nfield, s);
            /* можно сделать с полем s что-то еще */
         if(next){ *next= c; s= next+1; continue; }
         else    { break; /* последнее поле */    }
       }
    }

7.70.  Разработайте архитектуру и систему команд учебной машины и напишите  интерпре-
татор учебного ассемблера, отрабатывающего по крайней мере такие команды:
Предыдущая страница Следующая страница
1 ... 58 59 60 61 62 63 64  65 66 67 68 69 70 71 ... 87
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 

Реклама