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

Поразрядное отрицание - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 20, средняя оценка - 4.85
pepsikat
 Аватар для pepsikat
292 / 12 / 2
Регистрация: 21.12.2010
Сообщений: 295
01.06.2011, 12:37     Поразрядное отрицание #1
В общем мне нужно посторить транслятор программ заданного языка, реализующий механизм рекурсивного спуска.
Все работает кроме поразрядного НЕ. Помогите найти ошибку.

допустим если C=~1100, то результат должен быть С=0011. А он фигню какуето выводит.
Я так подозреваю что ошибка кроется в процедуре long ProcC(void). А как исправить не знаю.

Грамматика описана в коментарии в коде.
Пример входного файла с верной программой:
z1=001&100;
z1=001|100;
f=~111;
f=~101;
b101=1;
b=1;
c=0;
f=1|0&1;
d=~(b&c);
d=~c;
z10101=~0;


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
//---------------------------------------------------------------------------
 
#include <vcl.h>
#pragma hdrstop
 
#include <tchar.h>
//---------------------------------------------------------------------------
 
#pragma argsused
 
//---------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
 
using namespace std;
 
#define MAX_ID_LEN 50
#define MAX_VARS 20
 
/*
  S ::= I=E;                  Оператор присваивания
  E ::= E"|"T| T              Операция поразраднного ИЛИ
  T ::= T&M | M               Операция поращрядного И
  M ::= (E) | ~M | I | C      Cкобки,Поразрядное НЕ,  переменная, константа
  I ::= A | AK                Идентификатор: первая буква далее цифры
  K ::= D | DK                цифры
  C ::= D | CD                Константа: последовательность цифр
  A ::= a | b | ... | z | _   Буквы
  D ::= 0 | 1 |               Цифры
 
Пустые символы (пробелы, ентеры и т.п.) внутри
оператора или выражения не допускаются, но могут
быть между операторами, перед первым оператором
и после последнего.*/
 
// Обработка ошибок: вывод сообщения и завершение программы
void Error(const char * msg, const char * param);
 
// Обработка переменных:
long * VarPointer(const char * name);   // получение адреса переменной
long VarValue(const char * name);       // получение значения переменной
void VarPrint(void);                    // печать последней переменной
void VarPrintAll(void);                 // печать всех переменных
 
// Считать следующий символ
inline void Get(void);
 
// Процедуры разбора нетерминальных символов
void ProcS(void);
long ProcE(void);
long ProcT(void);
long ProcM(void);
long ProcI(void);   // там же внутри разбор A, K, D
long ProcC(void);   // D внутри, незачем для терминалов процедуры писать
long * ProcL(void); // это как I, только слева от =, потому и L, т.к.
                    // требуется присвоить значение этой переменной,
                    // а если переменная в выражении - то получить ее
                    // значение (это ProcI делает)
 
 
// Структура для хранения переменной
struct var
{
  char name[MAX_ID_LEN];
  long value;
};
 
var v[MAX_VARS];          // массив переменных
int n = 0;                // их количество
int last = -1;            // и номер последней присвоенной
 
FILE * f = 0;
int c = EOF;
 
 
 
void Error(const char * msg, const char * param)
{
  printf("Error: ");        // вместо этой функции можно использовать
  printf(msg, param);       // собственный класс исключения, объект
  printf("\n");             // которого будет содержать текстовое
  fclose(f);                // описание ошибки, ее код и т.п.,
  getch();
  exit(7);                  // а на верхнем уровне его обрабатывать
}
 
 
 
long * VarPointer(const char * name)
{
  if (!*name)
    Error("Syntax error.", 0);
 
  for (int i = 0; i < n; i++)
    if (strcmp(v[i].name, name) == 0)
      return &v[last = i].value;
 
  if (n >= MAX_VARS - 1)
    Error("Too many variables.", 0);
 
  strcpy(v[n].name, name);
  last = n;
  return &v[n++].value;
}
 
long VarValue(const char * name)
{
  if (!*name)
    Error("Syntax error.", 0);
 
  for (int i = 0; i < n; i++)
    if (strcmp(v[i].name, name) == 0)
      return v[i].value;
 
  Error("Undefined identifier \'%s\'.", name);
}
 
void VarPrint(void)
{
  if (last < 0)
    printf("No variables defined yet.\n");
  else
    printf("  %s = %ld\n", v[last].name, v[last].value);
}
 
void VarPrintAll(void)
{
  if (!n)
    printf("No variables defined yet.\n");
  else
    for (int i = 0; i < n; i++)
      printf("%s = %ld\n", v[i].name, v[i].value);
}
 
 
 
inline void Get(void)
{
  c = fgetc(f);
}
 
 
 
// Levels III-VI
 
long ProcC(void)
{
  long x = 0;
  while (c >= '0' && c <= '1')    // пока идут цифры
  {
    x *= 10;                      // собираем из них число
    x += c - '0';                 // по правилам позиционной
    Get();                        // системы счисления
  }
  return x;
}
 
long ProcI(void)
{
  char s[MAX_ID_LEN + 1] = {0};
  int i = 0;
    while ((!i)&&(c >= 'a' && c <= 'z') || c == '_' ||   // если это первая буква
    (i && c >= '0' && c <= '1'))                 // а после буквы цифры
  {
    if (i >= MAX_ID_LEN)                         // и длина не превысила
      Error("Too long identifier \'%s\'.", s);   // допустимую, то
    s[i++] = c;                                  // собираем их
    Get();
  }
  if (!i)                                        // нашли что-нибудь?
    Error("Identifier missing.", 0);
  return VarValue(s);                 // возвращаем значение переменной
}
 
long * ProcL(void)
{
  char s[MAX_ID_LEN + 1] = {0};                  // аналогично
  int i = 0;
  while ((!i)&&(c >= 'a' && c <= 'z') || c == '_' ||
    (i && c >= '0' && c <= '1'))
  {
    if (i >= MAX_ID_LEN)
      Error("Too long identifier \'%s\'.", s);
    s[i++] = c;
    Get();
  }
  if (!i)
    Error("Identifier missing.", 0);
  return VarPointer(s);               // но возвращаем адрес переменной
}
 
 
// Level II
 
long ProcM(void)
{
  long x;
 
  if (c == '(')                    // выражение в скобках
  {
    Get();
    x = ProcE();                      // вычисляем
    if (c != ')')                     // скобку закрыть не забыли?
      Error("\')\' missing.", 0);
    Get();
  }
  else
    if (c == '~')                  // поразрядное НЕ
    {
      Get();
      x =~(ProcM());                   // вычисляем
    }
    else
      if (c >= '0' && c <= '1')    // константа
        x = ProcC();                  // находим
      else
        if ((c >= 'a' && c <= 'z') || c == '_')  // переменная
          x = ProcI();                              // берем значение
        else
          Error("Syntax error.", 0);  // неизвестно что
 
  return x;            // возвращаем найденное значение
}
 
long ProcT(void)
{
  long x = ProcM();               // находим операнд
  while (c == '&')    // и пока идут операции
  {
    char p = c;                   // запоминаем операцию
    Get();
    x = x & ProcM();               //или поразрядное И
  }
  return x;
}
 
long ProcE(void)
{
  long x = ProcT();               // аналогично
  while (c == '|')
  {
    char p = c;
    Get();
    x = x | ProcT();
  }
  return x;
}
 
 
// Level I
 
void ProcS(void)
{
  long * p = ProcL();             // левый операнд - идентификатор
  if (c != '=')                   // потом =
    Error("\'=\' missing.", 0);
  Get();                          // затем находим значение
  *p = ProcE();                   // выражения - правый операнд
  if (c != ';')                   // дальше должен быть ;
    Error("\';\' missing.", 0);
  Get();
}
 
 
// High level
 
void Run(void)
{
  int i;
  Get();                          // берем первый символ и
  for (i = 1; ; i++)          // в цикле выполняем:
  {
    while (c >= 0 && c <= ' ')    // поглощаем пустые символы
      Get();                      // до, между и после операторов
    if (c == EOF)                 // и если не конец файла
      break;
    printf("Operator %2d: ", i);
    ProcS();                      // то разбираем следующий оператор
    VarPrint();                   // и выводим результат для контроля
  }
  printf("Result (%d variables defined in %d operators):\n", n,--i);
  VarPrintAll();
}
 
 
int main(int argc, char ** argv)
{
  printf("\n");
  if (argc < 2)
  {
    printf("Command line parameter (file name) missing.");
    return 1;
  }
 
  f = fopen(argv[1], "rb");
  if (!f)
  {
    printf("Can't open file \'%s\'.", argv[1]);
    return 2;
  }
 
  Run();             // выполняем разбор программы
 
  fclose(f);
  getch();
  return 0;
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.06.2011, 12:37     Поразрядное отрицание
Посмотрите здесь:

Поразрядное вычисление N+1
C++ Поразрядные поразрядное И (&)
C++ "Поразрядное Исключающее Или" с присваиванием
VBA Зачем нужно поразрядное сравнение в VBA
Поразрядное "и" C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
01.06.2011, 19:48     Поразрядное отрицание #2
Глубоко не вникал
Цитата Сообщение от pepsikat Посмотреть сообщение
допустим если C=~1100, то результат должен быть С=0011. А он фигню какуето выводит.
Это так, если запись числа интерпретируется как двоичная. Кстати, при вычислениях в функции ProcM в операции ~ будет участвовать столько бит, сколько их влезает в переменную типа long.
Цитата Сообщение от pepsikat Посмотреть сообщение
Я так подозреваю что ошибка кроется в процедуре long ProcC(void). А как исправить не знаю.
Насколько я вижу ProcC интерпретирует запись как десятичную. Раз в ProcM от неё ожидается интерпретация двоичной записи, то вот и получается фигня. Правда смущает что в остальных местах работает. Где-нибудь в программе есть место для десятичных чисел?
Ну или нужны примеры — что ожидается, а что получается.
pepsikat
 Аватар для pepsikat
292 / 12 / 2
Регистрация: 21.12.2010
Сообщений: 295
01.06.2011, 23:58  [ТС]     Поразрядное отрицание #3
Цитата Сообщение от grizlik78 Посмотреть сообщение
Насколько я вижу ProcC интерпретирует запись как десятичную. Раз в ProcM от неё ожидается интерпретация двоичной записи, то вот и получается фигня.
Да, в этом проблема, только я не знаю как ее исправить...
Цитата Сообщение от grizlik78 Посмотреть сообщение
Где-нибудь в программе есть место для десятичных чисел?
нет, только 0 или 1.
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
02.06.2011, 00:01     Поразрядное отрицание #4
Ну тогда, наверное,
C++
1
2
3
4
5
6
7
8
9
10
11
long ProcC(void)
{
  long x = 0;
  while (c >= '0' && c <= '1')    // пока идут цифры
  {
        x *= 2;                      // собираем из них число
        x += c - '0';                 // по правилам позиционной
        Get();                        // системы счисления
  }
  return x;
}
Правда меня смущает, что "всё остальное работает"
accept
4838 / 3237 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
02.06.2011, 07:18     Поразрядное отрицание #5
C++
1
printf(msg, param);
вместо этого используй vprintf()

получится
C++
1
void Error(const char *fmt, ...);
Yandex
Объявления
02.06.2011, 07:18     Поразрядное отрицание
Ответ Создать тему
Опции темы

Текущее время: 04:05. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru