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

Void main(void)

{

int n;

printf("введіть довжину процесу інтерпретації описувача n>=1\n');

scanf("%d',&n);

printf("шукана кількість: %ld\n',kilkist(n));

}

Нескладний аналіз показує, що код, записаний у тілі циклу for у функції kilkist(), може бути спрощений і записуватися без використання допоміжних змінних v1, m1, f1.

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

long kilkist(int n)

{

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

int i;

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

{

v+=m+f;

f=v-m-f;

m+=f;

}

return (v+m+f);

}

Для розв'язання другої частини задачі спочатку отримаємо всі можливі схеми інтерпретації указаної довжини та реалізуємо їх. Для цього нам необхідно мати:

 функцію, що генерує схеми;

 функцію-інтерпретатор, що будує конкретний описувач за заданою схемою;

 функцію, що формує список.

Ураховуючи вищезгадану схему, можемо вибрати різні структури даних, наприклад тернарні дерева. Однак ми зупинимось на однозв'язному списку, одночасно демонструючи технологію роботи зі списками. Виберемо таку структуру:

struct inter

{

struct inter *next; // покажчик на наступний елемент

char *s; // поле, де зберігається інтерпретаційна схема

char ost; // останній елемент поля s

};

Якщо поле ost відповідного елемента в списку містить ознаку покажчика, то утворюємо два нових екземпляра структури inter і записуємо їх у список одразу після відповідного елемента, модифікуючи і його поле s. Якщо ознака масиву – один елемент, то модифікуємо лише поточний покажчик.

#include <stdio.h>

#include <alloc.h>

#include <conio.h>

#include <string.h>

struct inter

{

struct inter *next; // покажчик на наступний елемент

char *s; // поле, де зберігається інтерпретаційна схема

char ost;// останній елемент поля s

};

/*Параметр функції flag набуває два значення: 0 та 1. Якщо він рівний 0, то функція модифікує саму структуру, що передається через покажчик p, дописуючи символ x як останній символ поля s, не створюючи при цьому нової структури в пам’яті. Якщо ж flag дорівнює 1, то утворюється нова структура, у якої поле s є конкатенацією поля s структури, що передається через покажчик p, та символу x*/

struct inter* vstavka(char x, struct inter *p,int flag)

{

if(p==NULL) /*Якщо p==NULL проводиться ініціалізація полів структури*/

{

p=(struct inter*)malloc(sizeof(struct inter));

p->s=(char*)malloc(sizeof(char)+1);

p->s[0]=x;

p->s[1]='\0';

p->ost=x;

p->next=NULL;

return p;

}

else /*інакше проводимо аналіз прапорця*/

{

int size=strlen(p->s);

if(flag!=0)

{struct inter* p1=(struct inter*)malloc(sizeof(struct inter));

p1->s=(char*)malloc(size+2);

strcpy(p1->s,p->s);

p1->s[size]=x;

p1->s[size+1]='\0';

p1->ost=x;

p1->next=NULL;

return p1;

}

else

{

char *srob=(char*)malloc(size+2);

strcpy(srob,p->s);

srob[size]=x;

srob[size+1]='\0';

strcpy(p->s,srob);

p->ost=x;

return p;

}

}

}

/*Функція-інтерпретатор*/

void interpret(char *s, char ident)

{

int i,j,sv=0,sv1=0,slen=strlen(s),identlen=1;

for(i=0;i<strlen(s);i++)

{

if (s[i]=='v' && s[i+1]!='v') sv++;

if (s[i]=='v') sv1++;

}

char *sinterp=(char*)malloc((slen-sv1)*2+identlen+sv1+sv*2);

/*sinterp – масив, де зберігається проінтерпретований варіант*/

int sost=identlen-1;

/*індекс останнього проініціалізованого елемента масиву*/

sinterp[0]=ident;

sinterp[1]='\0';

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

{

switch(s[i])

{

case 'v':

/*усе беремо в дужки і ставимо ліворуч зірочку*/

if(s[i+1]!='v'&& i<slen-1)

{

for(j=sost; j>=0; j--)

sinterp[j+2]=sinterp[j];

sinterp[0]='(';

sinterp[1]='*';

sinterp[sost+3]=')';

sost+=3;

}

else

{

for(j=sost; j>=0; j--)

sinterp[j+1]=sinterp[j];

sinterp[0]='*';

sost+=1;

}

break;

case 'm':

sinterp[sost+1]='[';

sinterp[sost+2]=']';

sost+=2;

break;

case 'f':

sinterp[sost+1]='(';

sinterp[sost+2]=')';

sost+=2;

break;

default: printf("вхідний масив невірний");

}

}

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

printf("%c",sinterp[i]);

printf("\n");

//char c=getch();

free(sinterp);

}

При розробці функції інтерпретора врахуємо, що в інтерпретації ознаки покажчика отриману конструкцію необхідно взяти в дужки (інакше порядок інтерпретації буде іншим).

/*функція, що формує список. Значення полів s – інтерпретаційні послідовності*/

struct inter* form(int n)

{

struct inter* spysok,*current;

int i;

spysok=vstavka('v',NULL,0);

current=spysok;

current->next=vstavka('m',NULL,0);

current->next->next=vstavka('f',NULL,0);

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

{

current=spysok;

while(current!=NULL)

{

//printf("%s\n",current->s);

//char c=getch();

switch(current->ost)

{

struct inter* currob;

case 'v':

currob=vstavka('m',current,1);

currob->next=vstavka('f',current,1);

current=vstavka('v',current,0);

currob->next->next=current->next;

current->next=currob;

current=currob->next->next;

break;

case 'm':

currob=vstavka('m',current,1);

current=vstavka('v',current,0);

currob->next=current->next;

current->next=currob;

current=currob->next;

break;

case 'f':

current=vstavka('v',current,0);

current=current->next;

break;

default:

printf("main список ініціалізований неправильно\n");

}

}

}

return spysok;

}

main()

{

struct inter *spysok,*current;

int n;

char c;

printf("введіть n\n");

scanf("%d",&n);

spysok=form(n);

current=spysok;

while(current!=NULL)

{

printf("%s\n",current->s);

interpret(current->s,'a');

printf("\n");

c=getch();

current=current->next;

}

free(spysok);

}