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

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

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 1509, средняя оценка - 4.80
#pragma
Временно недоступен
954 / 225 / 6
Регистрация: 12.04.2009
Сообщений: 921
#1

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

20.06.2009, 20:03. Просмотров 195128. Ответов 464
Метки нет (Все метки)

*****************
Благодаря форуму и Evg в частности интерпретатор развивается, потихоньку превращаясь в простенький интерпретатор QBASIC.
Некоторые из самых старых версий сохранились в теме и ссылки на них будут добавлены в это сообщение,а также ссылки на другие темы,связанные с этой.

Репозиторий с проектом находится тут, там же есть возможность в браузере посмотреть историю ревизий (английский в логах весьма примитивен,комментарии и рекомендации можете писать в личку),а также скачать самый последний архив репозитория в формате .tar.gz
Если кто-то пользуется Subversion,скачать исходники можно так:
Код
svn co https://basin.svn.sourceforge.net/svnroot/basin basin
Эти темы возникли в результате моих вопросов по ходу написания:
Технический приём для формирования согласованных данных
Makefile: как с использованием gcc строить автоматические зависимости от .h файлов?
Вопрос по svn (Subversion)
Создание системы тестирования ПО.
Вопрос про разные реализации бэйсиков
Можно ли выразить порядковый номер элемента массива через индексы?
[C++] Какие флаги указать линкеру для компиляции программы?
Как можно определить переменную в файле configure.in,чтобы её можно было использовать в Makefile?
Странный SIGSEGV, или что зависит от порядка написания интерфейса класса
[C++]Можно ли как-то указать в Makefile,чтобы часть файлов компилировал компилятор C?
Альтернативная версия интерпретатора от Evg на C
Это простая реализация разбора выражений, написанная Evg на C:
Представление выражения в двоичном дереве
*****************
Первое сообщение:
*****************
Задание(Страуструп,из книги,по готовому коду): Введите программу калькулятора и заставьте её работать.Например,при вводе
C++
1
2
r = 2.5
area = pi*r*r
Программа калькулятора выведет:
C++
1
2
2.5
19.635
Получили такой код:
LexicalAnalyzer.h
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
// LexicalAnalyzer.h
#ifndef LEXICALANALYZER_H_INCLUDED
#define LEXICALANALYZER_H_INCLUDED
 
#include <cctype>
#include <string>
#include <map>
#include <iostream>
 
enum Token_value {
    NAME,       NUMBER,      END,
    PLUS = '+', MINUS = '-', MUL = '*', DIV = '/',
    PRINT = ';',ASSIGN = '=',LP = '(',  RP = ')'
};
extern Token_value curr_tok;
extern std::map<std::string,double>table;
extern int no_of_errors;
 
Token_value get_token();
 
double expr(bool);
double term (bool);
double prim (bool);
int error(const std::string&);
 
#endif // LEXICALANALYZER_H_INCLUDED

LexicalAnalyzer.cpp
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
// LexicalAnalyzer.cpp
#include "LexicalAnalyzer.h"
 
 
std::map<std::string,double>table;
Token_value curr_tok=PRINT;
 
double expr (bool get)
{
    double left = term(get);
 
    for (;;)
        switch (curr_tok) {
            case PLUS:
                 left += term(true);
            break;
            case MINUS:
                 left-= term(true);
            break;
            default:
                 return left;
        }
}
 
double term (bool get)
{
    double left = prim (get);
 
    for (;;)
        switch (curr_tok) {
            case MUL:
                 left*=prim(true);
            break;
            case DIV:
                 if (double d = prim (true)) {
                     left /= prim (true);
                     break;
                 }
                 return error("Деление на ноль");
            default:
                 return left;
        }
}
 
double number_value;
std::string string_value;
 
double prim (bool get)
{
    if (get) get_token();
    switch (curr_tok){
        case NUMBER:{
            double& v = number_value;
            get_token();
            return v;
        }
        case NAME:{
            double& v = table[string_value];
            if (get_token()==ASSIGN) v = expr(true);
            return v;
        }
        case MINUS:
            return -prim(true);
        case LP:{
            double e = expr(true);
            if (curr_tok!=RP) return error("Ожидалась )");
            get_token();
            return e;
        }
        default:
            return error("Ожидалось первичное выражение");
    }
}
 
Token_value get_token()
{
    char ch = 0;
 
    do {
        if (!std::cin.get(ch)) return curr_tok = END;
    } while (ch!='\n'&&isspace(ch));
 
    switch (ch) {
        case 0:
             return curr_tok = END;
        case ';':case '\n':
             return curr_tok = PRINT;
        case '*':case'/':case '+':case '-':case '(':case ')':case '=':
             return Token_value(ch);
        case '0':case '1':case '2':case '3':case '4' :
        case '5':case '6':case '7':case '8':case '9':case '.':
             std::cin.putback(ch);
             std::cin>>number_value;
             return curr_tok=NUMBER;
        default:
             if (isalpha(ch)) {
                 string_value = ch;
                 while (std::cin.get(ch)&&isalnum(ch)) string_value.push_back(ch);
                 std::cin.putback(ch);
                 return curr_tok = NAME;
             }
             error ("Неправильная лексема");
             return curr_tok = PRINT;
    }
}
int no_of_errors=0;
int error (const std::string& s)
{
    no_of_errors++;
    std::cerr<<"Ошибка: "<<s<<'\n';
    return no_of_errors;
}

main.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// main.cpp
#include "LexicalAnalyzer.h"
 
 
int main()
{
    table["pi"]=3.1415926535897932385;
    table["e"]=2.7182818284590452354;
    while (std::cin) {
        get_token();
        if (curr_tok==END) break;
        if (curr_tok==PRINT) continue;
        std::cout<<expr(false)<<'\n';
    }
    return no_of_errors;
}

Анализатор-то работает,но конечное значение не вычисляется.Более того,если вводим
C++
1
a = 3 + 6
,то получаем "a", равное первому элементу в выражении,то есть 3.В чём логическая ошибка данной программы?С этими каскадными вызовами она слегка запутана.Уверен,что кто-то уже делал это задание.

Добавлено через 2 часа 5 минут 30 секунд
Пришлось решать влоб с дебаггером.У Страуструпа опечатка (или намеренная ошибка,что более вероятно ) Вот в этом куске кода в функции get_token():
C++
1
2
        case '*':case'/':case '+':case '-':case '(':case ')':case '=':
             return Token_value(ch);
Нехватает смены значения curr_tok,что и приводит к ошибочной работе.
C++
1
2
        case '*':case'/':case '+':case '-':case '(':case ')':case '=':
             return curr_tok=Token_value(ch);
Теперь всё пашет,всем спасибо,вопрос можно считать закрытым,но есть вопрос поважнее: В функциях prim и term возвращается int при ошибке,но ведь они имеют тип double,как вообще это работает?Происходит неявное преобразование типа,так?Мне интересно,почему Страуструп прибег к такому способу,это распространённая практика?

Добавлено через 16 минут 19 секунд
И ещё опечатка была
C++
1
2
3
                 if (double d = prim (true)) {
                     left /= d;// было left /= prim (true)
                     break;
30
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.06.2009, 20:03
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Пишем свой интерпретатор языка BASIC (C++):

Пишем свой чекер - C++
Я хочу написать свой чекер, но не знаю с чего начать? Кто знает основные принцип работы чекеров прошу объясните.

пишем свой троян с нуля - C++
Всем привет)))соглашусь, что изобретаю велосипед, но хочется сделать все своими ручками не прибегая к open source и т.п. для повышения...

Пишем свой класс, спецификатор доступа protected - C++
Всем привет! Из книги Р. Лафоре относительно спецификатора доступа protected: Далее пишется следующее: Возникает вопросы:...

Не удается откомпилировать интерпретатор М-языка - C++
Задача: взять интерпретатор М-языка на сайте http://cmcmsu.no-ip.info/2course/model.lang.parser.sample.htm и переработать его, добавив в...

Интерпретатор небольшого языка программирования на С++ - C++
Здравствуйте, уважаемые форумчане! Я тут где-то год назад прочитал тему Evg и #pragma о создании интерпретатора, меня эта тема очень...

Написать Интерпретатор Программного Языка(собственного) - C++
Здраствуйте! Кто знает C++ помогите пожалуйста с реализацией данного задания!!! Пожалуйста, очень надо. сроки поджимают. Есть...

464
#pragma
Временно недоступен
954 / 225 / 6
Регистрация: 12.04.2009
Сообщений: 921
17.11.2009, 10:45  [ТС] #241
Цитата Сообщение от Evg Посмотреть сообщение
Какую функцию и что значит "вызвать"
Я просто подумал,что можно разбить интерпретацию файла на фрагменты: 1.проверка синтаксиса 2.собственно запуск. 3.а также общая кнопочка(проверка +запуск). А если функции нужно вызывать по желанию (они же в программе basin) то IDE должна как-то знать о них.Но в принципе это не критично и можно сделать только одну кнопку.

Непонятно мне,как запускать программу из другой программы.Что,есть какая-то функция для этого (стандартная)? system как-то не очень хвалят,а как ещё можно вызвать стороннюю программу?

А сейчас у меня устроено так,что если прописана опция --gui в консоли,то в main всё просто идёт по другой ветке,и запускается конструктор окна,а уже оттуда вызываются функции проверки синтаксиса и интерпретации,которые и передаются в виде указателей экземпляру окна.А сама реализация gui классов лежит в разделяемой библиотеке.

Добавлено через 12 минут
Я подумал: "зачем создавать два приложения,когда можно обойтись одним?" и вариант с опцией командной строки показался мне наиболее простым.Потому и сделал так.
0
Evg
Эксперт CАвтор FAQ
18689 / 6654 / 468
Регистрация: 30.03.2009
Сообщений: 18,619
Записей в блоге: 29
17.11.2009, 12:04 #242
> Я подумал: "зачем создавать два приложения,когда можно обойтись одним?" и вариант с опцией командной строки показался мне наиболее простым.Потому и сделал так.

Можно и одним. Но у людей принято делать так, как я тебе пояснил. Если человеку не нужна IDE, он ставит просто компилятор (интерпретатор). Когда имеется две программы, то компилятор разрабатывает одна команда разработчиков, а IDE - другая, т.е. технически такой вариант удобнее. По большому счёту разбитие большого проекта на несколько отдельных программ - это то же самое, что разбивать одну программу на несколько файлов. Только в качестве интерфейса служит запуск с разными параметрами и обработка текстовой выдачи

> Я просто подумал,что можно разбить интерпретацию файла на фрагменты: 1.проверка синтаксиса 2.собственно запуск. 3.а также общая кнопочка(проверка +запуск). А если функции нужно вызывать по желанию (они же в программе basin) то IDE должна как-то знать о них.Но в принципе это не критично и можно сделать только одну кнопку.

Решается просто. В интерпретатор заводишь опцию типа --syntax-only и при включенной опции после завершения разбора синтаксиса выходишь. В IDE при нажатии на кнопку "Компилирровать, но не запускать" запускаешь интерпретатор с дополнительной опцией --syntax-only. Пункты 2 и 3 для интерпретатора разделить нельзя, это есть только в компиляторах, поскольку на стадии компиляции формируется исполняемый файл, а на стадии запуска он исполняется, а у интерпретатора нет выходного файла. ПОэтому в твоём случае остайтся только два варианта: "Проверить синтаксис" и "Исполнить"

> Непонятно мне,как запускать программу из другой программы.Что,есть какая-то функция для этого (стандартная)? system как-то не очень хвалят,а как ещё можно вызвать стороннюю программу?

Если не забуду, на работе пример покажу готовый. А так ищи в сторону fork, exec - это строго для запуска, pipe, dup2 - это чтобы перезватывать вывод программы

Как вариант ты можешь оставить то, что сделано у тебя сейчас, но это я бы крайне не рекомендовал, т.к. закопаешься довольно глубоко. Либо опять стОит попробовать по тем же причинам: чтобы понять, что так делать не стОит.
1
#pragma
Временно недоступен
954 / 225 / 6
Регистрация: 12.04.2009
Сообщений: 921
17.11.2009, 13:01  [ТС] #243
То есть получается,что идея создания динамической разделяемой библиотеки отпадает за недадобностью.Ведь у нас будет две отдельные программы,и одна запускает другую.В этом варианте библиотека .so (или .dll) не нужна.
0
Evg
Эксперт CАвтор FAQ
18689 / 6654 / 468
Регистрация: 30.03.2009
Сообщений: 18,619
Записей в блоге: 29
17.11.2009, 15:00 #244
Идея динамесечкой библиотеки с точки зрения IDE - отпадает. Но в самом интерпретаторе это сделать можно. Но для порядку надо найти ещё одну графическую библиотеку помимо SDL и уже экспериментировать с двумя собственными динамическими библиотеками, работающие по одному интерфейсу

По поводу запуска программы - я уже выкладывал исходник Трубопровод на линукс
Грубо говоря, можно его запустить как "./a.out ls -l" и в этом случае весь ввод-вывод запускаемой программы (в нашем случае ls) пройдёт через процедуру listener
1
#pragma
Временно недоступен
954 / 225 / 6
Регистрация: 12.04.2009
Сообщений: 921
26.11.2009, 02:21  [ТС] #245
Я вспомнил,что есть класс QProcess,и попробовал сделать с помощью него,(раз уж Qt использую).Наверное,твой пример с pipes намного более транспортабелен между unix-системами?
Вот как я делаю
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    void MainWindow::run()
    {
       console = new QProcess;
    #ifdef _UNIX_
       if (!console->startDetached("/usr/bin/xterm",QStringList()
                                                    << "-e"
                                                    << "./basin"
                                                    << *args
                                                    << filename))
       {
          //Error
       }
    #endif
    #ifdef _WINDOWS_
       // ...
    #endif
    }
Добавлено через 12 минут
Прочитал,что вроде как xterm есть на большинстве unix-систем,но точно не уверен.Ведь xterm может быть в другой папке.Просто немного сложновато в твоём примере,хотя общий смысл я понял,но там есть всякие define-ы специфические,немного усложняет понимание.

Да,я всё таки вернул флаги компиляции в интерпретаторе,это стало возможным благодаря тому,что gui теперь-отдельное приложение.Makefile у меня один,просто теперь он автоматом запускает компиляцию второй программы,заходит в папку,и копирует туда скомпиленный интерпретатор,чтобы лежал рядом с gui программой.
0
Evg
Эксперт CАвтор FAQ
18689 / 6654 / 468
Регистрация: 30.03.2009
Сообщений: 18,619
Записей в блоге: 29
26.11.2009, 10:18 #246
Цитата Сообщение от #pragma Посмотреть сообщение
Я вспомнил,что есть класс QProcess,и попробовал сделать с помощью него,(раз уж Qt использую).Наверное,твой пример с pipes намного более транспортабелен между unix-системами?
Тот пример действительно именно под юникс. Что-то я не подумал про Qt. Вариант с Qt будет работать на всех платформах, где поддерживается Qt. И делать надо именно через QProcess (имею ввиду именно через высокоуровневые средства Qt)

Цитата Сообщение от #pragma Посмотреть сообщение
Прочитал,что вроде как xterm есть на большинстве unix-систем,но точно не уверен.Ведь xterm может быть в другой папке.
Обычно путь до терминала выносят в настройки IDE. Если программа предварительноработает через configure, то по результату работы выставляется дефолтное значение пути до интерпретатора. Если без configure, то дефолтное значение лучше выставить пустым и при первом запуске выдавать кно с настройками, куда пользователь должен ввести параметры, которые нельзя (или нежелательно) вычислить автоматически, при этом одновременно решается проблема, что в unix'е и windows пути в принципе разные. После чего все настройки сохраняются в файл конфигурации и при следующих запусках цепляются оттуда. Примерно так выглядит нормальная user-friendly реализация
1
#pragma
Временно недоступен
954 / 225 / 6
Регистрация: 12.04.2009
Сообщений: 921
27.11.2009, 01:56  [ТС] #247
>Обычно путь до терминала выносят в настройки IDE. Если программа предварительно работает через configure, то по результату работы выставляется дефолтное значение пути до терминала.
Ты про тот configure скрипт,который запускается до сборки проекта? Сделать что-то навроде test -e /usr/bin/xterm?
Ну на на винде,я так понимаю,будет использоваться стандартная переменная %ComSpec% ? Или имелось в виду создание некой отдельной функции configure,или что-то ещё?
0
Evg
Эксперт CАвтор FAQ
18689 / 6654 / 468
Регистрация: 30.03.2009
Сообщений: 18,619
Записей в блоге: 29
27.11.2009, 11:34 #248
Цитата Сообщение от #pragma Посмотреть сообщение
>Обычно путь до терминала выносят в настройки IDE. Если программа предварительно работает через configure, то по результату работы выставляется дефолтное значение пути до терминала.
Ты про тот configure скрипт,который запускается до сборки проекта? Сделать что-то навроде test -e /usr/bin/xterm?
Я имел в виду, как делают люди. У людей обчно сначала запускается configure, а потом make. Имел в виду именно этот configure.

Цитата Сообщение от #pragma Посмотреть сообщение
Ну на на винде,я так понимаю,будет использоваться стандартная переменная %ComSpec% ? Или имелось в виду создание некой отдельной функции configure,или что-то ещё?
Да в общем неважно как настроить дефолтное значение. Важно лишь то, чтобы пользователь имел возможность это настроить. А так же при первом запуске знал, что есть такая вещь, которую надо настроить. Чтобы не было такого, что он надимает кнопку "Run", а в ответ тишина или сообщение об ошибке, которое без поллитры не разберёшь
1
#pragma
Временно недоступен
954 / 225 / 6
Регистрация: 12.04.2009
Сообщений: 921
28.11.2009, 02:34  [ТС] #249
Я сейчас читаю доку по autoconf,пока нашёл это http://www.gnu.org/software/libtool/...neric-Programs и это http://www.gnu.org/software/libtool/...cular-Programs. Мне нужен какой-то макрос,навроде AC_PROG_XTERM,но его там нет,и веть нужно ещё,чтобы в зависимости от проверки на существование писался define в config.h или в похожий файл.
Т.е. например,так
C++
1
#define PATH_TO_XTERM "/usr/bin/xterm"
А как это сделать?
Я помню,ты писал,что не работал с autotools,так что это,скорее вопрос риторический.Придётся наверное отдать всё во власть пользователя и как-то создавать .ini или что-то в этом духе.
0
Evg
Эксперт CАвтор FAQ
18689 / 6654 / 468
Регистрация: 30.03.2009
Сообщений: 18,619
Записей в блоге: 29
28.11.2009, 10:56 #250
Ну до реальных пользователей пока далеко, так что с autoconf'ом точно можно не спешить и отложить на потому. Потому как в процессе отладки ты все настройки сам можешь сделать.

Просто "пользователь" в данном случае можно рассматривать в двух контекстах:
- тот, кто программой будет пользоваться. Все возможные фичи в интерфейсе (опции командной строки в интерпретаторе и опции в gui и всевозможные кнопочки) надо закладывать сразу и всегда об этом помнить
- тот, кто программу будет собирать из исходников. Грубо говоря, в этом случае все настройки технически решаются через файл config.h. Как вариант ты его создаёшь руками и тестируешь в разной комбинации опций конфигурации системы, а уже под конец пишешь configure, который в автоматическом режиме создаст файл config.h

Получается так, что по второму пункту проблема локализована, и технически решается в узком месте, где вообще не нужно затрагивать исходники программы. А первая проблема - это то, что по большому счёту сильно влияет на работу всего комплекса и удобство пользования. И в сторонке не всегда это получается сделать, поэтому надо как можно раньше в процессе программирования/проектирования закладываться на эти свойства
1
#pragma
Временно недоступен
954 / 225 / 6
Регистрация: 12.04.2009
Сообщений: 921
30.11.2009, 08:06  [ТС] #251
Подглядел,как делают define-ы с помощью configure: написал в configure.in
configure.in
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
AC_CONFIG_HEADERS(Basin-IDE/config.h:Basin-IDE/config.h.in)
 
AC_MSG_CHECKING([for /usr/bin/xterm and define PATH_TO_XTERM])
if ( test -e /usr/bin/xterm ); then 
cat >>./Basin-IDE/config.h.in <<_ACEOF
#ifndef PATH_TO_XTERM
#define PATH_TO_XTERM "/usr/bin/xterm"
#endif
_ACEOF
AC_MSG_RESULT([defined])
else
AC_MSG_FAILURE(
  [/usr/bin/xterm program not found.Please view configure.in file,\
string number 39-42 to fix the problem.])
fi

Там я временно сделал вариант с ошибкой,так как не знаю,где лежит xterm на других системах по умолчанию. А программу всё-таки вызываю непосредственно,так чтобы она была под контролем IDE,а не внешнего терминала.Поэтому,скорее всего,придётся делать окошко для варианта успешного вывода (печать результатов программы),например по некому сигналу открывается окошко с текстовым полем.Меня только смущает то,что IDE по сути,толжна быть только обёрткой для программы,а тут получится вмешательство в стандартный вывод.Обычно же IDE вызывает внешнюю программу (cmd или xterm).
Вызываю интерпретатор так:
mainwindow.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* -------------------------------------------------------------------------- */
  void MainWindow::readErr()
  {
     arr = new QByteArray;
     *arr = console->readAllStandardError();
     errorsList ->insertPlainText( arr->data() );
  }
/* -------------------------------------------------------------------------- */
  void MainWindow::run()
  {
    console = new QProcess;
    connect(console, SIGNAL(finished(int,QProcess::ExitStatus)),
                                                         this, SLOT(readErr()));
    console->setReadChannel (QProcess::StandardError);
  #ifdef _UNIX_
    console->start("./basin",QStringList() << *args << filename);
  #endif
  #ifdef _WINDOWS_
    // ...
  #endif
  }

И в errorsList печатаются сообщения красным цветом.
0
Evg
Эксперт CАвтор FAQ
18689 / 6654 / 468
Регистрация: 30.03.2009
Сообщений: 18,619
Записей в блоге: 29
30.11.2009, 08:43 #252
Цитата Сообщение от #pragma Посмотреть сообщение
А программу всё-таки вызываю непосредственно,так чтобы она была под контролем IDE
А для чего? Вообще это очень плохой метод работы. С IDE и без IDE программа должна работать эквивалентно. Если работал на виндовых IDE, то во всех случаях консольной программа запускается в отдельно консоли. Понятно, что в случае юниксов это требование менее жёсткое, т.к. в отличие от виндов имеется множество разных реализаций терминалов, а в твоём случае попросту нужно сделать свою реализацию терминала (или эмулятор терминала), встроенную в IDE. Только вот не пойму, что тебе это даст
1
#pragma
Временно недоступен
954 / 225 / 6
Регистрация: 12.04.2009
Сообщений: 921
30.11.2009, 10:19  [ТС] #253
Просто я не представляю,как потом считать данные из потоков ошибок и вывода,ведь если я буду запускать консоль как дочерний процесс IDE,то считываться будут только данные,которые пишет этот процесс,а не запускаемый в консоли? Или в Unix-системах не существует разграничений для процессов,и все данные идут в один общий поток? Вот это мне не понятно. Постараюсь уточнить свой вопрос: допустим,есть файл - поток вывода stdout,запускается программа-терминал,у неё есть свой вывод (свои ошибки или ещё что-то),а программа,запускаемая внутри терминала имеет свой вывод(в данном случае это интерпретатор,и выводится результат программы на QBASIC). Пишутся ли все данные в один поток вывода? С этим и было связано моё затруднение,ведь если я создаю процесс для консоли,и передаю ей в качестве параметра имя программы,то как потом считать вывод этой программы?
0
Evg
Эксперт CАвтор FAQ
18689 / 6654 / 468
Регистрация: 30.03.2009
Сообщений: 18,619
Записей в блоге: 29
30.11.2009, 10:34 #254
Цитата Сообщение от #pragma Посмотреть сообщение
Просто я не представляю,как потом считать данные из потоков ошибок и вывода,ведь если я буду запускать консоль как дочерний процесс IDE,то считываться будут только данные,которые пишет этот процесс,а не запускаемый в консоли?
Всё, понял. Надо подумать. Если просто в терминале запустить процесс, а из него ещё один процесс, то извне они будут пользоваться одним и тем же stdout'ом, т.к. shell'ы при порождении нового процесса настраивают файловые дескрипторы таким образом, что они ссылаются на одни и те же потоки (по сути делается dup2, как в том примере про трубопровод). Правда я никогда не пытался запустить терминал, и уже перехватывать его (терминала) ввод-вывод. По логике вещей здесь уже ситуация другая. Тут надо знающих людей поспрашивать
1
Evg
Эксперт CАвтор FAQ
18689 / 6654 / 468
Регистрация: 30.03.2009
Сообщений: 18,619
Записей в блоге: 29
30.11.2009, 17:34 #255
В общем, знатоки утверждают, что при запуске черз нормальный терминал подобная операция перехвата ввода-вывода будет слишком геморройной. Не говоря уж о том, что кроссплатформенно сделать в принципе не получится, а потому их предложение так же сводилось к тому, что проще будет использовать самодельную эмуляцию терминала. Причём говорили, что в Qt вроде бы есть какая-то стандартная компонентя для консоли

Цитата Сообщение от #pragma Посмотреть сообщение
а тут получится вмешательство в стандартный вывод
Должно быть не вмешательство, а перехват ввывода. Т.е. интепретатор делает printf, а IDE должна перехватить то, что выдается в стандартный вывод и нарисовать это на своём терминале. В случае отладчика тебе надо будет ещё и ввод подсовывать (хотя ввод и для INPUT'а нужен) - его так же придётся моделировать в самодельном метрминале
1
30.11.2009, 17:34
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
30.11.2009, 17:34
Привет! Вот еще темы с ответами:

Написать интерпретатор программного языка -помощь - C++
Здраствуйте! Ребят, кто хорошо разбирается в C++ помогите пожалуйста с реализацией данного задания или хотя бы подтолкните к решению,...

Интерпретатор/компилятор ассемблер-подобного языка - C++
Привет! Чую, что изобрёл велисипед, даже скорее велопарк, но всё же, поделюсь: Некоторое время назад начал изучать кресты, в целом...

Интерпретатор музыки стандарта BASIC PLAY на С++ - C++
У кого нибудь есть функция или класс, который сможет воспроизводить в С++ напрямую музыкальные строки, записанные в стандарте оператора...

Задание: разработать "Интерпретатор языка". С чего начать? - C++
Здравствуйте, вручили темку на курсовик, ну точнее как вручили, не успел взять то, что хотел - пришлось брать то, что осталось. Плоховато...


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

Или воспользуйтесь поиском по форуму:
255
Закрытая тема Создать тему
Опции темы

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