认识新线

发布于 2024-07-26 12:51:35 字数 2348 浏览 5 评论 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 来产生输出,但它会保存用户在输入空格后输入的额外标记,因此操作顺序变得很混乱。

简而言之,我需要知道如何允许用户最初按空格然后输入(或者甚至只是输入,但现在使用空格并输入)来生成输出 - 无需任何其他字符。

如果您想查看更多来源或对计算器本身有任何疑问以解决问题,我很乐意发布更多内容。

PS 原始程序来自我正在学习 C++ 的一本书。 我刚刚做了一些练习来改变它并为其添加功能。

I've got a fairly complex calculator that prints output when the user inputs ";" (and hits enter.) What I'm trying to do now is allow the user to print output when they hit enter, (without use of semicolon.) I need to know how I can implement this.

Side note: The calculator uses tokenization to read user input

This is part of the calculator's source, and the only part that needs to be changed. It is a member function of Token_stream that is called when various other functions of the calculator call to get the next token.

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");
    }

So far if the user enters 5*5 and hits space then enter..nothing happens. However if they hit space, then enter a random character (any character, not just ;) then hit enter, it ouputs the answer. After this, the user can use enter to produce output, but it saves the extra token that the user input after they hit space, so the order of operations gets all screwy.

In short, I need to know how to allow the user initially to hit space then enter (or even just enter, but working with space and enter for now) to produce output - without any additional characters.

If you'd like to see more source or have any questions regarding the calculator itself in order to solve the problem I'd be happy to post more.

P.S. The original program is from a book I'm learning C++ from. I've just been doing exercises that change it and add features to it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

陈年往事 2024-08-02 12:51:36

我会首先将该行读入字符串,然后将其传递给您的“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;
}

I would read the line into a string first, and pass that to your 'Token' class.

Something like:

#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;
}
怪异←思 2024-08-02 12:51:36

扩展“厨房”

假设您像这样创建令牌流类:

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 中。

Exapnding on 'kitchen'

Assuming you create your token stream class like this:

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

     // Do Stuff.
};

You could change this too:

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

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

        // Do stuff
    }
}

Now each line is its own stream.
This assumes that each line contains all the information required for an expression and that you can store state information in an object MyApplicationState.

拔了角的鹿 2024-08-02 12:51:36

扩展上述解决方案的另一个想法是:

在一行不包含所有信息的情况下,即如果需要在多行上“间隔”输入,请设置标准分隔字符。
例如,两个换行符(连续按两次回车键)将标记流的结尾。

然后将整个内容读入一个缓冲区(就像之前答案中建议的那样)并解析该缓冲区。

Windows 上的行尾通常是 或 ,采用十六进制 0X0D 0X0A 序列。

Another idea to expand on the above stated solutions:

In the case that one line does not contain all the information, i.e if there is a need to 'space' the input over multiple line set a standard delimitation character(s).
For example two newlines (two enter presses in a row) would mark the end of the stream.

Then just read the whole thing into one buffer (like suggested in answers before) and parse that buffer.

An end of line on Windows is usually or in hex 0X0D 0X0A sequence.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文