Признавая новую линию - PullRequest
       20

Признавая новую линию

0 голосов
/ 30 июня 2009

У меня есть довольно сложный калькулятор, который печатает вывод, когда пользователь вводит ";" (и нажимает клавишу ввода.) Теперь я пытаюсь разрешить пользователю печатать вывод при нажатии клавиши ввода (без использования точки с запятой.) Мне нужно знать, как я могу это реализовать.

Примечание: калькулятор использует токенизацию для чтения ввода пользователя

Это часть источника калькулятора, и единственная часть, которую необходимо изменить. Это функция-член Token_stream, которая вызывается, когда различные другие функции калькулятора вызывают для получения следующего токена.

const char let = '#';
const char quit = 'Q';
const char print = ';';
const char number = '8';
const char name = 'a';
const char sq_rt = '@';
const char power = '^';
const char constant = '~';

Token Token_stream::get()
{
    if (full) { full=false; return buffer; }
    char ch;
    cin >> ch;
    switch (ch) {
    case '(':
    case ')':
    case '+':
    case '-':
    case '*':
    case '/':
    case '%':
    case ';':
    case '=':
    case ',':
    case constant:
    case power:
    case sq_rt:
    case let:
    case quit:
    case name:
        return Token(ch);   // let each character represent itself
    case '.':
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
    {   cin.unget();       // equivalent of putback
        double val;
        cin >> val;
        return Token(number,val);
    }
    default:
        if (isalpha(ch)) {       // in order to create variable names
            string s;
            s += ch;
            while(cin.get(ch) && (isalpha(ch) || isdigit(ch) || ch == '_')) s += ch;
            cin.unget();
            if (s == "const") return Token(constant);
            if (s == "quit") return Token(quit);
            if (s == "pow") return Token(power);
            if (s == "sqrt") return Token(sq_rt);
            if (s == "let") return Token(let);  
            if (s == "name") return Token(name);
            return Token(name,s);
             }
       else if (isspace(ch)) {    // my attempt at allowing enter to produce output
            string s;
            cin.get(ch);
            s += ch;
            if(s == "\n") return Token(print);
            }

            }
        error("Bad token");
    }

Пока пользователь вводит 5 * 5 и нажимает пробел, то ввод ... ничего не происходит. Однако, если они нажимают пробел, затем вводят случайный символ (любой символ, не только;), затем нажимают ввод, он выводит ответ. После этого пользователь может использовать ввод для создания выходных данных, но он сохраняет дополнительный токен, который вводит пользователь после попадания в пробел, поэтому порядок операций становится совершенно неясным.

Короче говоря, мне нужно знать, как разрешить пользователю сначала нажимать пробел, а затем вводить (или даже просто вводить, но пока работать с пробелом и вводить) для вывода - без каких-либо дополнительных символов.

Если вы хотите увидеть больше источников или у вас есть вопросы относительно самого калькулятора, чтобы решить проблему, я с удовольствием выложу больше.

P.S. Оригинальная программа из книги, из которой я изучаю C ++. Я только что делал упражнения, которые меняют его и добавляют к нему новые функции.

Ответы [ 3 ]

2 голосов
/ 30 июня 2009

Сначала я прочитал бы строку в строку и передал бы ее вашему классу 'Token'.

Что-то вроде:

#include <iostream>
#include <string>

...

{
    std::string in;
    getline( std::cin, in );
    Token t( in );
    // Do whatever you need to with 't'
    std::cout << in << " = " << t.Result() << std::endl;
}
0 голосов
/ 30 июня 2009

Еще одна идея для расширения вышеупомянутых решений:

В случае, если одна строка не содержит всей информации, т. Е. Если необходимо «пробелить» ввод по нескольким строкам, задайте стандартный символ (ы) разделения. Например, два символа новой строки (два нажатия клавиши подряд) будут отмечать конец потока.

Затем просто прочитайте все это в один буфер (как предложено в ответах ранее) и проанализируйте этот буфер.

Конец строки в Windows обычно или в шестнадцатеричной 0X0D 0X0A последовательности.

0 голосов
/ 30 июня 2009

Расширение на «кухню»

Предполагается, что вы создаете свой класс потока токенов следующим образом:

int main()
{
     Token_stream    stream(std::cin);

     // Do Stuff.
};

Вы также можете изменить это:

int main()
{
    MyApplicationState   stateInfo;
    std::string          line;

    while(std::getline(std::cin,line))
    {
        std::stringstream s(line);
        Token_stream      stream(stateInfo,s);

        // Do stuff
    }
}

Теперь каждая строка - это собственный поток.
Это предполагает, что каждая строка содержит всю информацию, необходимую для выражения, и что вы можете хранить информацию о состоянии в объекте MyApplicationState.

...