• 寒假作业之三


    这里是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 安装 jdk 后 jps 出现问题/usr/jdk1.8.0_151/bin/jps: /lib/ld-linux.so.2: bad ELF interpreter: No such
    Jackson 注解
    Git 右键添加Git Bash
    No validator could be found for constraint
    rror querying database. Cause: java.sql.SQLException: null, message from server: "Host '192.168.30.1' is not allowed to connect to this MySQL server"
    Linux 安装 Mysql-5.7.23-linux-glibc2
    Promise
    PAT(B) 1094 谷歌的招聘(Java)
    PAT(B) 1074 宇宙无敌加法器(Java)
    PAT(B) 1078 字符串压缩与解压(Java)
  • 原文地址:https://www.cnblogs.com/Anani-leaf/p/5192042.html
Copyright © 2020-2023  润新知