华为机试(五)
一、
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的各种函数。正向、逆向、找某一个具体值,找不是的那个值。等等