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

Пишем свой интерпретатор языка BASIC - C++

Восстановить пароль Регистрация
Другие темы раздела
C++ Меню и список http://www.cyberforum.ru/cpp-beginners/thread41194.html
Здравствуйте форумчане. Помоги пожалуйста в следующем вопросе: У меня есть 2связный список, написано меню. Но в моменте когда написано make a list и delete custom необходимо чтобы выводились: Введите элемент и номер. вот сам код: #ifndef __list_h #define __list_h #include <iostream>
C++ Здравствуйте! Не могу поместить class в один файл с программой. file.hpp #include "Cat.hpp" // здесь классы "2)" Cat::Cat(int initialAge) { itsAge = initialAge; } Cat::~Cat() { http://www.cyberforum.ru/cpp-beginners/thread41186.html
Массивы строк C++
Привет всем! Задан массив строк. Как узнать который символ встечаетса найбольшое количество раз в етом массиве?
C++ вывод на экран набор треугольников и квадратов, которые произвольно двигаются и меняют размер
Please, help me!!! Вот текст программы, которая выводит на экран набор треугольников и квадратов, которые произвольно двигаются и меняют размер только квадратов. Проблема в том, что необходимо исправить код, чтоб фигуры не исчезали за экран (т.е. 640х460) и были компактным набором, т.е. двигались неменяя своего положения относительно друг друга и стукаясь об стенку экрана меняли свое...
C++ Округление дробного числа до целого в большую сторону. http://www.cyberforum.ru/cpp-beginners/thread41139.html
Доброго дня. Я новичок в программирование на Visual C++. Проблема такая программа должна считать кол-во месяцев, если числа целые то программа шла дальше, если дробное то (например 3.33333) программа не округляет это число (в большую сторону) до 4. Перелопатил тонны литературы, но пропустил или не нашёл этого, большая просьба написать функцию которая могла бы это делать, или способ какой.
C++ Код из Delphi в C++ Нужно написать курсовую на C++. Сам я в программировании плохо шарю (не программист). Попросил у народу помощи, помогли. Но решение на Delphi: {$APPTYPE CONSOLE} type byteset=set of byte; var d:array of longint; procedure c; var a,b,i:longint; подробнее

Показать сообщение отдельно
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16935 / 5340 / 328
Регистрация: 30.03.2009
Сообщений: 14,354
Записей в блоге: 26
13.07.2009, 09:36     Пишем свой интерпретатор языка BASIC
Цитата Сообщение от #pragma Посмотреть сообщение
Хм,я объясню,почему выбрал этот вариант. Сначала я делал именно с Value как членом класса,но потом выяснилось,что необходим вызов конструктора Value,то есть требовалась запись вроде такой
C++
1
Variable a(paser_CurTokenStr,CONST_INT)
Чтобы сделать возможной вызов конструктора Value,причём получается что нужно,чтобы в paser_CurTokenStr было не имя переменной,а строка для константы. Я не нашёл другого способа,кроме как перегрузить оператор = для Variable. А как тебе видится решение?
А в каких случаях тебе нужно создавать переменную со значением? Просто для конструкции "LET a=5" получается что-то типа того:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/* Ожидаем конструкцию вида Ident "=" Expr */
void
syntax_StmtLET (void)
{
  Variable *var;
  Value val;
 
  /* Читаем имя переменной (девая часть присваивания) */
  var = syntax_Ident(); // <--- здесь реализовано синтаксическое правило Ident
 
  /* Знак "=" */
  if (parser_GetToken() != TOKEN_DELIM_EQUAL)
    error ("syntax error near %s", parser_CurTokenStr);
 
  /* Значение выражения (правая часть присваивания) */
  val = syntax_Expr(); // <--- здесь реализовано синтаксическое правило Expr
 
  /* Строим присваивание */
  var->SetValue(val);
}
Добавлено через 22 минуты 36 секунд
syntax_parser.c строки 49-50. Ты пишешь, что создаёшь переменную, но это не правильно. Ты в данный момент парсишь ПРАВУЮ часть присваивания, т.е. там, где нужно читать значения. Т.е. все переменные уже должны быть созданы, а ты в этот момент НЕ создаёшь новую переменую, а достаёшь в таблице уже СУЩЕСТВУЮЩУЮ переменную и берёшь от неё значение. Если переменная не существует, то тут выбираешь как действовать: либо выдавать ошибку, либо считать, что для несуществующеё переменной значение равно нулю. Я бы выбрал первый вариант.

Возможно мне следовало пояснить момент, который для тебя совсем неочевиден. Имя переменной (в нашем случае это синтаксическое правило Ident) может встретиться в присваивании в правой части или в левой. В этих двух случаях оно трактуется по разному. Устоявшиеся технические термины для этого lvalue (от слова left) и rvalue (от right).

Когда имя переменной стоИт в позиции rvalue, то это означает, что нам нужно прочитать ЗНАЧЕНИЕ этой переменной, а когда в позиции lvalue (т.е. фактически мы хотим записать в переменную), то говорят, что нужно АДРЕС переменной. Адрес не в буквальном смысле слова, а в абстрактном - т.е. это нечто, при помощи которого мы можем записать значение в переменную. Иногда rvalue и lvalue называют соотвественно VALUE POSITION и NAME POSITION, но это несколько неудобная терминология из-за слова NAME

Вот примеры того, как переменная "AAA" находится в разных позициях

PureBasic
1
2
3
4
5
6
7
b = 1 + AAA    <--- rvalue (значение)
b = COS (AAA)  <--- rvalue (значение), имеем значение среди параметров
         (а необязательно после знака присваивания
 
AAA = 1  <--- lvalue (адрес)
INPUT AAA  <--- lvalue (адрес), т.е. здесь знака присваивания нет, но семантика
         оператора INPUT такова, что в переменную нужно записывать
Поэтому технически над синтаксическим правилом Ident можно сделать две настройки

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
Variable*
syntax_Ident (void)
{
  // Разгребаем имя переменной. Создаём переменную и возвращаем
  // на неё указатель. У меня была идея избавиться от создания
  // переменных без константы, но такой вариант принесёт больше гемора,
  // чем пользы. Лучше в переменной иметь дополнительный признак,
  // инициализирована переменная или нет. Поэтому вданной процедуре
  // мы просто заводим неинициализированную переменную
}
 
// Разбор имени переменной в левой части присваивания. Именно эту
// процедуру надо подставить в мой вышестоящий код. Здесь нам нужен
// только АДРЕС переменной (в том понятии, котором я описал выше),
// а поэтому просто возвращаем ссылку на созданную переменную
Variable*
syntax_IdentLValue (void)
{
  return syntax_Ident();
}
 
// Разбор имени переменной в левой части присваивания. Здесь
// нам нужно вернуть значение переменной
Value
syntax_IdentRValue (void)
{
  Variable *var;
 
  var = syntax_Ident();
 
  if (var неинициализирована)
    error ("неинициализированная переменная %s", var->GetName());
 
  return var->GetValue();
}
Вот что-то типа того

============================================

Ещё момент по твоему коду: value_class.h строки 85 и 86.
Именно то место, где слодовало бы поставить ASSERT (внутренний контроль), что от целой переменной нельзя брать плавающее значение и наоборот. Хотя в теории эти методы вообще не должны использоваться за пределами модуля Value (потому как все операции перегружены, печать значения реализована в виде интерфейса, больше снаружи вроде бы как незачем)

Добавлено через 5 минут 59 секунд
Я понял, почему у тебя получалось создание переменной непосредственно со значением. Но нужно было бы это делать с Value (т.е. распарсили строковое имя переменной, вытащили правую часть в виде Value, создали переменную с Value). Но засада в том, что тут переменную надо НЕ создавать, а записывать в неё (т.е. если переменная уже создана, то новая переменная не нужна)
 
Текущее время: 00:19. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru