自娱自乐:

本来只是想改改第二次的代码规范的,然后好像把原来的代码玩坏了,真是尴尬。。。然后大概是又发现了一些东西。以上。

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++计算器后续(3)的更多相关文章

  1. 使用HTML+CSS,jQuery编写的简易计算器后续(添加了键盘监听)

    之前发布了一款简易的计算器,今天做了一下修改,添加了键盘监听事件,不用再用鼠标点点点啦 JS代码: var yunSuan = 0;// 运算符号,0-无运算;1-加法;2-减法;3-乘法;4-除法 ...

  2. c++计算器后续(5)

    自娱自乐: 大概是重新开始玩qt,然后MFC和第四步附加的作业大概不会去玩了.以上. QT相关: 阶段一: 原来作业里举了qt和mfc这两个做界面的东西,网上都说qt容易上手,学了mfc再来看qt简直 ...

  3. c++计算器后续(4)

    自娱自乐: 大概是终于做到没做完的部分了,第三步助教学长的评论还没去改,感觉那个把读取文件放到Scan里面比较麻烦,其他大概还好.以上. 文件读写: 先是原来的残留问题,都是和fstream :: o ...

  4. c++计算器后续(2)

    自娱自乐: 大概是了解了一下前缀.中缀.后缀表示法是啥,并没有去深究,比如考虑实现啊,然后Calculation类里面的计算方法还是选用原来的直接对中缀表达式求值,只是把代码改得规范点,以上. 各表示 ...

  5. c++计算器后续(1)

    自娱自乐: 大概是一直在说的代码规范,大概是玩一玩,以上. 代码规范: 参考原文:链接 相关节选: 4 程序的版式 4.4规则:较长的语句(>80字符)要分成多行书写. 4.5规则:不允许把多个 ...

  6. 微信小程序计算器后后续

    改的眼睛都要瞎了,总算是知道问题出哪了 最后一段 在等号里面计算输入的数组,这个判断的主要操作是将输入的数据的数组进行数和符号的拆分然后再计算,把数按字符串输入数组,然后将数和符号进行拆分 ,最后通过 ...

  7. 微信小程序计算器模拟后续

    今天按着自己的思路又重打了一遍 wxml没什么说的,就是分块起名,显示数字和结果的作为屏幕,数字键盘一行四块 <view class="onTop"> <view ...

  8. 【IOS开发笔记03-视图相关】简单计算器的实现

    UIView 经过前几天的快速学习,我们初步了解的IOS开发的一些知识,中间因为拉的太急,忽略了很多基础知识点,这些知识点单独拿出来学习太过枯燥,我们在今后的项目中再逐步补齐,今天我们来学习APP视图 ...

  9. Js函数初学者练习(一)switch-case结构实现计算器。

      前  言 JRedu 给大家介绍一点JS函数的练习题希望初学者多做一些练习能够更好的掌握JS的函数,以及能够提升大家的逻辑思维.(我也是个渣渣希望路过的大神多提建议或意见) 希望能够对大家有所帮助 ...

随机推荐

  1. UOJ #188. 【UR #13】Sanrd

    Description 给定 \(\sum_{i=l}^r f[i]\) \(f[i]=\) 把 \(i\) 的每一个质因子都从小到大排列成一个序列(\(p_i^{c_i}\)要出现 \(c_i\) ...

  2. IOS折线图二

    上周把项目的折线图给做了下,今天想着把它完善完善,自己设置了不同的数据源来测试,哈哈,还真遇到问题了, 就是给图表设置折点数为0时,视图显示的还是原来的,由于数据为空,应该将其设置为空,所以想着怎么把 ...

  3. 分享一个好用的dns

  4. JD上市前内情:李彦宏雷军柳传志拷问刘强东

    这篇文章是京东上市前夕,在某个会议上刘强东与柳传志.李彦宏.雷军等大佬们的闭门交流实录,由于当时京东正值上市敏感期,文章没有被发出来,现在京东上市了,我想,大家可以看看几位商界大佬对刘强东的“犀利拷问 ...

  5. IDEA设置类注解和方法注解(详解)

    从eclipse工具到IDEA工具的转化,发现IDEA工具配置注释模板变的不一样了,不说废话了,直接开始 一.设置类注解模板(在创建类的时候自动填充模板) /** * @ProjectName: ${ ...

  6. IO流的复习笔记

    IO字节流和缓冲流 IO字节流的读取和写入 读取 import java.io.FileInputStream; import java.io.FileNotFoundException; impor ...

  7. java四则运算----前缀、中缀、后缀表达式

    接到一个新需求,需要实现可配置公式,然后按公式实现四则运算. 刚拿到需求,第一反应就是用正则匹配‘(’,‘)’,‘+’,‘-’,‘*’,‘/’,来实现四则运算,感觉不复杂. 然后开始coding.发现 ...

  8. JQuery图片加载显示loading和加载失败默认图片

    在很多时候我们需要用到图片加载功能,在网上搜资料后就想为了以后使用方便重新整理了下,结果如图: 最后一张是加载失败显示的图片,没找到合适的图片,先用他顶替. 页面引用 <div class=&q ...

  9. Runtime 打开记事本

    package com.direct.str; import java.io.IOException; public class RunTimeDemo { /** * @param args */ ...

  10. jQuery和MVVM类框架的编程区别点

    本文说的mvvm框架以react为列,其他应该也是类似的: react实际上仅仅是帮助我们再View层简化,让我们仅仅需要专注数据,只要数据改变,所有的视图就会自己跟随着改变, 本人自己做react项 ...