华为机试(五)
一、
1、
编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串。但是要保证汉字不被截半个,如"我ABC"4,应该截为"我AB",输入"我ABC汉DEF"6,应该输出为"我ABC"而不是"我ABC+汉的半个"。
入描述:
输入待截取的字符串及长度
输出描述:
截取后的字符串
输入
我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\n",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\n",b); // \n换行
}

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个字节。
输出描述:
删除字符串中出现次数最少的字符后的字符串。
输入
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的各种函数。正向、逆向、找某一个具体值,找不是的那个值。等等
浙公网安备 33010602011771号