c++计算器后续(3)
2016-07-28 13:32
405 查看
自娱自乐:
本来只是想改改第二次的代码规范的,然后好像把原来的代码玩坏了,真是尴尬。。。然后大概是又发现了一些东西。以上。
main的参数:
大概是说main函数的括号里是可以带参数的,写成这个样子:
int main(int argc, char* argv[]),然后这时main函数的输入来自命令行。也就是用cmd直接调用.exe文件时,可以在后面跟上一些数,然后这些数就会被输到main函数里。其中argc表示输入的参数个数,argv则是一个指针数组,指向各个参数,然后argv[0]表示的是.exe文件的路径。写了个简单的代码玩了玩,感觉大概就是这么回事吧。附上代码和调用结果:
#include<iostream> using namespace std; int main(int argc, char* argv[]) { int i = argc; while (i > 0) { cout << argv[argc - i] << endl; i--; } return 0; }
大概也是因为我这么玩了,然后一不小心把argv数组里的元素当成了字符串,然后我Calculator项目里的main函数写成了这样:
#include<iostream> #include<queue> using namespace std; int main(int argc,char * argv[]) { Scan CScan; Print CPrint; Calculation CCalculate; string s_input = argv[argc-1]; //输入的字符串 queue<string> qs; //数字和运算符分开的队列 double ans; //四则算式的答案 qs = CScan.ToStringQueue(s_input); ans = CCalculate.CalculateStringQueue(qs); if (argv[1] == "-a") { CPrint.PrintAns(s_input, ans); } else { CPrint.PrintAns(ans); } return 0; }
结果当然是cmd里面输入'-a'它也只输出一个答案,然后不幸的还是个错误的答案,啊,这是后话,被我玩坏的代码。
于是又再去看看
int main(int argc,char * argv[]),指向字符的指针,然后就凌乱了,那我前面的输出是什么鬼,不应该输出地址吗,你输出元素也不该是字符串啊。
然后就写了一些东西来试试看:
#include<iostream> #include<string.h> using namespace std; int main() { string str; cin >> str; char* p1 = &str[0]; printf("%x\n",p1); cout << p1 << endl; cout << *p1 << endl; cout << "==分割线==" << endl; char** p2 = &p1; printf("%x\n",p2); cout << p2 << endl; cout << *p2 << endl; cout << "==分割线==" << endl; char arr[3] = {'a', 'b', 'c'}; cout << &arr[0] << endl; return 0; }
按照我的理解来说,输出p1应该是输出str的首地址才对,但是cout直接输出了str。然后输出*p大概还是符合预期的,只有一个a。所以cout不用指定输出的类型,如果你给它一个地址,它大概会输到底的意思?好像有点模糊的体会,不是很懂。
那我的判断条件
argv[1] == "-a",大概是比较第一参数的地址和"-a"的整型值(就像字符有整型值那样吧),会一样才奇怪。
于是去百度了比较字符串的函数,有挺多乱七八糟的,考不考虑大小写啊啥的,感觉
strcmp(const char*, const char*)就可以,形参大概是那么个意思,相等就返回零,然后要
#include<string.h>。
大概改完了玩坏的代码第一步,然后是计算的问题。。。
代码相关:
大概是知道代码错在哪里了,遍历队列的条件不能写
i < qs.size(),因为每次都会弹出队列元素,所以
qs.size()一直都在变的,这样没办法遍历整个队列。怎么说,还好没有找很久。。。
还有一件事是,全局变量不能在.h文件里声明,不然每include一次都会再定义一次,会报错说重复定义。
然后这次的代码改动主要是main函数改为从命令行传参,Print类里的输出用了函数重载,Scan类里面的拆分区分了负号和减号以及加了个Calculation类。代码挺长,不具体贴,这里给出链接:点我啊有些注释在dev c++ 里面明明是对齐好的,传上去就乱来。还有六个字变成了乱码,明明是一样的编码不是,其他注释至少还是汉字。去改了下缩进,git表示文件没有变,那我也没办法,将就先看吧。。。那我还是贴一些好了,还有一些调用样例:
Calculation.h
#ifndef CALCULATION_H #define CALCULATION_H #include<iostream> #include<queue> #include<stack> using namespace std; class Calculation { public: //计算并返回算式的答案 double CalculateStringQueue(queue<string> qs); //返回当前情况在优先级数组里的位置 char GetPosition(string CharStackTop, string t_str); //借助优先级数组,用两个栈来计算表达式 void CalculateByStack(char order, string t_str); }; #endif
Calculation.cpp
/******************************************************************************* FileName: Calculation.cpp Author:newmoon Version :2.0 Date:16/07/25 Description: 定义实现Calculation类中的相关方法 Function List: double CalculateStringQueue(queue<string> qs) 计算并返回算式的答案 void CalculateByStack(char order, string t_str) 用两个栈来计算表达式 char GetPosition(string CharStackTop, string t_str) 返回优先级数组位置 History: <author> <time> <version > <desc> newmoon 16/07/27 2.0 代码规范相关 *******************************************************************************/ #include"Calculation.h" #include<iostream> #include<sstream> #include<queue> #include<stack> using namespace std; int flag; //是否继续计算 double ans; //最终的计算结果 stack<double> NumStack; //储存数字的栈 stack<string> CharStack; //储存运算符的栈 //用于运算优先级判断的数组 //行表示运算符栈顶的运算符 //列表示算式当前遍历到的运算符 //">"表示栈顶优先级高,应弹出来进行计算 //"<"表示栈顶优先级低,遍历到的运算符直接入栈 //"="表示遍历到底,NumStack最后一个元素即答案 //或是遍历到")"且栈顶为"(",应弹出栈顶继续遍历 //"0"表示算式有误 //'+', '-', '*', '/', '(', ')', '#' char order[7][7] = {{'>', '>', '<', '<', '<', '>', '>'}, //'+' {'>', '>', '<', '<', '<', '>', '>'}, //'-' {'>', '>', '>', '>', '<', '>', '>'}, //'*' {'>', '>', '>', '>', '<', '>', '>'}, //'/' {'<', '<', '<', '<', '<', '=', '0'}, //'(' {'>', '>', '>', '>', '0', '>', '>'}, //')' {'<', '<', '<', '<', '<', '0', '='} //'#' }; /********************************************** Description:返回优先级数组位置 Input:运算符栈的栈顶元素string CharStackTop 算式当前遍历到的运算符string t_str Output:无 Return:优先级数组的字符型元素order[x][y]; Others:无 ***********************************************/ char Calculation :: GetPosition(string CharStackTop, string t_str) { int x, y; switch (CharStackTop[0]) { case '+': x = 0; break; case '-': x = 1; break; case '*': x = 2; break; case '/': x = 3; break; case '(': x = 4; break; case ')': x = 5; break; case '#': x = 6; break; } switch (t_str[0]) { case '+': y = 0; break; case '-': y = 1; break; case '*': y = 2; break; case '/': y = 3; break; case '(': y = 4; break; case ')': y = 5; break; case '#': y = 6; break; } return order[x][y]; } /***************************************** Description:用两个栈来计算表达式 Input:优先级数组元素char order 算式当前遍历到的运算符string t_str Output:无 Return:无 Others:答案存在全局变量ans里 ******************************************/ void Calculation :: CalculateByStack(char order, string t_str) { char m_order; //表示优先级数组中的位置 double num, num1, num2; //用于辅助计算 //借助优先级数组进行具体计算 switch (order) { //栈顶的运算符优先级较高 //弹出栈顶的运算符和两个数来计算 case '>': num1 = NumStack.top(); NumStack.pop(); num2 = NumStack.top(); NumStack.pop(); switch (CharStack.top()[0]) { case '+': num = num1 + num2; NumStack.push(num); CharStack.pop(); break; case '-': num = num2 - num1; NumStack.push(num); CharStack.pop(); break; case '*': num = num1 * num2; NumStack.push(num); CharStack.pop(); break; case '/': num = num2 / num1; NumStack.push(num); CharStack.pop(); break; } //下一个栈顶元素优先级仍然较高则继续计算 while(!CharStack.empty() && flag) { m_order = GetPosition(CharStack.top(), t_str); CalculateByStack(m_order, t_str); } break; //栈顶运算符优先级较低 //遍历到运算符直接入栈 case '<': flag = 0; CharStack.push(t_str); break; case '=': //表示遍历结束 if (t_str[0] == '#') { //最终答案 ans = NumStack.top(); NumStack.pop(); CharStack.pop(); } //遍历到")"且栈顶为"(",应弹出栈顶继续遍历 else { CharStack.pop(); flag = 0; } break; //算式有误的"0"情况 default: cout << "输入的算式有误" << endl; exit(1); } } /******************************************* Description:计算并返回算式的答案 Input:拆分好好的算式队列queue<string> qs Output:无 Return:算式的答案 Others:无 ********************************************/ double Calculation :: CalculateStringQueue(queue<string> qs) { //辅助判断遍历结束 qs.push("#"); CharStack.push("#"); char m_order; //表示优先级数组中的位置 string t_str; //遍历到的队列元素 double t_num; //辅助将string转为double int n = qs.size(); //每次循环qs.size()都会减小 stringstream stream; //辅助将string转为double //遍历队列开始计算 for (int i = 0; i < n; i++) { flag = 1; //是否继续计算 t_str = qs.front(); qs.pop(); //遍历到运算符,进行相应计算 if (t_str == "+" || t_str == "-" || t_str == "*" || t_str == "/" || t_str == "(" || t_str == ")" || t_str == "#") { //借助优先级数组判断运算的优先级 m_order = GetPosition(CharStack.top(), t_str); //实际的计算 CalculateByStack(m_order, t_str); } //遍历到数字,转为double并入栈 else { stream.clear(); stream << t_str; stream >> t_num; NumStack.push(t_num); } } return ans; }
调用样例:
相关文章推荐
- C语言中,为什么字符串可以赋值给字符指针变量
- 1. Two Sum(c++实现)
- codeblocks编译出错问题的解答!(编译c++ 或者c程序)
- 在C语言中,double、long、unsigned、int、char类型数据所占字节数
- c++set常用用法
- c++内存对齐
- 求一元二次方程的根
- 黑马程序员:C++学科推出全新三大实战项目
- Cpp环境【POJ3622】【Vijos2990】【Usaco2007】挑剔的美食家
- 【OpenJudge】c语言_计算2的幂
- 【OpenJudge】c语言_A*B问题
- 【OpenJudge】c语言_计算三角形面积
- C语言词法分析:C#源码
- 黑马程序员:C/C++薪资再创纪录,平均薪资11054元!
- c++ 析构函数为什么要加virtual
- 【c语言_取值范围】int long longlong
- C++文件处理
- C++构造函数、拷贝构造函数
- C语言学习之——排序
- C++使用ODBC连接数据库时出现无法将SQLCHAR*转换为SQLWCHAR*