华为机试(五)

一、

1、

编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串。但是要保证汉字不被截半个,如"我ABC"4,应该截为"我AB",输入"我ABC汉DEF"6,应该输出为"我ABC"而不是"我ABC+汉的半个"。 

入描述:

输入待截取的字符串及长度

输出描述:

截取后的字符串

示例1

输入

我ABC汉DEF
6

输出

我ABC
1、1
#include<iostream>
#include<string>
using namespace std;
int main()
{
    string str;
    int num;
    while(cin >> str >> num)//换用getline(cin,str)后就会受到流输入的影响。
    {
        cout<<str.length()<<endl;
        cout << str.substr(0, num) << endl;
    }
    return 0;
}

 可以看出一个汉字占两个字节,一个字母占1个字节。string已经自动将半个汉字减去了。  

#include<iostream>
#include<string>
using namespace std;
int main()
{
    string str;
    int num;
    while(cin >> str >> num)
    {
    	string s;
    	for(int i=0;i<str.length();i++)
    	{
    	    if(str[i]<'0'||str[i]>'9')
    	    {
    	    	s+=str[i];
			}
        }
        cout <<s.substr(0,num) << endl;
    }
    return 0;
}

2、题意理解不一样,上面是是先去除了数字再输出,下面是先获取了长度。再去除汉字。

#include<iostream>
#include<string>
#include<cmath>

using namespace std;
int main()
{
	string str; 
	int n;
	while(cin>>str>>n)  
	{
		string s;
		s=str.substr(0,n); 
		for(int i=0;i<s.length();i++)
		{
			if(str[i]<'1' || str[i]>'9')
			{
				cout<<s[i];
			}
		}
		cout<<endl; 
	}
	return 0;
} //我ABC123的def 

 

二、

#include<iostream>  
#include<vector>  
#include<string>  

using namespace std; 

int month_num[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};//月份天数 

int main()
{
	int y,w;//距离90年的年数,w,具体的星期 
	while(cin>>y>>w)
	{
		int week_num[7]={0};
		//int k=0;//1900年1月13日 星期六 
	    if(y>0&&y<=400)
		{
			
			
			int k=0;//1900年1月13日 星期六 
			
			for(int i=0;i<y;i++)//年数循环 
			{
				month_num[2]=28;
			    int year=1900+i;
			    if(((year%100)!=0 && (year%4)==0)||(year%400==0)) //判断 平,闰年 
			        month_num[2]=29;
				for(int j=1;j<=12;j++)//月数循环 
				{
					if(j==12)
					{
						//cout<<k<<" ";
						week_num[k]++;
						k=(k+31%7)%7; //下个月的星期数 
					}
					else
					{
						//cout<<k<<" ";
					    week_num[k]++;//本月加1; 
					    k=(k+month_num[j]%7)%7;	
					}   
				} 
			}
		}
		else
		{
		    cout<<-1;	
		}	
		for(int i=0;i<7;i++)
		    cout<<week_num[i]<<" ";
		cout<<endl;
	} 
	return 0; 
}

 

三、

 1、格式化输出

#include <iostream>  
#include <fstream>  
#include <iomanip>  
//用setprecision(n)设置精度,其中n表示精确到小数点后n位  
using namespace std;  
  
void main()  
{  
    double aa = 10;  
    cout<<"     12345.0普通输出为:"<<12345.0<<endl;//输出12345  
    cout<<fixed<<setprecision(8)<<"          10保留8位有效数字输出为:"<<aa<<endl;  
    //fixed:表示普通方式输出,不采用科学计数法。fixed也可以放在setprecision(n)后面  
    cout<<"     12345.0保留8位有效数字输出为:"<<12345.0<<endl;  
    cout<<fixed<<setprecision(2)<<"    -123.456保留2位有效数字输出为:"<<-123.456<<endl;  
  
    cout << setprecision (4); // 精度  
    cout.setf(ios::fixed,ios::floatfield); // 定点格式  
    cout << "123.45678901保留4位有效数字输出为:"<< 123.45678901<<endl;  
  
    printf("     %2.4f保留2位有效数字输出为:%2.2f
",11.1191,11.1191);  
  
    system("pause");  
}  

#include<iostream>  
#include<vector>  
#include<string>  
#include <iomanip>

using namespace std; 

int main()
{
	double aa;
	aa=(double)4/8;
	cout<<aa<<endl;
	double n=6;
	cout<<fixed<<setprecision(8)<<n<<endl;//必须得用fixed,否则不会保留小数 
	cout<<setprecision(5)<<aa<<endl; 
	double b=(double)6/7;
	cout<<b<<endl;
	printf("%2.6f
",b); //   
换行 
}  

2、

解题思路: 
第一步,确定问题解的表达式。可将f(n, s) 表示n个骰子点数的和为s的排列情况总数。 
第二步,确定状态转移方程。n个骰子点数和为s的种类数只与n-1个骰子的和有关。因为一个骰子有六个点数,那么第n个骰子可能出现1到6的点数。所以第n个骰子点数为1的话,f(n,s)=f(n-1,s-1),当第n个骰子点数为2的话,f(n,s)=f(n-1,s-2),…,依次类推。在n-1个骰子的基础上,再增加一个骰子出现点数和为s的结果只有这6种情况!那么有:

f(n,s)=f(n-1,s-1)+f(n-1,s-2)+f(n-1,s-3)+f(n-1,s-4)+f(n-1,s-5)+f(n-1,s-6) ,0< n<=6n 
f(n,s)=0, s< n or s>6n

上面就是状态转移方程,已知初始阶段的解为: 
当n=1时, f(1,1)=f(1,2)=f(1,3)=f(1,4)=f(1,5)=f(1,6)=1。

#include <stdio.h>
#include <string.h>
#include<cmath>
#include <iostream>
#include<iomanip>//格式化输出的库
using namespace std;

/****************************
func:获取n个骰子指定点数和出现的次数
para:n:骰子个数;sum:指定的点数和
return:点数和为sum的排列数
****************************/
int getNSumCount(int n, int sum)
{
    if(n<1||sum<n||sum>6*n)
	{
        return 0;
    }
    if(n==1)
	{
        return  1;
    }
    int resCount=0;
    resCount=getNSumCount(n-1,sum-1)+getNSumCount(n-1,sum-2)+
             getNSumCount(n-1,sum-3)+getNSumCount(n-1,sum-4)+
             getNSumCount(n-1,sum-5)+getNSumCount(n-1,sum-6);
    return resCount;
}

//验证
int main()
{
    int n=0; 
    while(true)
	{
        cout<<"input dice num:";
        cin>>n;
        int S=pow(6,n);
cout<<"["; //格式化输出 for(int i=n;i<6*n;++i) cout<<"["<<i<<","<<setprecision(5)<<(double)getNSumCount(n,i)/S<<"]"<<","; cout<<"["<<n*6<<","<<setprecision(5)<<(double)getNSumCount(n,n*6)/S<<"]"; cout<<"]"<<endl; } }

使用递归的方式,重复了太多的计算,改为递推如下。

3、递推其实是将各个值存储起来,遇到了直接调用,不用再重新计算,而C++动态分配空间的功能相比其他语言,并不是那么强。

通过new来动态分配空间。

#include<iostream>

#include<cstring>

using namespace std;

int main()
{    
	//char* p=new char("Hello"); //error分配一个char(1字节)的空间,//用"Hello"来初始化,这明显不对    
	char* p=new char[6];    
	//p="Hello";                 
	//不能将字符串直接赋值给该字符指针p,原因是:                                 
	//指针p指向的是字符串的第一个字符,只能用下面的                                 
	//strcpy    
	strcpy(p,"Hello");    
	cout<<*p<<endl;   //只是输出p指向的字符串的第一个字符!    
	cout<<p<<endl;     //输出p指向的字符串!    
	delete[] p;       //清除空间
return 0; }

memset:

memset 函数是内存赋值函数,用来给某一块内存空间进行赋值的。 其原型是:void* memset(void *_Dst, int  _Val, size_t _Size)

_Dst是目标起始地址,_Val是要赋的值,_Size是要赋值的字节数。所以,在memset使用时要千万小心,在给char以外的数组赋值时,只能初始化为0或者-1。

#include<iostream>
#include <typeinfo> 
#include<string.h>

using namespace std;

int main() 
{ 	
    int num[8];
    memset(num,0,8*sizeof(int));
    for(int i=0;i<8;i++)
    {
    	cout<<num[i]<<" ";
	}
}   

#include<iostream>
#include <typeinfo> 
#include<string.h>

using namespace std;

int main() 
{ 	
    int num[8];
    memset(num,1,8*sizeof(int));
    for(int i=0;i<8;i++)
    {
    	cout<<num[i]<<" ";
	}
}   

赋值为1时出现异常情况

#include<iostream>
#include <typeinfo> 
#include<string.h>

using namespace std;

int main() 
{ 	
    int num[8];
    memset(num,-1,7*sizeof(int));
    for(int i=0;i<8;i++)
    {
    	cout<<num[i]<<" ";
	}
}   

#include<iostream>
#include<string.h>

using namespace std;

int main() 
{ 
    int num[3][8];
    memset(num,-1,24*sizeof(int));
    for(int i=0;i<3;i++)
    {
    	for(int j=0;j<8;j++)
		    cout<<num[i][j]<<" ";
		cout<<endl;
	}
}   

数组赋值。

#include<iostream>
#include<string.h>

using namespace std;

int main() 
{ 
    int n;
    while(cin>>n)
    {
	    int num[n][n*6];
	    memset(num,0,n*n*6*sizeof(int));//矩阵赋初值 
	    for(int i=0;i<n;i++)
	    {
	    	for(int j=0;j<n*6;j++)
			    cout<<num[i][j]<<" ";
			cout<<endl;
		}
    }
}   

3、极简单的递推程序

#include<iostream>
#include<cmath>
#include<string.h> 

using namespace std;

/****************************************
func:给定骰子数目n,求所有可能点数和的种类数
para:n:骰子个数;count:存放各种点数和的种类数,下标i表示点数和为(i+n)
return:出错返回-1,成功返回0
****************************************/
int getNSumCountNotRecusion(int n, int* count)
{
    if(n<1)
        return -1;
    //初始化最初状态
    count[0]=count[1]=count[2]=count[3]=count[4]=count[5]=1; //初始转态 
    if(n==1) 
	    return 0;

    for(int i=2;i<=n;++i)//从2开始,3开始, 
	{
        for(int sum=6*i;sum>=i;--sum)  //从高向地处覆盖 从12到2,从18到3 
		{
            int tmp1=((sum-1-(i-1))>=0?count[sum-1-(i-1)]:0); //上一阶段点数和sum-1的排列总数
            int tmp2=(sum-2-(i-1)>=0?count[sum-2-(i-1)]:0);
            int tmp3=(sum-3-(i-1)>=0?count[sum-3-(i-1)]:0);
            int tmp4(sum-4-(i-1)>=0?count[sum-4-(i-1)]:0);
            int tmp5=(sum-5-(i-1)>=0?count[sum-5-(i-1)]:0);
            int tmp6=(sum-6-(i-1)>=0?count[sum-6-(i-1)]:0);
            count[sum-i]=tmp1+tmp2+tmp3+tmp4+tmp5+tmp6;
            cout<<sum-i<<" "<<count[sum-i]<<endl;
        }
    }
    return 0;
}

//验证
int main()
{
    int n;
    while(true)
	{
        cout<<"iteration input dice num:";
        cin>>n;
        int* count=new int[5*n+1];
        cout<<count<<endl;
        memset(count,0,(5*n+1)*sizeof(int));//全部赋值为0; 
        getNSumCountNotRecusion(n,count);
        int allCount=0;
        for(int i=0;i<5*n+1;++i)
		{
            cout<<"f("<<n<<","<<i+n<<")="<<count[i]<<endl;
            //allCount+=count[i];
        }
        delete[] count;     
    }
}

可以看到整个的计算过程。

4、生成n行n*6列的矩阵存放f(n,m)的值,n:骰子数目,m:点数和。f(n,m)出现的次数。

 四、

题目描述

实现删除字符串中出现次数最少的字符,若多个字符出现次数一样,则都删除。输出删除这些单词后的字符串,字符串中其它字符保持原来的顺序。 

输入描述:

字符串只包含小写英文字母, 不考虑非法输入,输入的字符串长度小于等于20个字节。

输出描述:

删除字符串中出现次数最少的字符后的字符串。

示例1

输入

abcdd

输出

dd

 1、

#include <iostream>
#include <string>
using namespace std;

int main()
{
    int i, m,min;
    int a[26]={0};
    string str,temp;
    while (cin >> str)
    {
        m = str.size();
        for (i = 0; i<m; i++)
        {
        	a[str[i]-'a']++;//对每个字母次数统计 
		}
            
        min = a[str[0]-'a'];//假设最小值
		 
        for (i = 0; i<m; i++)
        {
        	if (a[str[i] - 'a'] <= min)
                min = a[str[i]-'a'];    //找到最小的次数 
		} 
        
        for (i = 0; i < m; i++)
        {
		    if (a[str[i] - 'a'] > min)//输出比最小值大的数 
                cout << str[i];
		} 
        cout << endl;
    }  
    return 0;
}

五、

 

#include<iostream>   
#include<string>  

using namespace std; 

int main()
{
	string str;
	while(cin>>str)   //循环输入
	{
		int Num[10]={0};
		string s;
		for(int i=0;i<str.length();i++)
		{
			if(Num[str[i]-'0']==0)  //判断0~9数字如果是0,添加到s,并加1,为后面判断做准备
			{
				s+=str[i];
			}
			Num[str[i]-'0']++;
		}
		
		int flag=0,n;//flag是最后逆向去0的标志,n是最后s的个数
		for(int i=s.length()-1;i>=0;i--)
		{
			if(s[i]!='0')
			{
			    flag=1;
			    n=i;
			    break;
		    }
		}
		for(int i=n;i>=0;i--)
		{
			cout<<s[i];
		}
		cout<<endl;
	}
	return 0;
}//98766730

六、

#include<iostream>
#include<string>
#include<algorithm>
#include<cmath>


using namespace std; 

int main()
{
	double t;
	while(cin>>t)
	{
		double c;
		if(t>=-400 && t<0)
		{
			c=(double)(1700/170)*(t+170)-1000;
		}
		else if(t>=0 && t<40)
		{
			c=700+(double)6*(t);
		}
		else if(t>=40 && t<300)
		{
			c=(double)940+(t-40)*6;
		}
		else if(t>=300 && t<1000)
		{
			c=2500+(double)20*(t-300);
		}
		
		
		else if (c<-400)
		{
			c=-3300;
		}
		else 
		{
			c=16500;
		}
		cout<<c<<endl;	
	}
	return 0;
}

 七、

1、vector 和结构体的结合

#include<iostream>
#include<vector>

using namespace std;

struct Ini
{
    string Sec;
	string Key;
	string Value;	
}; 

int main()
{
	Ini a[3];
	a[0].Sec="section1";
	a[0].Key="key2";
	a[0].Value="value2";
	
	a[1].Sec="section2";
	a[1].Key="key1";
	a[1].Value="value1";
	
	a[2].Sec="section1";
	a[2].Key="key1";
	a[2].Value="value1";
	
	vector<Ini> Str;
	for(int i=0;i<3;i++)
	{
		Str.push_back(a[i]);
	}
	for(int i=0;i<3;i++)    
	{
		cout<<Str[i].Sec<<" "<<Str[i].Key<<" "<<Str[i].Value<<endl;
	}	
}

2、排序

#include<iostream>
#include<vector>
#include <algorithm>  

using namespace std;

struct Ini
{
    string Sec;
	string Key;
	string Value;	
}; 

bool compare(const Ini& st1,const Ini& st2)  //自定义的比较排序函数 
{  
    if(st1.Sec!=st2.Sec)
    {
    	return st1.Sec<st2.Sec;
	}
	else
	{
		return st1.Key<st2.Key;
	}     
}  

int main()
{
	Ini a[4];
	a[0].Sec="section1";
	a[0].Key="key2";
	a[0].Value="value2";
	
	a[1].Sec="section2";
	a[1].Key="key1";
	a[1].Value="value1";
	
	a[2].Sec="section1";
	a[2].Key="key1";
	a[2].Value="value1";
	
	a[3].Sec="section2";
	a[3].Key="key0";
	a[3].Value="value0";
	
	vector<Ini> Str;
	for(int i=0;i<4;i++)
	{
		Str.push_back(a[i]);
	}
	
	sort(Str.begin(),Str.end(),compare);//vector 中有多个键值时,得自定义比较函数 
	
	for(int i=0;i<4;i++)    
	{
		cout<<Str[i].Sec<<" "<<Str[i].Key<<" "<<Str[i].Value<<endl;
	}	
}

当vector中有多个值时,sort比较函数需要自己添加。

3、按格式提取数据

3.1去除注释

#include<iostream>
#include<string.h>
#include<cmath> 
using namespace std;

string DeletExp(string s)
{
	string a;
	int n,m;
	n=s.find(';');//找到位置
	a=s.substr(0,n);//获取字符串
	return a; 
}

int main() 
{ 
    string str;
    while(getline(cin,str))
	{
		string a;
	    a=DeletExp(str);
		cout<<a<<endl;	
	} 
} //
/*
[section1] dagd;test
;test case
[section1];test
*/

3.2提取字符

#include<iostream>
#include<string.h>
#include<cmath> 
using namespace std;

string DeletExp(string s)
{
	string a;
	int n,m;
	n=s.find(';');
	a=s.substr(0,n);
	return a; 
}

int main() 
{ 
    string str;
    while(getline(cin,str))
	{
		string a;
	    a=DeletExp(str);
		int k1,k2,d;
		string sec,key,val;
		k1=a.find('[');
		k2=a.rfind(']');
		d=a.find('=');
		if(k2==-1)
		{
			key=a.substr(0,d);
			val=a.substr(d+1,a.length()-d);
			
			cout<<key<<" "<<val<<endl;
		}
		else
		{
			sec=a.substr(k1+1,k2-1);
			cout<<sec<<endl;
		}
	} 
} 
/*
;test case
[section1];test
ke2=value2
key1=value1
*/

3.3 去除首尾空格

#include <iostream>
#include <string>
using namespace std;

//去掉首尾空格
string ClearHeadTailSpace(string str)   
{  
	if (str.empty()) //为空则返回原字符串   
	{  
	    return str;  
	}  
	
	str.erase(0,str.find_first_not_of(" "));  
	str.erase(str.find_last_not_of(" ") + 1);  
	return str;  
}  

//去掉字符串中的全部空格
string ClearAllSpace(string str)
{
    int index = 0;
    if( !str.empty())
    {
        while( (index = str.find(' ',index)) != string::npos) //没有找到的话就会返回npos 
        {
            str.erase(index,1);
        }
    }
    return str;
}




int main()
{
	string str = "  123   456  789   ";
	
	cout << ClearHeadTailSpace(str) << endl;
	cout << ClearAllSpace(str) << endl;
	
	return 0;
}

4、

4.1首先将数据存入容器

#include <iostream>
#include <string>
#include<vector>

using namespace std;

int main()
{
    vector<int> vec;
    int n;
	while(cin>>n)
	{
	  	vec.push_back(n);
	}	
	for(int i=0;i<vec.size();i++)
	{
		cout<<vec[i]<<" ";
	}
}

#include <iostream>
#include <string>
#include<vector>

using namespace std;

int main()
{
    vector<string> vec;
    string str;
	while(getline(cin,str))
	{
	  	vec.push_back(str);
	}	
	for(int i=0;i<vec.size();i++)
	{
		cout<<vec[i]<<endl;
	}
}

5、整合一块

#include <iostream>
#include <string>
#include<vector>
#include <algorithm>  

using namespace std;

struct Ini     //结构体,按要求输出的每一行的内容 
{
    string Sec;
	string Key;
	string Value;	
}; 

string DeletExp(string s) //去除注释 
{
	string a;
	int n,m;
	n=s.find(';');
	a=s.substr(0,n);
	return a; 
}

string ClearHeadTailSpace(string str)  //去除首尾空格 
{  
	if (str.empty()) //为空则返回原字符串   
	{  
	    return str;  
	}  
	str.erase(0,str.find_first_not_of(" "));  
	str.erase(str.find_last_not_of(" ") + 1);  
	return str;  
}  

bool compare(Ini st1,Ini st2)  //自定义的比较排序函数 
{  
    if(st1.Sec!=st2.Sec)
    {
    	return st1.Sec<st2.Sec;
	}
	else
	{
		return st1.Key<st2.Key;
	}     
}  

int main()
{
    vector<string> vec;
    string str;
	while(getline(cin,str)) //初始数据装入容器 
	{
	  	vec.push_back(str);
	}
	
	vector<Ini> V;
	Ini Q;	
	for(int i=0;i<vec.size();i++)
	{
		string a;
	    a=DeletExp(vec[i]);
	    if(a.empty()) //为空,继续 
		{
		    continue;	
		} 
		else //不为空的情况 
		{
			int k1=0,k2=0,d;
			string sec,key,val;
			k1=a.find('[');
			k2=a.rfind(']');//没找到会返回-1 
			d=a.find('=');
			
			if(k2!=-1)
			{
				sec=ClearHeadTailSpace(a.substr(k1+1,k2-1));   //section
				Q.Sec=sec;
			}
			
			else
			{
				key=ClearHeadTailSpace(a.substr(0,d));   //key
				val=ClearHeadTailSpace(a.substr(d+1,a.length()-d));  //value 
				Q.Key=key;
			    Q.Value=val;
			    V.push_back(Q);  //将清洗后的数据加入容器V中 
			}			
	    }
    }
    
    for(int i=0;i<V.size();i++)    
	{    
		cout<<V[i].Sec<<" "<<V[i].Key<<" "<<V[i].Value<<endl;
	}	
	
	cout<<endl; 
	sort(V.begin(),V.end(),compare);//vector中有多个键值时,得自定义比较函数
	
	for(int i=0;i<V.size();i++)    
	{    
		cout<<"{"<<V[i].Sec<<"}{"<<V[i].Key<<"}{"<<V[i].Value<<"}"<<endl;
	}	
}
/*
;test case
[section1];test
key2 = value2
key1 = value1
[section2]
key2 = value2
key0 =value0
*/

 总结:考察知识点

1、结构体和vector的组合。结构体用来存放三个值,然后一起存入vector中。

2、利用sort排序,注意自己手写判断条件。

3、按要求读取中string.find的各种函数。正向、逆向、找某一个具体值,找不是的那个值。等等

原文地址:https://www.cnblogs.com/ruo-li-suo-yi/p/8878162.html