Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Бичков - Основи сучасного програмування.doc
Скачиваний:
69
Добавлен:
07.03.2016
Размер:
2.67 Mб
Скачать

Val val; /*значення*/

}*hashtable[HASHSIZE]; /*хеш-таблиця*/

/*отримання значення за ключем*/

struct cell *get(KEY key){

struct cell *p;

for(p=hashtable[HASHFUNC(key)]; p; p=p->next)

if(EQKEY(p->key, key))

return p;

return NULL; /*відсутнє*/

}

/*занести пару ключ : значення в таблицю*/

Void set(key key, val val){

struct cell *p;

/*перевірити, чи не було елемента з таким ключем*/

if((p=get(key))==NULL){/*не було*/

if(!(p=(struct cell*) malloc(sizeof(*p)))) return;

SETKEY(p->key, key);

p->next=hashtable[hash]; /*hash обчислене в get()*/

hashtable[hash]=p;

} else /*уже було: змінити значення*/

FREEVAL(p->val);

SETVAL(p->val, val);

}

/*знищення за ключем*/

int del(KEY key){

int indx=HASHFUNC(key);

struct cell *p, *prev=NULL;

if((p=hashtable[indx])==NULL) return 0;

for(;p;prev=p, p=p->next)

if(EQKEY(p->key, key)){

FREEVAL(p->val); FREEKEY(p->key);

if(p==hashtable[indx]) /*голова списку*/

hashtable[indx]=p->next;

else prev->next=p->next;

free((void*)p); return 1; /*знищений*/

}

return 0; /*не було такого*/

}

/*роздрукувати пару ключ : значення*/

Void printcell(struct cell *ptr){

putchar('(');

printf(KEYFMT, ptr->key); putchar(',');

printf(VALFMT, ptr->val); putchar(')');

}

/*друк таблиці (для налагодження)*/

void printtable(){

register i; struct cell *p;

printf("----TABLE CONTENTS----\n");

for(i=0; i<HASHSIZE; i++)

if((p=hashtable[i]) !=NULL){

printf("%d: ", i);

for(; p; p=p->next)

printcell(p), putchar(' ');

putchar('\n');

}

}

/*ітератор*/

struct celliter {

int index; struct cell *ptr;

};

/*видати чергове значення*/

struct cell *nextpair(struct celliter *ci){

struct cell *result;

while((result=ci->ptr)==NULL){

if(++(ci->index)>=HASHSIZE)

return NULL; /*більше немає*/

ci->ptr=hashtable[ci->index];

}

ci->ptr=result->next; return result;

}

/*ініціалізація ітератора*/

struct cell *resetiter(struct celliter *ci){

ci->index=(-1); ci->ptr=NULL;

return nextpair(ci); /*перше значення*/

}

void main(){

/*таблиця з імен і розмірів файлів поточного каталогу*/

struct celliter ci; struct cell *cl;

char key[40], value[40]; struct cell *val;

extern FILE *popen(); FILE *fp; char *s;

/*popen() читає виведення команди, заданої в 1-му аргументі*/

fp=popen("ls -s", "r");

while(fscanf(fp, "%s%s", value, key)==2)

set(key, value);

pclose(fp); /*popen() потрібно закривати pclose();*/

for(;;){

printf("-> "); /*запрошення*/

if(!gets(key)) break; /*EOF*/

if(*key=='-'){/*КЛЮЧ : видалити*/

printf(del(key+1)? "OK\n" : "немає такого\n");

continue;

}

if(!*key||!strcmp(key,"=")){

/*=:роздрукувати таблицю*/

printtable(); continue;

}

if(s=strchr(key,'=')){

/*КЛЮЧ=ЗНАЧЕННЯ : додати*/

*s++='\0';

set(key, s); continue;

}

if((val=get(key))==NULL) /*КЛЮЧ : знайти значення*/

printf("немає такого ключа\n");

else{printf("значення"); printf(VALFMT, val->val);

putchar('\n');

}

}

/*друк таблиці за допомогою ітератора*/

for(cl=resetiter(&ci); cl; cl=nextpair(&ci))

printcell(cl), putchar('\n');

}

2. Складені описувачі. Напишемо програму, яка:

а) підраховує кількість усіх допустимих у мові С складених описувачів заданої довжини;

б) генерує довільний складений описувач заданої довжини;

в) друкує всі допустимі складені описувачі заданої довжини.

У допустимих описувачах ураховуватимемо лише тривіальні ознаки масивів і функцій – дужки [ ], (). Розглянемо поняття довжини як кількість кроків інтерпретації.

Якщо позначити через V ознаку покажчика, М – масиву, F – функції, то за правилами розшифровки довільна послідовність FFVVMFVV задає схему утворення описувача (інтерпретуємо її зліва направо). Описувач буде допустимим, якщо в цій послідовності немає комбінацій вигляду FM (масив функцій), FF (функція повертає функцію), MF. Схему створення допустимого складеного описувача можна подати так:

V – покажчик M-масив F-функція

V-V M-V F-V

V-M M-M

V-F

Якщо останньою була ознака покажчика, то вона може утворити всі три ознаки, масиву – дві й, нарешті, ознака функції – лише одну ознаку покажчика.

Для підрахунку кількості всіх можливих описувачів ми можемо використати лише три змінних – v, m, f типу long, які б зберігали в собі на кожному кроці кількість описувачів, у яких останньою при інтерпретації була б відповідно ознака покажчика, масиву та функції. Неважко помітити, що ці кількості за 1 крок зростають за правилом

v1=v+m+f;

m1=m+v;

f1=v;

Наведемо відповідний підрахунок у вигляді функції:

long kilkist(int n)

{

long v=1, m=1, f=1, v1,m1,f1;

int i;

for(i=1;i<n;i++)

{

v1=v+m+f;

m1=m+v;

f1=v;

v=v1;

m=m1;

f=f1;

}

return (v+m+f);

}

Тоді main-функція має вигляд

#include <stdio.h>