简单计算器-难以解析部分数字和负数 [英] Simple Calculator--trouble parsing for partial and negative numbers

查看:87
本文介绍了简单计算器-难以解析部分数字和负数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用有限的C ++知识来制作一个遵循基本数学运算符优先级规则并可以处理大型方程式的计算器.我有它适用于+,-,*,/和e(指数),但是我还没有找到解析部分数字(使用."分隔的数字)和负数(区分负数)的方法.减去).可以按照我尝试的方式完成吗?还有其他可以更好地完成工作的结构吗? (请记住,我是一个初学者).请仅提供有用的评论.提前谢谢.

更新:更改了removeSpace函数,作为pregoldriff的建议.

<pre>#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
#include <cctype>
#include <math.h>

using namespace std;

string removeSpace(string eq);
void colate(string eq);
double calculate(vector<string> &stor, double ttl);

int main(int argc, char *argv[])
{
    while(true)
    {
    string e = "";       
    cout << "enter equation: ";
    getline(cin, e);     
    e = removeSpace(e);           
    colate(e);    
    }
      
    system("PAUSE");
    return EXIT_SUCCESS;   
}


string removeSpace(string eq)  //removes spaces from string
{
   int i = -1;
   int j = 0;
   
      while (i != eq.length())
        {
        i++;
        if (!isspace(eq[i]))
            {
            eq[j] = eq[i];
            j++;       
            }
        }
     
   eq.resize(j);
   return eq;
}


void colate(string eq)   //stores the operators and numbers in a string vector, in order
{
    double opPos = 0;
    double numPos = 0;
    vector<string> storage;
    string storeStr;
    int i = 0;
    
    while(eq.length() >= 1)
    {  
       numPos = eq.find_first_of("1234567890");                
       opPos = eq.find_first_of("*/+-se");
       
       if (numPos < opPos)
       {
          storeStr = eq.substr(numPos, opPos-numPos);
          storage.push_back(storeStr);
          eq.erase(numPos, opPos-numPos);      
       }  
          
       if (numPos > opPos)
       {
          storeStr = eq.substr(opPos, numPos-opPos);
          storage.push_back(storeStr);
          eq.erase(opPos, numPos-opPos);      
       }             
    i++;  
    }
       
    double total =0;
    total = calculate(storage, total);  //passes the string vector to calculate function
    cout << "Total: " << total << endl; 
}
  

double calculate(vector<string> &stor, double ttl)  //finds the total of the equation
{
       double Total = ttl;      
       double num1 = 0;   
       double num2 = 0;
       int Pos = 0;      //holds the position of the current operator
       string temp = ""; 
       
       vector<string>::iterator x; 
       
       vector<string> ex;  //highest operator priority vector
       ex.push_back("e");
       
       vector<string> prim;  //next highest operator priority vector
       prim.push_back("*");
       prim.push_back("/");
       
       vector<string> sec;   //lowest operator priority vector
       sec.push_back("+");
       sec.push_back("-");
        
       while (true)
       {
          //below if-else statements set the position integer according to operator precedence         
          x = find_first_of(stor.begin(), stor.end(), ex.begin(), ex.end());
          
             if (x!=stor.end())
             {
                 Pos = find_first_of(stor.begin(), stor.end(), ex.begin(), ex.end()) - stor.begin();
             }
             else
             {
                 x = find_first_of(stor.begin(), stor.end(), prim.begin(), prim.end());
                 
                 if(x!=stor.end())
                 {   
                     Pos = find_first_of(stor.begin(), stor.end(), prim.begin(), prim.end()) - stor.begin();
                 }
                 else
                 {
                     Pos = find_first_of(stor.begin(), stor.end(), sec.begin(), sec.end()) - stor.begin();
                 }    
             }
          
          //convert the strings to the left and right of the operator to double           
          num1 = atof(stor.at(Pos-1).c_str());       
          num2 = atof(stor.at(Pos+1).c_str());
             
             //perform math based on the operator found 
             if(stor.at(Pos) == "*")
             {Total = num1 * num2;}
             if(stor.at(Pos) == "/")
             {Total = num1 / num2;}
             if(stor.at(Pos) == "+")
             {Total = num1 + num2;}
             if(stor.at(Pos) == "-")
             {Total = num1 - num2;}
             if(stor.at(Pos) == "e")
             {Total = pow(num1, num2);}
             if(stor.at(Pos) == "f")
             {Total = fmod(num1, num2);}
          
          //erases the three vector spaces occupied by the two numbers and the 
          //operator and replaces them with the new number (the total)
          stor.erase(stor.begin()+Pos-1, stor.begin()+Pos+2);
             {std::ostringstream ss;
             ss << Total;
             temp = ss.str();}
          stor.insert(stor.begin()+Pos-1, temp);
          
          //returns the total of the string if the string contains the answer
             if(stor.end()-stor.begin() <=1)
             {
                 return Total;
             }          
       }
}



解决方案

您需要考虑自己在做些什么:

while (i != eq.length())
{
    i++;
    if (isspace(eq[i]))
    {continue;}

    else
    eq[j] = eq[i];
    j++;
}

首先,您不需要else:如果条件评估为true,则它将执行continue,因此不需要else.其次,即使您在if之后继续操作,缩进也暗示else代码将同时是

eq[j] = eq[i];


j++;

行-事实并非如此.第三,保持一致:始终将代码缩进适当的级别,这使得阅读起来更容易:

if (isspace(eq[i]))
{continue;}

不是特别可读吗? :laugh:

尤其是在开始时,请始终对条件执行块使用{...}:即使它们是单个statemnet,当您添加应作为条件的一部分执行的代码时,它也很明显并可以防止以后出现问题.

while (i != eq.length())
{
    i++;
    if (isspace(eq[i]))
    {
        continue;
    }
    else
    {
        eq[j] = eq[i];
        j++;
    }
}

我实际上将更简单地重写它:

while (i != eq.length())
   {
   i++;
   if (!isSpace(eq[i]))
       {
       eq[j] = eq[i];
       j++;
       }
   }

请注意,我将您的函数的名称更改为与其他函数匹配!

我知道这并不能解决您的问题,但是请尝试通过您的代码来体现这一点-它会使代码更具可读性,这只会有所帮助!您可能会对源代码有所了解.
例如:
字符串解析器和评估器 [
Update: changed the removeSpace function as pre oldgriff''s advice.

<pre>#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
#include <cctype>
#include <math.h>

using namespace std;

string removeSpace(string eq);
void colate(string eq);
double calculate(vector<string> &stor, double ttl);

int main(int argc, char *argv[])
{
    while(true)
    {
    string e = "";       
    cout << "enter equation: ";
    getline(cin, e);     
    e = removeSpace(e);           
    colate(e);    
    }
      
    system("PAUSE");
    return EXIT_SUCCESS;   
}


string removeSpace(string eq)  //removes spaces from string
{
   int i = -1;
   int j = 0;
   
      while (i != eq.length())
        {
        i++;
        if (!isspace(eq[i]))
            {
            eq[j] = eq[i];
            j++;       
            }
        }
     
   eq.resize(j);
   return eq;
}


void colate(string eq)   //stores the operators and numbers in a string vector, in order
{
    double opPos = 0;
    double numPos = 0;
    vector<string> storage;
    string storeStr;
    int i = 0;
    
    while(eq.length() >= 1)
    {  
       numPos = eq.find_first_of("1234567890");                
       opPos = eq.find_first_of("*/+-se");
       
       if (numPos < opPos)
       {
          storeStr = eq.substr(numPos, opPos-numPos);
          storage.push_back(storeStr);
          eq.erase(numPos, opPos-numPos);      
       }  
          
       if (numPos > opPos)
       {
          storeStr = eq.substr(opPos, numPos-opPos);
          storage.push_back(storeStr);
          eq.erase(opPos, numPos-opPos);      
       }             
    i++;  
    }
       
    double total =0;
    total = calculate(storage, total);  //passes the string vector to calculate function
    cout << "Total: " << total << endl; 
}
  

double calculate(vector<string> &stor, double ttl)  //finds the total of the equation
{
       double Total = ttl;      
       double num1 = 0;   
       double num2 = 0;
       int Pos = 0;      //holds the position of the current operator
       string temp = ""; 
       
       vector<string>::iterator x; 
       
       vector<string> ex;  //highest operator priority vector
       ex.push_back("e");
       
       vector<string> prim;  //next highest operator priority vector
       prim.push_back("*");
       prim.push_back("/");
       
       vector<string> sec;   //lowest operator priority vector
       sec.push_back("+");
       sec.push_back("-");
        
       while (true)
       {
          //below if-else statements set the position integer according to operator precedence         
          x = find_first_of(stor.begin(), stor.end(), ex.begin(), ex.end());
          
             if (x!=stor.end())
             {
                 Pos = find_first_of(stor.begin(), stor.end(), ex.begin(), ex.end()) - stor.begin();
             }
             else
             {
                 x = find_first_of(stor.begin(), stor.end(), prim.begin(), prim.end());
                 
                 if(x!=stor.end())
                 {   
                     Pos = find_first_of(stor.begin(), stor.end(), prim.begin(), prim.end()) - stor.begin();
                 }
                 else
                 {
                     Pos = find_first_of(stor.begin(), stor.end(), sec.begin(), sec.end()) - stor.begin();
                 }    
             }
          
          //convert the strings to the left and right of the operator to double           
          num1 = atof(stor.at(Pos-1).c_str());       
          num2 = atof(stor.at(Pos+1).c_str());
             
             //perform math based on the operator found 
             if(stor.at(Pos) == "*")
             {Total = num1 * num2;}
             if(stor.at(Pos) == "/")
             {Total = num1 / num2;}
             if(stor.at(Pos) == "+")
             {Total = num1 + num2;}
             if(stor.at(Pos) == "-")
             {Total = num1 - num2;}
             if(stor.at(Pos) == "e")
             {Total = pow(num1, num2);}
             if(stor.at(Pos) == "f")
             {Total = fmod(num1, num2);}
          
          //erases the three vector spaces occupied by the two numbers and the 
          //operator and replaces them with the new number (the total)
          stor.erase(stor.begin()+Pos-1, stor.begin()+Pos+2);
             {std::ostringstream ss;
             ss << Total;
             temp = ss.str();}
          stor.insert(stor.begin()+Pos-1, temp);
          
          //returns the total of the string if the string contains the answer
             if(stor.end()-stor.begin() <=1)
             {
                 return Total;
             }          
       }
}



You need to think about what you are doing a bit better:

while (i != eq.length())
{
    i++;
    if (isspace(eq[i]))
    {continue;}

    else
    eq[j] = eq[i];
    j++;
}

Firstly, you don''t need the else: if the condition evaluates to true, then it executes the continue so the else isn''t needed. Secondly, even if you did carray on after the if, the indentation implies that the else code would be both the

eq[j] = eq[i];

and the

j++;

lines - this is not the case. Thirdly, be consistent: always indent code to the proper level, it makes it easier to read:

if (isspace(eq[i]))
{continue;}

Not particularly readable, is it? :laugh:

Particularly when you are starting, always use {...} for condition execution blocks: even when they are a single statemnet - it makes it obvious and can prevent problems later, when you add code that should be executed as part of the condition.

while (i != eq.length())
{
    i++;
    if (isspace(eq[i]))
    {
        continue;
    }
    else
    {
        eq[j] = eq[i];
        j++;
    }
}

I would actually re-write this a lot more simply:

while (i != eq.length())
   {
   i++;
   if (!isSpace(eq[i]))
       {
       eq[j] = eq[i];
       j++;
       }
   }

Note that I changed the name of your function to match with the others!

I know this doesn''t solve your problem, but try reflecting this though your code - it will make it more readable, which can only help!


There several equation evaluators on CodeProject. You may have a look to the source code to have some ideas.
For example this one:
String Parser and Evaluator[^]


这篇关于简单计算器-难以解析部分数字和负数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆