C++ c++;计算器程序-寻找阶乘

C++ c++;计算器程序-寻找阶乘,c++,calculator,factorial,C++,Calculator,Factorial,我找不到哪里出错了。计算器工作正常,但当我想找到给定数字的阶乘(“!”用作运算符)时,我会得到奇怪的答案,如“1”和“59”。有人能找到我哪里出了差错并帮我吗?另外,很抱歉我要上传的代码太长了 #include "Header.h" class Token { public: char kind; // what kind of token double value; // for numbers: a value Token(char ch) // make a

我找不到哪里出错了。计算器工作正常,但当我想找到给定数字的阶乘(“!”用作运算符)时,我会得到奇怪的答案,如“1”和“59”。有人能找到我哪里出了差错并帮我吗?另外,很抱歉我要上传的代码太长了

#include "Header.h"

class Token {
public:
char kind;        // what kind of token
double value;     // for numbers: a value 
Token(char ch)    // make a Token from a char
    :kind(ch), value(0) { }    
Token(char ch, double val)     // make a Token from a char and a double
    :kind(ch), value(val) { }
};


class Token_stream {
public: 
Token_stream();   // make a Token_stream that reads from cin
Token get();      // get a Token (get() is defined elsewhere)
void putback(Token t);    // put a Token back
private:      
bool full;  
Token buffer;     // here is where we keep a Token put back using putback()
};


// The constructor just sets full to indicate that the buffer is empty:
Token_stream::Token_stream()
:full(false), buffer(0)    // no Token in buffer
{
}


// The putback() member function puts its argument back into the Token_stream's buffer:
void Token_stream::putback(Token t)
{
if (full) error("putback() into a full buffer");
buffer = t;       // copy t to buffer
full = true;      // buffer is now full
}


Token Token_stream::get()
{
if (full) {       // do we already have a Token ready?
    // remove token from buffer
    full=false;
    return buffer;
} 

char ch;
cin >> ch;    // note that >> skips whitespace (space, newline, tab, etc.)

switch (ch) {
case ';':    // for "print"
case 'q':    // for "quit"
case '(': case ')': case '+': case '-': case '*': case '/': case '{': case '}': case         '!':
    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.putback(ch);         // put digit back into the input stream
        double val;
        cin >> val;              // read a floating-point number
        return Token('8',val);   // let '8' represent "a number"
    }
default:
    error("Bad token");
}
}


Token_stream ts;        // provides get() and putback() 



double expression();  // declaration so that primary() can call expression()


int factorial (int x)
{
int left = 1;
    for (int a = 1; a<=x;++a){
        left =a*left;
    }
        return left;
}

// deal with numbers and parentheses
double primary()
{
Token t = ts.get();
switch (t.kind) {
case '(':    // handle '(' expression ')'
    {    
        double d = expression();
        t = ts.get();
        if (t.kind != ')') error("')' expected)");
        return d;
    }
case '{':
    {
        double d = expression();
        t = ts.get();
        if (t.kind != '}') error ("'}' expected)");
        return d;
    }

case '8':
    return t.value;
default:
    return t.kind;
    error("primary expected");
}
}


// deal with *, /, and %
double term()
{
double left = primary();
Token t = ts.get();        // get the next token from token stream

while(true) {
    switch (t.kind) {
    case '*':
        left *= primary();
        t = ts.get();
        break;
    case '/':
        {    
            double d = primary();
            if (d == 0) error("divide by zero");
            left /= d; 
            t = ts.get();
            break;
        }
    case '!': 
        {
    Token t = ts.get();
    int d = factorial(t.value);
    return d;
        }

    default: 
        ts.putback(t);     // put t back into the token stream
        return left;
}
}
}


// deal with + and -
double expression()
{
double left = term();      // read and evaluate a Term
Token t = ts.get();        // get the next token from token stream

while(true) {    
    switch(t.kind) {
    case '+':
        left += term();    // evaluate Term and add
        t = ts.get();
        break;
    case '-':
        left -= term();    // evaluate Term and subtract
        t = ts.get();
        break;
    default: 
        ts.putback(t);     // put t back into the token stream
        return left;       // finally: no more + or -: return the answer
    }
}
}




int main()
try
{
while (cin) {
    double val = expression();
    Token t = ts.get();

    switch(t.kind){
case 'q': cout<<"end of programme";
    break;
case ';':        // ';' for "print now"
        cout << "=" << val << '\n';
        break;
default:
        ts.putback(t);
    val = expression();
    }
}
keep_window_open();
}
catch (exception& e) {
cerr << "error: " << e.what() << '\n'; 
keep_window_open();
return 1;
}
catch (...) {
cerr << "Oops: unknown exception!\n"; 
keep_window_open();
return 2;
}
#包括“Header.h”
类令牌{
公众:
char-kind;//什么类型的令牌
double value;//对于数字:一个值
Token(char ch)//从字符生成一个令牌
:种类(ch),值(0){}
Token(char ch,double val)//从char和double生成一个令牌
:种类(ch),值(val){}
};
类令牌流{
公众:
Token_stream();//生成一个从cin读取的Token_流
令牌get();//获取令牌(get()在别处定义)
void putback(令牌t);//将令牌放回
私人:
bool-full;
令牌缓冲区;//这里是使用putback()将令牌放回的地方
};
//构造函数只是设置full以指示缓冲区为空:
令牌流::令牌流()
:full(false),buffer(0)//缓冲区中没有令牌
{
}
//putback()成员函数将其参数放回令牌流的缓冲区:
无效令牌流::回存(令牌t)
{
if(full)错误(“将()放回完整缓冲区”);
buffer=t;//将t复制到缓冲区
full=true;//缓冲区现在已满
}
令牌流::get()
{
如果(已满){//我们是否已准备好令牌?
//从缓冲区中删除令牌
满=假;
返回缓冲区;
} 
char ch;
cin>>ch;//注意>>跳过空白(空格、换行符、制表符等)
开关(ch){
大小写“;”://用于“打印”
案例'q'://用于“退出”
案例“(”:案例“)”:案例“+”:案例“-”:案例“*”:案例“/”:案例“{”:案例“}”:案例“!”:
返回标记(ch);//让每个字符表示它自己
案例“”:
案例“0”:案例“1”:案例“2”:案例“3”:案例“4”:
案例“5”:案例“6”:案例“7”:案例“8”:案例“9”:
{    
cin.putback(ch);//将数字放回输入流
双val;
cin>>val;//读取浮点数
返回标记('8',val);//让'8'表示“一个数字”
}
违约:
错误(“坏令牌”);
}
}
令牌流ts;//提供get()和putback()
双表达式();//声明,以便primary()可以调用表达式()
整数阶乘(整数x)
{
int左=1;
对于(inta=1;a
intfactorial(intx)
来说,从算法上讲是很好的


但是,任何大于
12!
的整数如果是32位有符号的,都会溢出。使用
uint64\u t
将提供更多的数字(最多为
19!
),但您应该提前检查
x
的值。

更有可能,由于整数溢出,您会得到奇怪的结果。任何大于或等于
13!
的值都将溢出32位
int

您溢出了32位int的最大大小。请尝试此

 std::cout << std::numeric_limits<int>::max(); 

std::cout打印的内容会产生不可知的结果。

手动调用阶乘函数时,是否尝试了正确的值?是否尝试了在输入阶乘函数时使用正确的值调用阶乘函数?是否可以删除代码中不相关的部分?您已经尝试了哪些方法来解决此问题?什么方法有效d什么不起作用?你知道你的解决方案为什么不起作用吗?你应该花更多的时间在格式化上,这样所有的代码都能正确缩进,我还建议去掉背对背的空行。可读的代码更有可能得到积极的回应。你到底在为你的阶乘计算输入什么?阶乘增长非常快,32位带符号的
int
不会有太大的容量。对于大于8的数字,无论如何都不需要进行阶乘运算。但是,当我输入!8时,我得到了错误的答案。我自己尝试了这个函数,它工作得很好。核心部分是:case'!':{Token t=ts.get();int d=factorial(t.value);返回d;}和int factorial(int x){int left=1;for(int a=1;a
#incldue <limits>