Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 11, средняя оценка - 4.64
perimetral
1 / 1 / 0
Регистрация: 17.12.2010
Сообщений: 16
#1

Brainf**k - C++

07.02.2011, 12:48. Просмотров 1369. Ответов 23
Метки нет (Все метки)

Народ, суть проблемы такова: наш препод по программированию сам только только окончил вуз, и, к сожалению, это дотавляет неприятности. Вот какое задание к лабораторной он дал:
"Как известно, язык Brainf**k есть интерпретируемый язык программирования с 8ю операциями: > < + - [ ] , .. Задача состоит в написании интерпретатора для него на C++.". Почитать о нем лучше всего на Вики. Это вроде не сложно. В крайнем случае можно взять известный интерпретатор на JS и переписать структуру под C++. Но для 5ки, нужно еще кое-что добавить: необходимо описать процедуры языка. Для управления процедурами добавить еще 3 оператора: ( ) :. Оператор ( должен начинать описание процедуры. Т.е. грубо говоря, функции. ID (как бы имя) процедуры есть число и сохраняется в ячейке, на которой стоит каретка при описании процедуры. Оператор ) заканчивает процедуру. Код в процедуре не выполняется при последовательном интерпретировании кода, и вызывается командой :. Команда : читает значение текущей ячейки и вызывает процедуру с ID, указанным в этой ячейке. Для работы в процедуру передается следующая ячейка (т.е. в самой процедуре каретка изначально будет стоять на ячейке n+1, где n - ячейка , хранящая ID процедуры).
Народ, пожалуйста, помогите, для повышенной стипендии как раз не хватает этого зачета на 5, буду очень благодарен! Сдавать в пятницу, так что, думаю, время есть. Собственно, нужен полный интерпретатор + новые 3 команды.
Пример кода с ними:
Код
>>>+(+++)<<<,>+:<[>>+<<-].
Тут мы в 3й ячейке (если отчет с 0 вести) ставим ID процедуры = 1, потом описываем процедуру (она трижды инкрементирует рабочую ячейку), потом возвращаемся в ячейку 0, вводим в нее символ, в ячейке 1 ставим единицу и вызываем процедуру с этим ID. Т.к. рабочая ячейка нашей процедуры в данном случае - ячейка 2, потому мы возвращаемся в ячейку 0 и переносим из нее значение в ячейку 2, прибавляя то, что там уже есть. Выводим результат - наш символ + 3 по ASCII.
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Nameless One
Эксперт С++
5774 / 3424 / 255
Регистрация: 08.02.2010
Сообщений: 7,447
07.02.2011, 20:02 #16
silent_1991, хм... Возможно, так будет лучше. В принципе, твое решение будет отличаться от моего только тем, что, у тебя ячейки (переменные) будут представлять собой локальные переменные функции-парсера, а не будут храниться явно в экземляре структуры; т.е. они будут уничтожаться автоматически при возврате из функции, и не придется их вручную "подчищать".
0
silent_1991
Эксперт С++
4984 / 3041 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
07.02.2011, 20:05 #17
Nameless One, именно. Мне просто это решение естественным кажется. Вроде как побочного эффекта от решения другой задачи (т.е. мы решаем задачу собственно реализации функций в брэйнфаке, а побочным эффектом рекурсивного метода является ещё и реализация областей видимости в качестве бонуса).
0
Nameless One
Эксперт С++
5774 / 3424 / 255
Регистрация: 08.02.2010
Сообщений: 7,447
08.02.2011, 21:37 #18
Сделал вариант интерпретатора, в котором новые операции определены немного не так, как хотел ТС (но переделать под свои нужды, ИМХО, несложно). Новые операторы вводят не процедуры в их типичном "паскалевском" понимании, а функции, а именно, функции без переменных, которые возвращают значение текущей на момент возврата ячейки. У каждой функции собственные локальные переменные (ячейки). Переменные из внешней области видимости захватывать нельзя. Можно создавать вложенные определения функций. Операторы '(' и ')', соответственно, определяют начало и конец локальной функции. Оператор ':' вызывает функцию, ID которой задается значением текущей ячейки, и записывает в эту же ячейку возвращаемое значение функции.

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
 
#define E_NOINP 1
#define E_MEM 2
#define E_OPEN 3
#define E_READ 4
#define E_PAR 5
#define E_LV 6
#define E_LF 7
#define E_LP 8
#define E_INV 9
#define E_RANGE 10
#define E_UND 11
 
#define MAX_CELLS_CNT 512
#define MAX_LOCAL_FUN_CNT 16
#define MAX_PROGRAM_LENGTH 1024
 
typedef struct fun
{
    size_t ID;
        
    struct fun* localFuns[MAX_LOCAL_FUN_CNT];
    size_t localsCnt;
    
    char pExpr[MAX_PROGRAM_LENGTH];
} fun_t;
 
fun_t* newFun(size_t ID, char* expr, char** pRet);
void delFun(fun_t* pFun);
unsigned char eval(fun_t* pFun);
 
#ifdef DEBUG
void printFun(const fun_t* pFun);
void printLocals(unsigned char* pLocals, size_t size);
#endif
 
void errExit(int code, const char* fmt, ...);
 
int main(int argc, char* argv[])
{
    FILE* pInp;
    char  buf[MAX_PROGRAM_LENGTH + 3];
    fun_t* pTopFun;
    unsigned char result;
    char* p;
    
    p = buf;
    *p = '(';
        
    if(argc != 2)
    errExit(E_NOINP, "Usage: %s FILE\n", *argv);
 
    if((pInp = fopen(argv[1], "r")) == NULL)
    errExit(E_OPEN, "Can't open file `%s' to input.\n", argv[1]);
 
    do
    {
    if(p - buf == MAX_PROGRAM_LENGTH)
        errExit(E_LP, "Maximal program length (%u sybmols) was reached.\n", MAX_PROGRAM_LENGTH);
    
    *(++p) = fgetc(pInp);
    }
    while(!isspace(*p) && (*p != EOF) && (*p != '\0'));
 
    if(ferror(pInp))
    errExit(E_READ, "Error reading from file `%s'.\n", argv[1]);
 
    *p = '\0';
    
    printf("Expression: `%s'.\n\n", buf + 1);
    fflush(stdout);
 
    *p++ = ')';
    *p++ = '\0';
    
#ifdef DEBUG
    fputs("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n", stderr);
    fputs("Starting parsing...\n\n", stderr);
#endif
 
    pTopFun = newFun(0, buf, NULL);
 
#ifdef DEBUG
    fputs("Parsing is done.\n", stderr);
    fputs("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n", stderr);
    fputc('\n', stderr);
    fputs("Starting evaluation...\n\n", stderr);
#endif
 
    result = eval(pTopFun);
    printf("\nThe result is %u.\n\n", result);
    fflush(stdout);
    
#ifdef DEBUG    
    fputs("Evaluation is done.\n", stderr);
#endif
    delFun(pTopFun);
 
    exit(0);
}
 
fun_t* newFun(size_t ID, char* expr, char** pRet)
{
    fun_t* pFun;
    char* p;
    const char* pExpr;
    
    pExpr = expr;
    
    if((pFun = (fun_t*) malloc(sizeof(fun_t))) == NULL)
    errExit(E_MEM, "Can't allocate memory.\n");
    pFun->ID = ID;
     
    memset(pFun->localFuns, 0, sizeof(fun_t*) * MAX_LOCAL_FUN_CNT);
    pFun->localsCnt = 0;
 
    p = pFun->pExpr;
    ++expr;
    
    while(*expr != ')')
    {
    if(*expr == '(')
    {
        if(pFun->localsCnt == MAX_LOCAL_FUN_CNT)
        errExit(E_LF,
            "Local functions maximum was reached"
            " while parsing expression: `%s'.\n", pExpr);
        
        pFun->localFuns[pFun->localsCnt] = newFun(pFun->localsCnt++, expr, &expr);
    }
    else if(strchr("><+-[],.:", *expr) != NULL)
        *p++ = *expr;
    else if(*expr == '\0')
        errExit(E_PAR, "Mismatched parentheses were detected while parsing expression: `%s'.\n", pExpr);
    else
        errExit(E_INV, "Invalid character: `%c'.\n", *expr);
    
    ++expr;
    }
    
#ifdef DEBUG
    printFun(pFun);
#endif
    
    if(pRet)
    *pRet = expr;
    
    return pFun;
}
 
void delFun(fun_t* pFun)
{
    size_t i;
 
    for(i = 0; i < pFun->localsCnt; ++i)
    {
    delFun(pFun->localFuns[i]);
    pFun->localFuns[i] = NULL;
    }
     
    free(pFun);
    pFun = NULL;
}
 
unsigned char eval(fun_t* pFun)
{
    unsigned char locals[MAX_CELLS_CNT];
    unsigned char* pCurrCell;
    char* pCurrOp;
 
    size_t br = 0;
            
#ifdef DEBUG
    fputs("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n", stderr);
    fputs("Entering function...\n", stderr);
    printFun(pFun);
#endif
 
    memset(locals, 0, sizeof(unsigned char) * MAX_CELLS_CNT);
    pCurrCell = locals;
    pCurrOp = pFun->pExpr;
    
    while(*pCurrOp != '\0')
    {
 
#ifdef DEBUG
    fprintf(stderr, "Current operation: `%c'.\n", *pCurrOp);
    fprintf(stderr, "Current cells's (%u) value: %u.\n", pCurrCell - locals,
        (size_t) *pCurrCell);
#endif
    switch(*pCurrOp)
    {
    case '+':
        ++(*pCurrCell);
        break;
        
    case '-':
        --(*pCurrCell);
        break;
 
    case '>':
        if(pCurrCell >= locals + MAX_CELLS_CNT - 1)
        errExit(E_RANGE, "The next cell's index is out of range [0..%u].\n", MAX_CELLS_CNT - 1);
        ++pCurrCell;
        break;
 
    case '<':
        if(pCurrCell <= locals)
        errExit(E_RANGE, "The previous cell's index is out of range [0..%u].\n", MAX_CELLS_CNT - 1);
        --pCurrCell;
        break;
 
    case ',':
        *pCurrCell = getchar();
        break;
 
    case '.':
        putchar(*pCurrCell);
        fflush(stdout);
        break;
 
    case ':':
        if(*pCurrCell >= pFun->localsCnt)
        errExit(E_UND, "Function with local ID #%u is undefinded.\n", *pCurrCell);
        
        *pCurrCell = eval(pFun->localFuns[*pCurrCell]);
        break;
        
    case '[':
        if(*pCurrCell == 0)
        {
        ++pCurrOp;
        if(*pCurrOp == '\0')
            errExit(E_PAR, "Mismatched parentheses were found in function's body: `%s'.\n", pFun->pExpr);
        ++br;
        while(br != 0)
        {
            if(*pCurrOp == '[')
            ++br;
            else if(*pCurrOp == ']')
            --br;
            ++pCurrOp;
            if(*pCurrOp == '\0')
            errExit(E_PAR, "Mismatched parentheses were found in function's body: `%s'.\n", pFun->pExpr);
        }
        --pCurrOp;
        }
        break;
 
    case ']':
        if(*pCurrCell != 0)
        {
        --pCurrOp;
        if(pCurrOp < pFun->pExpr)
            errExit(E_PAR, "Mismatched parentheses were found in function's body: `%s'.\n", pFun->pExpr);
        ++br;
        while(br != 0)
        {
            if(*pCurrOp == '[')
            --br;
            else if(*pCurrOp == ']')
            ++br;
            --pCurrOp;
            if(pCurrOp < pFun->pExpr)
            errExit(E_PAR, "Mismatched parentheses were found in function's body: `%s'.\n", pFun->pExpr);
        }
        }
    }
    ++pCurrOp;
    }
    
#ifdef DEBUG
    printLocals(locals, 10);
    fprintf(stderr, "Return value: %u.\n", (size_t) *pCurrCell);
    fputs("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n", stderr);
#endif
    return *pCurrCell;
}
 
#ifdef DEBUG
void printFun(const fun_t* pFun)
{
    fprintf(stderr, "Function with local ID #%u:\n", pFun->ID);
    fprintf(stderr, "Body: `%s'\n", pFun->pExpr);
    fprintf(stderr, "Number of local functions: %u.\n\n", pFun->localsCnt);
}
 
void printLocals(unsigned char* pLocals, size_t size)
{
    size_t i;
    
    fprintf(stderr, "The first %u local cells are:\n", size);
    for(i = 0; i < size; ++i)
    fprintf(stderr, "%u ", (size_t) pLocals[i]);
    fputc('\n', stderr);
}
#endif
 
void errExit(int code, const char* fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    vfprintf(stderr, fmt, ap);
    va_end(ap);
    exit(code);
}
Интерпретатор получает из командной строки один аргумент - имя файла, содержащее исходный код программы, и читает из него выражение до тех пор, пока не кончится файл или не встретится пробельный символ или '\0'. После чего происходит разбиение выражения на функции и вычисление главной функции.

Ну и программа для теста, которая выводит зацензуренное название языка (прям как в названии темы):
Код
(+++++++++++[>++++++<-]>)(+++++++++++[>++++++++++<-]>)(+++++++[>++++++<-]>):.>+:++++.>+:-------------.++++++++.>+:.<---.>>++:..<<+++++.

Разбор программы
Помимо главной функции, программа содержит три локальных:
  1. ID = 0: `+++++++++++[>++++++<-]>'. Возвращает число 66 (символ `B'). Сначала последовательно 11 раз инкрементируется значение ячейки 0. Потом эта ячейка используется как счетчик цикла, в котором 6 раз инкрементируется значение ячейки 1. Таким образом, 11 * 6 = 66, это значение и возвращается.
  2. ID = 1: `+++++++++++[>++++++++++<-]>'. Возвращает число 110 (символ `n').
  3. ID = 2: `+++++++[>++++++<-]>'. Возвращает число 42 (символ `*').
Тело главной функции: `:.>+:++++.>+:-------------.++++++++.>+:.<---.>>++:..<<+++++.'. Разберем его по шагам:
  1. :. - вызов функции с ID=0 и печать возвращаемого значения (cимвол `B').
  2. >+:++++. - делаем ячейку 1 текущей, инкрементируем ее, вызываем фукнцию 1, которая возвращает 110, увеличиваем это значение до 114 и печатаем символ `r'.
  3. >+:-------------. - переходим к ячейке 2, вызываем функцию 1, уменьшаем возвращаемое значение до 97 и печатаем его (`a').
  4. ++++++++. - увеличиваем текущее значение до 105 и печатаем его (`i').
  5. >+:. - переходим к ячейке 3, вызываем функцию 1, печатаем возвращаемое значение (`n').
  6. <---. - переходим к ячейке 2, уменьшаем ее старое значение (105) до 102 и печатаем его (`f').
  7. >>++:.. - переходим к ячейке 4, увеличиваем ее значение до 2, вызываем функцию с ID=2 и печатаем возвращаемое значение - 42 (символ `*') - два раза.
  8. <<+++++. - переходим к ячейке 2, увеличиваем ее старое значение (102) до 107 и печатаем его (символ `k').


Не по теме:

Кстати, Wikipedia почему-то считает LOLCODE диалектом сабжа

2
perimetral
1 / 1 / 0
Регистрация: 17.12.2010
Сообщений: 16
08.02.2011, 23:38  [ТС] #19
Суть в том, что мне лично не нужно, дабы у каждой функции была своя область видимости. Ибо с общей областью видимости программист может передавать параметры (например, в следующих ячейках).
0
perimetral
1 / 1 / 0
Регистрация: 17.12.2010
Сообщений: 16
08.02.2011, 23:47  [ТС] #20
Недавно вот тут: http://www.cyberforum.ru/cpp-beginners/thread239337 я просил вас о помощи в реализации интерпретатора Brainf**ck с процедурами. Предложенный вариант не подошел тем, что присутствует ограничение области видимости процедуры. А тем временем я дописал свой интерпретатор, но возникла новая проблема - неизвестная ересь при работе с процедурами. Я сделал парсер отдельной функцией, которую и вызываю при старте программы; при встрече процедуры я вызываю парсер на текст внутри процедуры. Проблема в том, что текст в процедурах не парсится, не знаю, почему. Я бы и сам нашел ошибку, если бы мог ходить отладкой (F10) по коду, но не могу, ибо нужно вводить аргумент в cmd, чего при отладке по F10 нельзя. Кстати, VS2010. Вот код:
Код
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include "stdafx.h"
#include <iostream>
#include <fstream>
using namespace std;
 
const int MAX = 32767;
 
void parse(char * txt, int pos, int now, int * inf, bool isproc) {
    int len = strlen(txt); int i=0, i3=0, i2=0, toreturn=0; char ** procZ = new char *, * tmp = new char; bool * isp = new bool;
    while (pos<len) {
        switch (txt[pos]) {
        case '<': {
            now++; if (now == MAX) now = 0; pos++;
            break; }
        case '>': {
            now--; if (now == 0) now = MAX; pos++;
            break; }
        case '+': {
            inf[now]++; pos++;
            break; }
        case '-': {
            inf[now]--; pos++;
            break; }
        case ',': {
            inf[now] = getchar(); pos++;
            break; }
        case '.': {
            putchar(inf[now]); pos++;
            break; }
        case '[': {
            if (inf[now] != 0) {
                pos++;
            } else if (inf[now] == 0) {
                i = pos;
                while (txt[i] != ']') { pos++; i++; } }
            break; }
        case ']': {
            if (inf[now] == 0) {
                pos++;
            } else if (inf[now] != 0) {
                i = pos;
                while (txt[i] != '[') { pos--; i--; } }
            break; }
        case ')': {
            if (isproc) {
                pos=len;
            } break; }
        case '(': {
            if (isproc) {
                cout<<"Синтаксическая ошибка на "<<pos+1<<"м символе"; pos=len; break; } else {
            i3 = inf[now];
            procZ[i3] = new char;
            tmp = procZ[i3];
            i = pos; i2 = 0;
            while (txt[i] != ')') {
                tmp[i2] = txt[i]; i2++; i++;
            }
            procZ[i3] = tmp;
            isp[i3] = true;
            pos = i+1;
            break; } }
        case ':': {
            i3 = inf[now];
            tmp = procZ[i3];
            if (isp[i3]) {
                parse(tmp, pos, now, inf, true); } else { cout<<"Попытка вызвать несуществующую процедуру на "<<pos+1<<"м символе";
                pos=len; }
            pos++;
            break; }
        default: {
            pos++; break; }
        } }
}
 
void work(char * txt) {
    int len = strlen(txt), i=0, pos=0, now=100, inf[MAX];
    char ** procZ = new char *; char * tmp = new char;
    while (i<MAX) {
        inf[i] = 0; i++; } i=0;
    parse(txt, pos, now, inf, false);
}
 
int main(int argc, char * argv[])
{
    fstream f = fstream(); setlocale(LC_ALL, "Russian");
    bool towork = true; char * txt = new char;
    if (argc < 2) {
        cout<<"Вы не ввели имя файла";
        towork = false; }
    else if (argc > 2) {
        cout<<"Вы ввели лишний параметр";
        towork = false; }
    if (towork) {
        f.open(argv[1], ios::in);
        f >> txt;
        work(txt);
        cout<<endl<<"Программа завершилась";
        f.close();
    }
    return 0;
}


 Комментарий модератора 
Не нужно плодить темы про одно и то же. Да и ссылку Вы неправильную дали...
0
Nameless One
Эксперт С++
5774 / 3424 / 255
Регистрация: 08.02.2010
Сообщений: 7,447
09.02.2011, 05:06 #21
Цитата Сообщение от perimetral Посмотреть сообщение
Я бы и сам нашел ошибку, если бы мог ходить отладкой (F10) по коду, но не могу, ибо нужно вводить аргумент в cmd, чего при отладке по F10 нельзя. Кстати, VS2010.
Студии под рукой нет, но, если не ошибаюсь, можно в свойствах проекта в разделе "Отладка" (Debugging) указать аргументы командной строки для отладки.

Добавлено через 7 минут
Вот, собственно, руководство, как это сделать: http://msdn.microsoft.com/ru-ru/libr...(v=VS.90).aspx.
И вопрос: что мешает, если уж ты не разобрался, как задать аргументы командной строки при отладке, "зашить" необходимое значение в коде самой программы, например, вот так:
C++
1
2
3
4
int main(/*int argc, char* argv[]*/)
{
    ifstream f = ifstream("testfile.bf");
    // ... и так далее
Добавлено через 9 минут
Цитата Сообщение от perimetral Посмотреть сообщение
Предложенный вариант не подошел тем, что присутствует ограничение области видимости процедуры
Если не хочешь доделывать свой вариант, можно легко переделать мой, чтобы он удовлетворял твоим требованиям. Нужно всего лишь заменить дерево fun_t на глобальный массив и немного изменить функции разбора и вычисления.
0
silent_1991
Эксперт С++
4984 / 3041 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
09.02.2011, 14:07 #22
perimetral, проверяйте, то, что вам надо?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
 
void interpret(std::string &, const char *, const char *);
int interpret_helper(std::string &, const char *, const char *, int *, int);
 
int main(int argc, char *argv[])
{
    setlocale(LC_ALL, "Rus");
    
    if (argc != 4)
    {
        std::cerr << "Программа должна быть запущенна в виде" << std::endl
                  << "имя_программы имя_входного_файла имя_файла_входных_данных имя_файла_выходных_данных" << std::endl;
 
        exit(1);
    }
    
    std::ifstream fprog(argv[1]);
 
    std::string prog;
    std::string temp;
 
    while (fprog >> temp)
        prog += temp;
 
    fprog.close();
 
    interpret(prog, argv[2], argv[3]);
 
    return 0;
}
 
void interpret(std::string &prog, const char *input_file_name, const char *output_file_name)
{
    int memory[2048] = {0};
    
    interpret_helper(prog, input_file_name, output_file_name, memory, 0);
}
 
int interpret_helper(std::string &prog, const char *input_file_name, const char *output_file_name, int *memory, int index)
{
    std::ifstream input(input_file_name);
    std::ofstream output(output_file_name);
 
    std::vector< int > loop(prog.size());
 
    int level = 1;
 
    for (size_t i = 0; i < prog.size(); ++i)
    {
        loop[i] = 0;
 
        if (prog[i] == '[')
            loop[i] = level++;
        else
        {
            if (prog[i] == ']')
                loop[i] = --level;
        }
    }
 
    std::map< int, std::string > funcs;
 
    int start_index = index;
 
    for (size_t i = 0; i < prog.size(); ++i)
    {
        switch (prog[i])
        {
        case '>':
            ++index;
 
            break;
        case '<':
            --index;
 
            break;
        case '+':
            ++memory[index];
 
            break;
        case '-':
            --memory[index];
            break;
        case '.':
            output << memory[index];
 
            break;
        case ',':
            input >> memory[index];
 
            break;
        case '[':
            if (memory[index] == 0)
            {
                level = loop[i++];
 
                while (loop[i] != level)
                    ++i;
            }
 
            break;
        case ']':
            if (memory[index] != 0)
            {
                level = loop[i--];
 
                while (loop[i] != level)
                    --i;
 
                --i;
            }
 
            break;
        case '(':
        {
            size_t left_bracket, right_bracket;
 
            left_bracket = i + 1;
 
            while (prog[++i] != ')');
 
            right_bracket = i;
 
            std::string func;
 
            for (size_t k = left_bracket; k < right_bracket; ++k)
                func += prog[k];
 
            funcs.insert(std::make_pair(memory[index], func));
 
            break;
        }
        case ':':
            index = interpret_helper(funcs[memory[index]], input_file_name, output_file_name, memory, index + 1);
            
            break;
        default:
            std::cerr << "Синтаксическая ошибка в позиции " << i << std::endl;
 
            exit(1);
        }
    }
 
    return start_index - 1;
}
1
perimetral
1 / 1 / 0
Регистрация: 17.12.2010
Сообщений: 16
09.02.2011, 18:52  [ТС] #23
silent_1991, Спасибо, работает как надо, осталось разобраться с vector, ибо мне преподу еще пояснять как это все работает. Но все равно благодарен =)
0
silent_1991
Эксперт С++
4984 / 3041 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
09.02.2011, 20:03 #24
perimetral, это я ещё по минимуму STL использовал. Выдирание функции из текста программы сделано полностью вручную, можно было всё это стандартными алгоритмами провернуть.
0
Yandex
Объявления
09.02.2011, 20:03
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru