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

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

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 20, средняя оценка - 4.85
pepsikat
292 / 12 / 2
Регистрация: 21.12.2010
Сообщений: 295
#1

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

01.06.2011, 12:37. Просмотров 2562. Ответов 4
Метки нет (Все метки)

В общем мне нужно посторить транслятор программ заданного языка, реализующий механизм рекурсивного спуска.
Все работает кроме поразрядного НЕ. Помогите найти ошибку.

допустим если 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
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Поразрядное отрицание (C++):

Поразрядное сравнение чисел - C++
Здравствуйте. Нужно написать программу сравнения двух чисел размера N. Они должны быть представлены в виде целочисленных массивов. Кто-...

Поразрядные поразрядное И (&) - C++
есть такой пример a%16 = a&amp;(16-1) как преобразовать тогда тогда a%2, a%3, a%4, a%10? Добавлено через 13 минут извините за...

XOR и поразрядное или не работают - C++
Собственно есть числа: 0011 0010 - bit_text==1(идём справа налево) 0100 0011 - это биты val_bmp какого-то числа. Мне надо bit_text...

Бинарное отрицание ~ - C++
Имеется 2 массива шестнадцатеричных чисел: 1) на 6 чисел 2) на 2 числа Требуется заполнить 3й массив 4 первых элемента первого...

"Поразрядное Исключающее Или" с присваиванием - C++
Бъясните пожалуйста как работает &quot;Поразрядное исключающее ИЛИ с присваиванием(^=)&quot; на примере: mass^= mass^= mass^= mass;

Как можно реализовать отрицание множества на с++? - C++
Как можно реализовать отрицание множества на с++? .Имеется два множества A и В, как сделать отрицание?

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
grizlik78
Эксперт С++
1908 / 1440 / 111
Регистрация: 29.05.2011
Сообщений: 2,996
01.06.2011, 19:48 #2
Глубоко не вникал
Цитата Сообщение от pepsikat Посмотреть сообщение
допустим если C=~1100, то результат должен быть С=0011. А он фигню какуето выводит.
Это так, если запись числа интерпретируется как двоичная. Кстати, при вычислениях в функции ProcM в операции ~ будет участвовать столько бит, сколько их влезает в переменную типа long.
Цитата Сообщение от pepsikat Посмотреть сообщение
Я так подозреваю что ошибка кроется в процедуре long ProcC(void). А как исправить не знаю.
Насколько я вижу ProcC интерпретирует запись как десятичную. Раз в ProcM от неё ожидается интерпретация двоичной записи, то вот и получается фигня. Правда смущает что в остальных местах работает. Где-нибудь в программе есть место для десятичных чисел?
Ну или нужны примеры — что ожидается, а что получается.
pepsikat
292 / 12 / 2
Регистрация: 21.12.2010
Сообщений: 295
01.06.2011, 23:58  [ТС] #3
Цитата Сообщение от grizlik78 Посмотреть сообщение
Насколько я вижу ProcC интерпретирует запись как десятичную. Раз в ProcM от неё ожидается интерпретация двоичной записи, то вот и получается фигня.
Да, в этом проблема, только я не знаю как ее исправить...
Цитата Сообщение от grizlik78 Посмотреть сообщение
Где-нибудь в программе есть место для десятичных чисел?
нет, только 0 или 1.
grizlik78
Эксперт С++
1908 / 1440 / 111
Регистрация: 29.05.2011
Сообщений: 2,996
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
4821 / 3241 / 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, ...);
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
02.06.2011, 07:18
Привет! Вот еще темы с ответами:

Составить логический калькулятор (конъюнкция, дизъюнкция, отрицание) на C или C++ - C++
Помогите, пожалуйста, составить программу, которая реализует логический калькулятор.

Поразрядное "и" - C++
A = 12 B = 8 C = 34 D = 123 D - выполнить поразрядное «и» 1-6 разрядов В и 0-2 разрядов С, сдвинутых вправо на 1 разряд. ...

Отрицание xy это значит умножение х на у или отрицание х + отрицание у - Логика и множества
отрицание xy это значит умножение х на у или отрицание х + отрицание у,в таблице истинности незнаю как делать

Поразрядное вычисление N+1 - Алгоритмы
Доброго времени суток всем форумчанам! Хотел попросить помощи у разбирающихся в вопросе. Сразу скажу, вопрос более чем просто...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
02.06.2011, 07:18
Ответ Создать тему
Опции темы

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