zoukankan      html  css  js  c++  java
  • 寒假作业之三

    这里是github的代码的传送门

    我是作业开始弄没多久做的,遇到问题挺多,主要是对多文件的处理,和string的应用的实践太弱,导致问题一大堆,看见题目,如果不用string和类,单纯是按一道规范的编程题目,难度会降低很多。所以我一开始低估了这题的难度= =....

    完成花时:

    作业发布开始,每天1-2小时至春节前后


    遇到问题:

    1.不清楚多文件中,类的.h与.cpp的作用...

    问题描述

    因为没想到作业是多文件的...所以没有注意这方面的内容,没有练习,只是看了翁恺老师的视频而已....因为看 头文件 这一节内容比较早,到现在少说也有半个月了,又没有回头看,慕课上的类差点看到,所以没有二轮回头看,所以不太熟悉这方面内容,然后我回头看这一节,发现翁老师对这一块讲的比较少,主要说头文件的是用于声明的,对于类的写法比较范一些,所以我没太研究清楚,开始1.2天还不知道是写一个项目,就直接写在一个cpp里面了....后来写项目才发现,自己真的什么都不懂,不知道成员变量写哪,更有甚者,发现居然不知道成员变量如何给成员函数用(我原来觉得这个是理所当然的).总之..很乱

    解决办法

    说真的,编译过不了,而且是因为内容不熟,就会有一种无从下手的感觉,因为自己都不知道错哪了,很是让人恼火
    然后,我回头看了一下翁老师 自动售票机 这一节实例,很凄楚的写出了如何创建类,使用成员变量,成员函数,我上面之所以给成员函数用成员变量,是因为,我习惯是想到什么变量,然后临时添加变量,然后,DEV C++的编译,并没有按先.h再.cpp的顺序把,所以.cpp里面报错了..正确的做法是,该类的.h添加了成员变量,F9保存,再到.cpp里面工作...
    比如:

    添加了queue<string> que;;要想Scan.cpp能使用这个队列,要先将头文件保存,消灭

    其中Scan.h前面的[*]当时不知道,所以一堆错误...


    2.队列问题

    不用怀疑,基本上每个注意点,我都是躺着错过去的

    问题描述

    string类的问题,基本上可以说是最大的问题了,如何赋值,如何清空,基本上每一个问题,我都遇见了比如:

    这个可能很容易就看出来,但是我经常在输出的时候,就是会忘记(),忘记括号,我为什么会输出这个东西呢,因为第三个问题,string类方面的问题,让我必须找每一步错误,这个是中间调试过程,本来这个错误是很好找的,但是你是刚刚接触这个东西,而且,我的错误可是一!大!堆!,加上我的DC经常抽风,所以有时候就找不出来了,还有就是que.front(),这个的()漏了,然后错误信息又是乱七八糟一大团,完全不知所云.....

    解决方法

    没什么方法,跪久了,就大概知道是怎么回事了,开始不知道怎么回事,多来几次,就知道是怎么回事了,《挑战程序设计》第二章有提到队列用法,最简单的输入输出,然后百度一下大概用法,多余的没怎么用,也记不住,但现学现用,在这里也算足矣。

    3.string 类的问题

    问题描述

    本题核心就是就是如何写Scan类里面的 ToStringQueue(string input)函数,这个函数要完成的是:将数字和符号提取出来,并存到队列中去

    然而我遇到的问题是,如何用string 类的变量,按要求存储相应的字符,然后将其给队列

    基本上我后面的时间,都要解决这个问题,为了解决这个问题,我用了很多方法,弄了好多中间变量,然后发现,咦,这个样子都是错的.....然后,好多时间就过去了..

    解决方法1

    用一个string类的 temp变量,来存储
    下面是代码雏形,(一开始做题目是需要考虑数字正负号的)

    
       void Scan::ToStringQueue(string input)
    	{
    	string temp = "";        //用一个temp来保存
    	int n = input.size();    //记录字符数
    	temp[0] = input[0];      //一开始不知道string类可以直接加单个字符,就是用temp+=input[0]的形式
    	
    	/*判断第一个字符是不是数字,是数字就存入temp中*/
    	if (input[0] == '+' || input[0] == '-' || (input[0] >= '0' && input[0] <= '9'))
    	{		
    	} 
    	else     //不是数字,那么就存如队列,然后清空temp
    	{	
    		Scan::que.push(temp);
    		temp = "";
    	}
    	for (int i = 1; i < n; i++)    //遍历
    	{
    		if (input[i] >= '0' && input[i] <= '9')    //判断当前字符是不是数字
    		{
    			
    			
    			if (input[i-1] >= '0' && input[i-1] <= '9')
    			{
    				temp += input[i];
    			} 
    			else     //当时题目没改,判断+-是不是数字的符号
    			{
    				if (input[i-1] == '+' || input[i-1] == '-')
    				{
    					if (i-2 < 0 || input[i-2] < '0' && input[i-2] > '9')
    					{
    						temp += input[i];
    					}
    					else temp[0] = input[i];
    				}
    			}
    			
    		}
    		else if (input[i] == '+' || input[i] == '-')    
    		{
    			Scan::que.push(temp);    
    			temp="";
    			temp[0] = input[i];
    			if (input[i-1]>='0'&&input[i-1]<='9')
    			{			
    				Scan::que.push(temp);    
    				temp = "";
    			 } 
    		}
    		else    //其他符号,则直接存入,然后清空
    		{
    			Scan::que.push(temp);
    			temp = "";
    			temp[0] = input[i];
    			Scan::que.push(temp);
    			temp = "";
    		}
    		
    	}
    	Scan::que.push(temp);
    	temp = "";
    }
    
    

    输入测试数据

    测试3

    失败,
    然后我当时测试了数据,以为是string 类再赋值的方法temp=""或者
    temp.clear()失效,所以当时后面选择了另外的方法
    直到我临近写随笔的时候,才发现了我的错误temp[0]=input[0]这个代码是错误的,所以导致我的temp存不了东西,所以que里面存的都是空
    而且,代码还有瑕疵,漏考虑了一种情况
    下面是修改后的代码

    void Scan::ToStringQueue(string input)
    {
        /*所有temp[0]的地方全部改成了temp+,因为temp无论是有没有初始化或者清空后,已经算是空串的存在,可以用'temp+='的形式*/
    	string temp = "";	
    	int n = input.size();
    	temp += input[0];
    	if (input[0] == '+' || input[0] == '-' || (input[0] >= '0' && input[0] <= '9'))
    	{
    	}
    	else 
    	{		
    		Scan::que.push(temp);
    		temp = "";
    	}
    	for (int i = 1; i < n; i++)
    	{
    		if (input[i] >= '0' && input[i] <= '9')
    		{
    			if (input[i-1] >= '0'&&input[i-1] <= '9')
    			{
    				temp += input[i];
    			} 
    			else 
    			{
    				if (input[i-1] == '+' || input[i-1] == '-')
    				{
    					if (i-2 < 0 || input[i-2] < '0' && input[i-2] > '9')
    					{
    						temp += input[i];
    					}
    					else
    					{
    						temp += input[i];
    					} 
    				}
    				else    //当时漏考虑了如果数字前是除了‘-’,‘+’字符的情况
    				{
    					Scan::que.push(temp);
    					temp = "";
    					temp += input[i]; 
    				}
    			}
    			
    		}
    		else if (input[i] == '+' || input[i] == '-')
    		{
    			Scan::que.push(temp);
    			temp = "";
    			temp += input[i];
    			if (input[i-1] >= '0' && input[i-1] <= '9')
    			{			
    				Scan::que.push(temp);
    				temp = "";
    			 } 
    		}
    		else
    		{
    			Scan::que.push(temp);
    			temp = "";
    			temp += input[i];
    			Scan::que.push(temp);
    			temp = "";
    		}
    		
    	}
    	Scan::que.push(temp);
    	temp = "";
    }
    

    测试结果如下

    测试4

    很好,就差空行了,为什么会有空行呢?其实空行最好解决了的,只要加一个判断条件que.empty()que.size()在push前判断一下就好了

    代码改如下:

    Scan::que.push(temp);
    temp = "";
    temp += input[i];
    

    都改为

    if (que.size())//或者que.empty()
    {
    	Scan::que.push(temp);
        temp = "";
    }
    temp += input[i];
    

    便可以解决空行问题,因为这个是最初版本,而修改为可用版本的时候已经过了半个月,就不予深究


    解决方法2

    用string类数组temp[100],分别存储字符,然后存入队列,这样就不用于清空这一操作了

    实现方法:

    增加一个int类型的coun变量每当temp[coun]存入队列后,就让coun自增一

    代码如下:

    void Scan::ToStringQueue(string input)
    {
    	string temp[100];//用数组代替
    	int n = input.size(), coun = 0;
    	temp[coun] += input[0];
    	for (int i = 1; i < n; i++)
    	{
    		if (input[i] >= '0' && input[i] <= '9' || input[i] == '.')   
    		{
    			if ((input[i-1] >= '0' && input[i-1]<='9')||input[i-1]=='.')
    			{
    				temp[coun]+=input[i];  
    			} 
    			else
    			{
    				if (input[i-1] == '+' || input[i-1] == '-')
    				{
    					if (i-2 < 0 || input[i-2]<'0' || input[i-2] > '9')
    					{
    						temp[coun] += input[i];
    					}
    					else 
    					{						
    						Scan::que.push(temp[coun++]);    //存入队列后coun自增
    						temp[coun] += input[i];
    					}
    				}
    				else     //其他符号
    				{				 
                        Scan::que.push(temp[coun++]);
    					temp[coun] += input[i];
    				}
    			
    			}
    			
    		}
    		else 
    		{
    			Scan::que.push(temp[coun]);	
    			coun++; 
    			temp[coun] += input[i];
    		}
    		
    	}
    	Scan::que.push(temp[coun]);
    	coun++;	
    }
    
    
    

    测试结果如下:

    测试5

    没问题,到这里,基本上问题都解决的差不多了

    如何是按要求,解决输入数位的问题了
    (ps然而我当时没认真看修改后的作业要求= =)

    只要要push进队列前,判断一下输入的temp是否超过10位就好了,如果超过10位,则将队列清空,然后往队列加入警告语句,即可.要做到这些,要先定义一个判断的只要要push进队列前,判断一下输入的temp是否超过10位就好了,如果超过10位,则将队列清空,然后往队列加入警告语句,即可.要做到这些,要先定义一个判断的bool类型,然后判断temp[coun].size()是否超过10位就好了

    具体代码如下:

    
    if (temp[coun].size() > 10)
    	{				
    	    if (temp[coun][0] == '-' || temp[coun][0] == '+')
    	    {
    	        if (temp[coun].size() > 11)  flag = true;
    	    }
    	    else flag = true;
        } 
    

    但是,很久之后,我发现我理解问题弄错题目意思了,小数点不算一个位数,所以,我加了一个bool类型的变量判断是不是当前位数存在小数点,如果是的话,那么超过10位报错,就要改为超过11位小数报错了;

    代码如下:

        if (temp.size()>10) 
        {
            if (temp.size()==11&&flag_dot) 
    		{
    		}
       	    else
            {
                flag = true;
            } 		
    	 }
    

    然后在函数末尾加上

    
    
        
    void Scan::ToStringQueue(string input)
    {
    	string temp[100];
    	bool flag = false;                  //判断是否存在数超过10位
    	int n = input.size(),coun = 0;      //n用于记录字符串长度,coun来控制将字符存入temp的不同数组中
    	temp[coun] += input[0];
    	for(int i=1; i < n; i++)
    	{
    		if(flag)     //如果存在数超过10位,直接跳出循环
    		{
    			break;
    		}
    		if (input[i] >= '0' && input[i] <= '9' || input[i] == '.')
    		{
    			if ((input[i-1] >= '0' && input[i-1] <= '9') || input[i-1] == '.')
    			{
    				temp[coun] += input[i];
    				if (temp[coun].size() > 10)//当前temp数组存的为数字,判断当前temp数组中的数字是否超过10位
    				{
    					
    					//超过10位,判断是不是带符号,如果带符号,则要超过11位
    					if (temp[coun][0] == '-' || temp[coun][0] == '+')
    					{
    						if (temp[coun].size() > 11)  flag = true;
    					}
    					else
    					{
    						flag = true;
    					} 
    				}
    			}
    			else   //前一个是符号,下面分情况讨论  
    			{
    				if (input[i-1] == '+' || input[i-1] == '-')  
    				{
    					if(i-2 < 0 || input[i-2] < '0' || input[i-2] > '9')
    					{
    						temp[coun] += input[i];//那么该符号表示数字的正负,存储到temp,先不传给队列
    					}
    					else     //如果符号前面是数字,那么该符号表示运算符
    					{
    						Scan::que.push(temp[coun++]);
    						temp[coun] += input[i];
    					}
    				} //前面符号不是+,-,可以把temp传到队列,更新coun
    				else
    				{
    					if (temp[coun].size() > 10)//判断是否超过10位,同理
    					{
    						if(temp[coun][0] == '-'||temp[coun][0] == '+')
    						{
    							if (temp[coun].size() > 11)  flag = true;
    						}
    						else
    						{
    							flag = true;
    						} 
    					}
    
    					Scan::que.push(temp[coun++]);
    					temp[coun] += input[i];
    				}
    			}
    		}
    		else     //如果当前字符是符号,将temp传入队列,更新coun;
    		{
    			if (temp[coun].size() > 10)
    			{
    
    				if (temp[coun][0] == '-' || temp[coun][0] == '+')
    				{
    					if (temp[coun].size()>11)  flag = true;
    				}
    				else flag = true;
    			}
    			Scan::que.push(temp[coun]);
    			coun++;
    			temp[coun] += input[i];
    		}
    
    	}
    	if (temp[coun].size() > 10)    //最后一个temp还没有存,判断同理
    	{
    		if (temp[coun][0] == '-' || temp[coun][0] == '+')
    		{
    			if (temp[coun].size() > 11)  flag = true;
    		}
    		else
    		{
    			flag = true;
    		} 
    	}
    	Scan::que.push(temp[coun]);//存最后一个
    	coun++;
    	if (flag)    //如果超过10位,那么,把原来存进去的都清空,push上 下面的警告.
    	{
    		while (que.size())
    		{
    			que.pop();
    		} 
    		que.push("error:You can enter the number of digits can not be more than 10");
    	}
    }
    

    之后,我才发现题目改了,不过难度降低,只需要删除多余的判断即可,毕竟该解决的问题已经解决了:

    改进版代码如下:

    void Scan::ToStringQueue(string input) 
    {
    	
    	/*temp作为中间变量,暂时存储将要存入队列中的元素,重复利用temp,或者用temp[100]与int类型变量coun,利用数组分别存储数字与字符,再存入队列 */
    	string temp = "";
    	bool flag = false;           //判断是否存在超过十位的数
    	bool flag_dot = false;       //判断是否存在小数点 
    	int n = input.size();        //n表示字符串的长度
    	for (int i = 0; i<n; i++)    //遍历字符串中的字符 
    	{ 
    		if (flag)    
    		{ 
    		    break;
    		}
    		if (input[i] >= '0' && input[i] <= '9' || input[i] == '.')    
    		{
    			if (input[i] == '.') flag_dot = true;
    			
    			/*如果前面一位字符也是数字,或者当前字符是第一个字符,则先不将temp传入队列*/
    			if (i == 0 || (input[i-1] >= '0' && input[i-1] <= '9' || input[i-1] == '.'))
    			{
    			}
    			else if (temp.size())    //为了防止出现空串而错误将空串存入队列 
    		    {
    					Scan::que.push(temp);    
    					flag_dot = false;
    					temp = "";
    			}
    			temp += input[i];
    			if (temp.size() > 10)    //判断是否存在超过10位的数字 
    			{
    				if (temp.size() == 11 && flag_dot == true)    //排除包含小数点而实际只有10位数的情况 
    				{
    				}
    				else
    				{
    				    flag = true;
    				} 
    			}
    		}
    	    else    //当前字符是符号 
    		{
    			if (temp.size()>10) 
    			{ 
    				if (temp.size() == 11 && flag_dot)
    				{
                    } 
    				else 
    				{
    					flag = true;
    				} 
    			}
    			if (temp.size())     
    			{ 
    				Scan::que.push(temp);
    				flag_dot = false;
    				temp = "";
    			}
    			temp += input[i];
    		}
    
    	}
    	
    	/*遍历完成时,temp中依然有字符未存入队列,所以还需判断存在超过10位的数和将temp内容存入队列*/
    	if (temp.size() > 10)    
    	{ 
    		if (temp.size() == 11 && flag_dot)
    		{
    		} 
    		else
    		{
    			flag = true;
    	    } 
    	}
    	if (temp.size()) 
    	{
    		Scan::que.push(temp);
    		temp = ""; 
    	}
    	if (flag)    //判断如果存在超过十位的数,则只输出警告内容
    	{ 
    		while (!que.empty())    
    		{
    			que.pop();
    		}    
    		que.push("error:You can enter the number of digits can not be more than 10
    ");
    	}
    	return ; 
    }
    

    不过,既然用了判断是否为空串
    代码应该可以更加简洁一些,如果运用库函数中判断数字的函数isdigit()等,看起来会更简洁一些,但是这里并不需要怎么做,其中包含一些个人习惯养成的问题,小问题调用过多函数反而会浪费更多时间(当然这里并没有限时)就不予深究


    其他注意点:

    关于Scan类与Print类中队列问题:

    Scan.cpp中完成了输入,字符传入队列之后,如何交给Print类中呢?看了写翁恺老师的教学视频后,我个人是不太愿意直接把Scan类中queue类型的变量que做成public的,因为这样子外界可以对他进行更改..同理输入也是,所以我把输入的string s做成私有,用函数与外界对接,应该可以体现C++类的封装把?
    但是很可惜,当我定义一个函数类型为队列的时候..报错了...所以就直接把队列做成public了,直接用2个对象的队列进行赋值操作;
    main函数中的代码如下:

    	Scan get_scanf;
    	Print put_printf;
    	
    	/*调用 GetString() 函数,利用其返回值将输入的字符串传递给 ToStringQueue() 函数*/
    	get_scanf.ToStringQueue(get_scanf.GetString());	
    	put_printf.que = get_scanf.que;
    	put_printf.putqueue();    //调用函数输出分好的数字与字符 
    	system("pause");
    
    

    最终代码附上#

    ===
    main.cpp

    #include <iostream>
    #include<cstdlib>
    #include"Scan.h"
    #include"Print.h"
    /* run this program using the console pauser or add your own getch, system("pause") or input loop */
    using namespace std;
    int main()
    {
    	Scan get_scanf;
    	Print put_printf;
    	
    	/*调用 GetString() 函数,利用其返回值将输入的字符串传递给 ToStringQueue() 函数*/
    	get_scanf.ToStringQueue(get_scanf.GetString());	
    	put_printf.que = get_scanf.que;
    	put_printf.putqueue();    //调用函数输出分好的数字与字符 
    	system("pause");
    }
    
     
        
    

    Scan.h

    /************************************************************
      FileName: 	Scan.h
      Author:       031502248
      Date:         2016/2/16
      History:        
      <author>     <time>   <version>      <desc>
      03150248     16/3/23     2.0       修改代码规范  
    ***********************************************************/
    #ifndef SCAN_H
    #define SCAN_H
    #include<queue>
    #include<string>
    using namespace std;
    class Scan
    {
    	public:
    		Scan();
    		~Scan();
    		string GetString();
    		void ToStringQueue(string input); 
    		queue<string> que;
    	private:
    		string s;
    		
    };
    
    #endif
    
    
    

    Scan.cpp

    #include "Scan.h"
    #include<cstring>
    #include<string>
    #include<iostream>
    #include<queue>
    using namespace std;
    Scan::Scan() 
    {
    }
    
    Scan::~Scan() 
    {
    }
    
    /*************************************************************
      functionname:    GetString
      Description:     用于输入一个string类和返回这个string类,目
                       的是为了避免外界直接接触类中的string变量 
      Input:           NULL
      Return:          string s:类中的私有string类型的变量 
      Others:          NULL
    **************************************************************/
    string Scan::GetString() 
    {
    	cin >> s;
    	return s;
    }
    
    /*************************************************************
      functionname:    ToStringQueue
      Description:     将输入的字符串,逐个的字符扫描这,
                       将数字和符号提取出来分别存入队列 
      Input:           string input:输入字符串
      Return:         no return 
      Others:         NULL
    **************************************************************/
    void Scan::ToStringQueue(string input) 
    {
    	
    	/*temp作为中间变量,暂时存储将要存入队列中的元素,重复利用temp,或者用temp[100]与int类型变量coun,利用数组分别存储数字与字符,再存入队列 */
    	string temp = "";
    	bool flag = false;           //判断是否存在超过十位的数
    	bool flag_dot = false;       //判断是否存在小数点 
    	int n = input.size();        //n表示字符串的长度
    	for (int i = 0; i<n; i++)    //遍历字符串中的字符 
    	{ 
    		if (flag)    
    		{ 
    		    break;
    		}
    		if (input[i] >= '0' && input[i] <= '9' || input[i] == '.')    
    		{
    			if (input[i] == '.')
    			{
    				flag_dot = true;
    			} 
    			
    			/*如果前面一位字符也是数字,或者当前字符是第一个字符,则先不将temp传入队列*/
    			if (i == 0 || (input[i-1] >= '0' && input[i-1] <= '9' || input[i-1] == '.'))
    			{
    			}
    			else if (temp.size())    //为了防止出现空串而错误将空串存入队列 
    		    {
    					Scan::que.push(temp);    
    					flag_dot = false;
    					temp = "";
    			}
    			temp += input[i];
    			if (temp.size() > 10)    //判断是否存在超过10位的数字 
    			{
    				if (temp.size() == 11 && flag_dot == true)    //排除包含小数点而实际只有10位数的情况 
    				{
    				}
    				else
    				{
    				    flag = true;
    				} 
    			}
    		}
    	    else    //当前字符是符号 
    		{
    			if (temp.size()>10) 
    			{ 
    				if (temp.size() == 11 && flag_dot)
    				{
                    } 
    				else 
    				{
    					flag = true;
    				} 
    			}
    			if (temp.size())     
    			{ 
    				Scan::que.push(temp);
    				flag_dot = false;
    				temp = "";
    			}
    			temp += input[i];
    		}
    
    	}
    	
    	/*遍历完成时,temp中依然有字符未存入队列,所以还需判断存在超过10位的数和将temp内容存入队列*/
    	if (temp.size() > 10)    
    	{ 
    		if (temp.size() == 11 && flag_dot)
    		{
    		} 
    		else
    		{
    			flag = true;
    	    } 
    	}
    	if (temp.size()) 
    	{
    		Scan::que.push(temp);
    		temp = ""; 
    	}
    	if (flag)    //判断如果存在超过十位的数,则只输出警告内容
    	{ 
    		while (!que.empty())    
    		{
    			que.pop();
    		}    
    		que.push("error:You can enter the number of digits can not be more than 10");
    	}
    	return ; 
    }
    
    
    

    Print.h

    /************************************************************
      FileName: 	Print.h
      Author:       031502248
      Date:         2016/2/16
      History:        
      <author>     <time>   <version>      <desc>
      03150248     16/3/23     2.0       修改代码规范  
    ***********************************************************/
    #ifndef PRINT_H
    #define PRINT_H
    #include "Scan.h"
    class Print :Scan
    {
    	public:
    		Print();
    		~Print();
    		queue<string> que;
    		void putqueue(); 
    	protected:
    };
    
    #endif
    
    
    

    Print.cpp

    #include "Print.h"
    #include<iostream>
    Print::Print()
    {
    
    }
    
    Print::~Print()
    {
    }
    
    /*************************************************************
      functionname:    putqueue
      Description:     输出类中私有成员变量中的queue类中的元素 
      Input:           NULL
      Return:          no return 
      Others:          NULL
    **************************************************************/
    void Print::putqueue()
    {
    	while (que.size())   //或者用que.empty(),只要队列不为空,就一直循环下去
    	{
    		std::cout << que.front() << endl; 
    		que.pop(); 
    	}
    	return ; 
    }
    
    
    
  • 相关阅读:
    linux 解压tgz 文件指令
    shell 脚本没有执行权限 报错 bash: ./myshell.sh: Permission denied
    linux 启动solr 报错 Your Max Processes Limit is currently 31202. It should be set to 65000 to avoid operational disruption.
    远程查询批量导入数据
    修改 MZTreeView 赋权节点父节点选中子节点自动选中的问题
    关于乱码的问题解决记录
    我的网站优化之路
    对设计及重构的一点反思
    我的五年岁月
    奔三的路上
  • 原文地址:https://www.cnblogs.com/Anani-leaf/p/5192042.html
Copyright © 2011-2022 走看看