0

ユーザーが「;」を入力すると出力を出力するかなり複雑な電卓があります。(そして入力を押します。) 私が今やろうとしているのは、ユーザーが入力を押したときに (セミコロンを使用せずに) 出力を印刷できるようにすることです。これを実装する方法を知る必要があります。

補足: 電卓はトークン化を使用してユーザー入力を読み取ります

これは電卓のソースの一部であり、変更が必要な唯一の部分です。これは、電卓の他のさまざまな関数が次のトークンを取得するために呼び出すときに呼び出される 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 を入力してスペースを押しても何も起こりません。ただし、スペースを押してからランダムな文字 (; だけでなく任意の文字) を入力してから Enter キーを押すと、答えが出力されます。この後、ユーザーは enter を使用して出力を生成できますが、スペースを押した後にユーザーが入力した余分なトークンが保存されるため、操作の順序がすべて厄介になります。

要するに、ユーザーが最初にスペースを押してから入力できるようにする方法を知る必要があります (または単に入力しますが、今のところはスペースを入力して入力します)。追加の文字なしで出力を生成します。

問題を解決するために、より多くのソースを表示したり、電卓自体に関する質問がある場合は、喜んで投稿します。

PS 元のプログラムは、私が C++ を学んでいる本からのものです。私はそれを変更して機能を追加する演習を行ってきました。

4

3 に答える 3

2

最初に行を文字列に読み取り、それを「トークン」クラスに渡します。

何かのようなもの:

#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;
}
于 2009-06-29T21:06:47.347 に答える
0

「キッチン」の拡大

次のようなトークン ストリーム クラスを作成するとします。

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 に格納できることを前提としています。

于 2009-06-29T21:19:17.057 に答える
0

上記のソリューションを拡張する別のアイデア:

1 行にすべての情報が含まれていない場合、つまり複数行にわたって入力を「スペース」する必要がある場合は、標準の区切り文字を設定します。たとえば、2 つの改行 (Enter キーを 2 回続けて押す) は、ストリームの終わりを示します。

次に、全体を1つのバッファに読み込み(前の回答で提案されているように)、そのバッファを解析します。

Windows の行末は、通常、または 16 進0X0D 0X0Aシーケンスです。

于 2009-06-29T21:36:29.580 に答える