zoukankan      html  css  js  c++  java
  • c++计算器后续(4)

    自娱自乐:

    大概是终于做到没做完的部分了,第三步助教学长的评论还没去改,感觉那个把读取文件放到Scan里面比较麻烦,其他大概还好。以上。

    文件读写:

    先是原来的残留问题,都是和fstream :: open这个函数有关的。这个函数用来打开文件,它有两个参数,一个是打开的文件的路径,一个是打开文件的方式,然后问题都出在路径上。其一:ifstream infile("D: ext.txt", ios :: in)中的斜杠要写成双斜杠才能成功的打开文件,一个可以接受的解释是:因为 C++ 编译系统将单斜杠理解为转义字符。其二:用一个string的对象来接收键盘输入的路径,然后把这个对象放在第一个参数的位置上,会报错说没有适合的重载函数,可是看写函数时候的参数提示,除了const char*,明明也有const string&。原来是看了别人的,用string :: c_str()函数,把string的对象变成c中的字符串样式(大概是字符数组吧,那个函数会返回一个指向字符的指针),大概是变成了调用参数为const char*的那种。然后网上有人说这是个bug,c++ 11就支持直接用string的对象。不过现在是用命令行调用,那我直接用char* argv[]的元素当参数就好。大概就是这样了。

    代码修改:

    Main.cpp

    #include"Scan.h"
    #include"Print.h"
    #include"Calculation.h" 
    
    #include<iostream>
    #include<fstream>
    #include<queue>
    using namespace std;
    
    int main(int argc, char* argv[])
    {
        Scan CScan;
        Print CPrint;
        Calculation CCalculate;
    
        string arg_1 = argv[1];	//储存第一个参数 
        queue<string> qs;	//数字和运算符分开的队列 
        string s_input;	//输入的字符串 	 
        double ans;	//四则算式的答案
    
        if (arg_1.compare("-f") == 0) 
        {
            //打开读,写文件 
            ifstream ifile(argv[2], ios :: in);
            ofstream ofile(argv[3], ios :: out);
    
            if (ifile.is_open() && ofile.is_open())
            {
                while (!ifile.eof())
                {
                    s_input = CScan.GetFileString(ifile);
                    qs = CScan.ToStringQueue(s_input);
                    ans = CCalculate.CalculateStringQueue(qs);
                    CPrint.PrintToFile(ofile, ans);
                }
            }
            else 
            {
                cout << "文件打开失败!" << endl; 
            }
    
            //关闭读,写文件 
            ifile.close();
            ofile.close();
        }
        else
        {		
            s_input = argv[argc - 1];
            qs = CScan.ToStringQueue(s_input);
            ans = CCalculate.CalculateStringQueue(qs);
    
            if (arg_1.compare("-a") == 0)
            {
                CPrint.PrintExpreesion(s_input, ans);
            }
            else
            {
                CPrint.PrintAns(ans);
            }
        } 
    
        return 0;
    }
    

    主要就是main里面的修改比较大,其他的就是添了一些简单的函数或是又考虑了一些情况而已,像算式有了等号,还有就是支持不带括号的负数(看了助教学长发到群里的那个测试文件之后。。。)。主要的修改是围绕着学长的建议来的,全部读写完成之后再关闭文件,然后打开文件之后在Scan里面读取(现在大概算吧),还有用上了c++自己的字符串比较string::compare。

    实际测试的时候,一直报错说文件打开错误,后来发现是文件名打错了。。。打对名字之后,它还是会迷之停止运行啊,我的天,到底是为什么。不过啊,输出文件里倒是真的有输出,然后破罐子破摔试了下十万个数据那个。唔,大概有输出十万个答案吧,不过用cmd里面的fc来和正确答案的文件比较啊,还是有很多不一样的地方(看下图侧边那长长的进度条。。。):

    啊,大概是我的答案四舍五入了?哪里忘记用double了吗。。。原来第三次的代码会停止运行好像就是因为有个double写错了,然后下面是完善过程。

    关于找停止运行的地方,断点调试还是很迷啊,表示没成功过几次,感觉应该很简单的啊,大概是dev c++抽了,不管,反正用傻办法(大概是加一堆的提示输出。。。)也知道为什么会停止运行了。大概是fstream::eof的锅,它让循环多了一次,然后是文件里找不到可以输入的东西而崩溃。百度了一下,eof貌似没什么用啊,它在没有东西可输的时候才会从false变成true,然而这个时候代码不是也崩溃了嘛,没起到下次没东西输这样的预测的作用。唔,虽然在别人博客有看到这么用(大概当初就是直接看过来的,然后我还用错了。。。),不管,不再去研究别人为什么可以,我用自己的想法。然后我的想法大概就是这样:

    //实际上等价于while (ifile >> s_input)。。。 
    while (CScan.GetFileString(ifile, s_input))
    {		
        qs = CScan.ToStringQueue(s_input);
        ans = CCalculate.CalculateStringQueue(qs);
        CPrint.PrintToFile(ofile, ans); 
    }
    

    唔,反正不崩溃就好,然后是原来那个double的四舍五入的问题。写了个简单的输入输出来测试,发现cout默认输出的double的有效数字是六位(啊,大概是上课没认真听)。于是继续百度改有效数位的方法,改成10位就够了吧,原来第一步就说不支持数位超过十位的。下面是修改后cmd里面的fc比较结果:

    居然出现了-0耶,试了下输入-0到double类型的a,输出的a真的是-0。然后好像想起了貌似有上过《计算机导论》,好像有说double里的0和-0表示不一样的?啊,不去深究,再稍微改改代码。下面是最终的结果:

    哈,大概是完成了计算器第三步了吧,开心,代码已上传github,这是链接:点我啊

    除了有些缩进传上去它又乱来(大概是dev c++的锅),其他感觉完美(哈哈)。。。

  • 相关阅读:
    窗口参数Hello Win32 之疯狂注释版
    返回代码hdu 2054 A==B?
    function类html5游戏开发零基础开发《圣诞老人送礼物》小游戏
    路径工程OpenCV依赖文件路径自动添加方法
    变形测试数据HDU1181:变形课(DFS)
    类参数Hello MFC 之疯狂注释版
    按钮保存ios学习之xcode到处ipa安装包
    clientapivc api TCP&UDP—helloworld
    文件下载Asp.net下载文件的实例
    选择代码在Ubuntu12.04.2上使用Xmonad窗口管理器(续)
  • 原文地址:https://www.cnblogs.com/mingyueanyao/p/5719463.html
Copyright © 2011-2022 走看看