C/C++程序题(21-25)
来源:互联网 发布:数据库基础pdf 编辑:程序博客网 时间:2024/05/16 00:54
21.
通过键盘输入100以内正整数的加、减运算式,请编写一个程序输出运算结果字符串。
输入字符串的格式为:“操作数1 运算符 操作数2”,“操作数”与“运算符”之间以一个空格隔开。
补充说明:
1. 操作数为正整数,不需要考虑计算结果溢出的情况。
2. 若输入算式格式错误,输出结果为“0”。
示例
输入:“4 + 7” 输出:“11”
输入:“4 - 7” 输出:“-3”
输入:“9 ++ 7” 输出:“0” 注:格式错误
#include<iostream>using namespace std;int calculate(char *input,int n){char *p=new char[n];char *q=new char[n];int j=0,m=0;for(int i=0;i<n;){while(1){p[j++]=input[i++];if(input[i]<'0'||input[i]>'9') break;}if(input[i]<'0'||input[i]>'9') break;}int num1=0;for(int i=0;i<j;i++){num1+=(p[i]-'0')*pow(10.0,j-i-1);}if(input[j]!=' '||input[j+2]!=' ') return 0;for(int k=j+3;k<n;){while(1){q[m++]=input[k++];if(input[k]<'0'||input[k]>'9') break;}if(input[k]<'0'||input[k]>'9') break;}int num2=0;for(int i=0;i<m;i++){num2+=(q[i]-'0')*pow(10.0,m-i-1);}int num3=0;if(input[j+1]='+') num3=num1+num2;else if(input[j+1]='-') num3=num1-num2; else return 0;return num3;}void main(){char *input=new char[100];cin.get(input,100);int n=strlen(input);int result=calculate(input,n);cout<<result<<endl;}
注:分别存取、转换(字符到整数)加数与被加数。
22.
IP地址匹配
问题描述:
在路由器中,一般来说转发模块采用最大前缀匹配原则进行目的端口查找,具体如下:
IP地址和子网地址匹配:
IP地址和子网地址所带掩码做AND运算后,得到的值与子网地址相同,则该IP地址与该子网匹配。
比如:
IP地址:192.168.1.100
子网:192.168.1.0/255.255.255.0,其中192.168.1.0是子网地址,255.255.255.0是子网掩码。
192.168.1.100&255.255.255.0 = 192.168.1.0,则该IP和子网192.168.1.0匹配
IP地址:192.168.1.100
子网:192.168.1.128/255.255.255.192
192.168.1.100&255.255.255.192 = 192.168.1.64,则该IP和子网192.168.1.128不匹配
最大前缀匹配:
任何一个IPv4地址都可以看作一个32bit的二进制数,比如192.168.1.100可以表示为:11000000.10101000.00000001.01100100,
192.168.1.0可以表示为11000000.10101000.00000001.00000000
最大前缀匹配要求IP地址同子网地址匹配的基础上,二进制位从左到右完全匹配的位数尽量多(从左到右子网地址最长)。比如:
IP地址192.168.1.100,同时匹配子网192.168.1.0/255.255.255.0和子网192.168.1.64/255.255.255.192,
但对于子网192.168.1.64/255.255.255.192,匹配位数达到26位,多于子网192.168.1.0/255.255.255.0的24位,
因此192.168.1.100最大前缀匹配子网是192.168.1.64/255.255.255.192。
请编程实现上述最大前缀匹配算法。
要求实现函数:
void max_prefix_match(const char *ip_addr, const char *net_addr_array[], int *n)
【输入】ip_addr:IP地址字符串,严格保证是合法IPv4地址形式的字符串
net_addr_array:子网地址列表,每一个字符串代表一个子网,包括子网地址和掩码,
表现形式如上述,子网地址和子网掩码用’/’分开,严格保证是
合法形式的字符串;如果读到空字符串,表示子网地址列表结束
【输出】n:最大前缀匹配子网在*net_addr_array[]数组中对应的下标值。如果没有匹配返回-1
示例
输入:
ip_addr = "192.168.1.100"
net_addr_array[] =
{
"192.168.1.128/255.255.255.192",
"192.168.1.0/255.255.255.0",
"192.168.1.64/255.255.255.192",
"0.0.0.0/0.0.0.0",
""
}
输出:n = 2
#include <iostream> #include<cmath> using namespace std; void max_prefix_match(const char *ip_addr,const char *net_addr_array[],int *n) { char num[4]; int n1=strlen(ip_addr); int q=0; long long s1=0; int p=3; for(int i=0;i<n1;i++)//将输入的IP地址转换成长整型 { if(ip_addr[i]=='.') { int t1=0; for(int j=0;j<q;j++) t1+=(num[j]-'0')*pow(10.0,q-j-1); s1+=t1*pow(256.0,p--); q=0; } else num[q++]=ip_addr[i]; } int temp=0; for(int j=0;j<q;j++) temp+=(num[j]-'0')*pow(10.0,q-j-1); s1+=temp;//加上D段,转换后的IP地址存于s1 int m=0; while(1) {n1=strlen(net_addr_array[m]); int k=0; long long s2=0,s3=0; q=0;p=3; for(int i=0;;i++) { if(net_addr_array[m][i]=='/') break; if(net_addr_array[m][i]=='.') { int t1=0; for(int j=0;j<q;j++) t1+=(num[j]-'0')*pow(10.0,q-j-1); s2+=t1*pow(256.0,p--); q=0; } else num[q++]=net_addr_array[m][i]; k++; } temp=0; for(int j=0;j<q;j++) temp+=(num[j]-'0')*pow(10.0,q-j-1); s2+=temp;//转换后的子网IP地址存于s2 q=0;p=3; for(int i=k+1;i<n1;i++) { if(net_addr_array[m][i]=='.') { int t1=0; for(int j=0;j<q;j++) t1+=(num[j]-'0')*pow(10.0,q-j-1); s3+=t1*pow(256.0,p--); q=0; } else num[q++]=net_addr_array[m][i]; } temp=0; for(int j=0;j<q;j++) temp+=(num[j]-'0')*pow(10.0,q-j-1); s3+=temp;//转换后的子网掩码存于s3 long long s4=0; if((s1&s3)==s2) { if(s3>s4) { s4=s3; *n=m; } } m++; if(net_addr_array[m]=="") break; } } void main() { int *n=new int; const char* ip_addr = "192.168.1.100"; const char *net_addr_array[] = { "192.168.1.128/255.255.255.192", "192.168.1.0/255.255.255.0", "192.168.1.64/255.255.255.192", "0.0.0.0/0.0.0.0", "" }; max_prefix_match(ip_addr,net_addr_array,n); cout<<*n<<endl; }
注:点分十进制IP地址:XXX.XXX.XXX.XXX 分为四段:A.B.C.D ——> 长整型:A*256^3+B*256^2+C*256+D
点分十进制IP转换成长整型:第一步,先把每段字符型数字转化为整型数字{(char-'0')*10的相应倍数再相加}
第二步,公式A*256^3+B*256^2+C*256+D
一个目的地址可能与多个表项匹配。最明确的一个表项,即子网掩码最长的一个,就叫做最长前缀匹配。
IP地址 点十分制转换成长整数型再与掩码的长整型进行&操作。
另:const 修饰函数参数,返回值,函数体 http://blog.csdn.net/youoran/article/details/8517611
1.用const 修饰函数的参数:const 只能修饰输入参数;如果参数作输出用,不论它是什么数据类型,也不论它采用“指针传递”还是“引用传递”,都不能加const 修饰,否则该参数将失去输出功能。
2.用const 修饰函数的返回值:如果给以“指针传递”方式的函数返回值加const 修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const 修饰的同类型指针。例如函数:const char * GetString(void); 正确的用法是 const char *str = GetString();(不可去掉const)
23.
数字排序
编写一个程序,实现排序算法,从小到大输出,数字间以逗号分隔,所有数字为非负整数。数目小于1028;
输入:1,6,3,5
输出:1,3,5,6
#include <iostream>#include <cmath>using namespace std; void main() { char *input=new char[100]; char *output=new char[100]; int *num=new int[100]; cin>>input; int n=strlen(input); char *temp=new char[10]; int m=0; for(int i=0;i<n;) { int k=0; while(i<n)//防止死循环 { temp[k++]=input[i++]; if(input[i]==',') { i++;//滤去',' break; } } num[m]=0; for(int j=0;j<k;j++) { num[m]+=(temp[j]-'0')*pow(10.0,k-j-1); } m++;//获取字符串中的数字 } //大小排序 int tp; for(int i=0;i<m;i++) { for(int j=1;j+i<m;j++) { if(num[i]>num[i+j]) { tp=num[i]; num[i]=num[i+j]; num[i+j]=tp; } } } int N=0; for(int i=0;i<m;i++)//将排序后的数字变成字符串输出 { int a[10],l=0,p=0; while(p=num[i]%10) { a[l++]=p; num[i]=num[i]/10; } for(int j=0;j<l;j++) { output[N++]=a[l-j-1]+'0'; } if(N<n) output[N++]=','; } for(int i=0;i<n;i++) cout<<output[i]; delete []input; delete []output; delete []num; delete []temp; }注:思路:先提取数字块(类比前面“块”的提取),字符转整型—>大小排序—>整型转字符—>输出字符串
24.
我们把只包含因子2,3,5的数称为丑数,把1当作第一个丑数,求从小到大的第n个丑数
输入:1都500之间的整数(包含1和500)
输出:第n个丑数。不在1-500输出-1
#include <iostream>using namespace std;bool ISUGLY(int number){while(number%2==0)number=number/2;while(number%3==0)number=number/3;while(number%5==0)number=number/5;if(number==1) return true;else return false;}int find(int n){if(n<1||n>500) return -1;int k=0;for(int i=1;;i++)//注意i的初始值,为0的话造成死循环{if(ISUGLY(i)){k++;if(k==n) return i;}}}void main(){int n;cin>>n;int ugly=find(n);cout<<ugly<<endl;}注:关键点是丑数判断函数!对2、3、5进行整除,如果最后能整除到底,返回true。这是遍历寻找法。
还有一种方法,比较难理解,但是运行时间短。其主要思想是只计算丑数,而不在非丑数的整数上花费时间。根据丑数的定义,丑数应该是另一个丑数乘以2、3或者5的结果(1除外)。因此我们可以创建一个数组,里面的数字是排好序的丑数。里面的每一个丑数是前面的丑数乘以2、3或者5得到的。
这种思路的关键在于怎样确保数组里面的丑数是排好序的。我们假设数组中已经有若干个丑数,排好序后存在数组中。我们把现有的最大丑数记做M。现在我们来生成下一个丑数,该丑数肯定是前面某一个丑数乘以2、3或者5的结果。我们首先考虑把已有的每个丑数乘以2。在乘以2的时候,能得到若干个结果小于或等于M的。由于我们是按照顺序生成的,小于或者等于M肯定已经在数组中了,我们不需再次考虑;我们还会得到若干个大于M的结果,但我们只需要第一个大于M的结果,因为我们希望丑数是按从小到大顺序生成的,其他更大的结果我们以后再说。我们把得到的第一个乘以2后大于M的结果,记为M2。同样我们把已有的每一个丑数乘以3和5,能得到第一个大于M的结果M3和M5。那么下一个丑数应该是M2、M3和M5三个数的最小者。
前面我们分析的时候,提到把已有的每个丑数分别都乘以2、3和5,事实上是不需要的,因为已有的丑数是按顺序存在数组中的。对乘以2而言,肯定存在某一个丑数T2,排在它之前的每一个丑数乘以2得到的结果都会小于已有最大的丑数,在它之后的每一个丑数乘以2得到的结果都会太大。我们只需要记下这个丑数的位置,同时每次生成新的丑数的时候,去更新这个T2。对乘以3和5而言,存在着同样的T3和T5。
#include <iostream>using namespace std; int min(int a,int b,int c) { if(a>b) a=b; if(a>c) a=c; return a; } void main() { int n; cin>>n; if(n<1||n>500) cout<<"-1"<<endl; int *p=new int[n]; p[0]=1; int a=0,b=0,c=0; for(int i=1;i<n;i++) { p[i]=min(2*p[a],3*p[b],5*p[c]);//每个丑数都是前面的丑数*2或*3或*5 if(p[i]==2*p[a]) a++; if(p[i]==3*p[b]) b++; if(p[i]==5*p[c]) c++; } cout<<p[n-1]<<endl; delete []p; }注:每个丑数都是前面的丑数*2或*3或*
25.
描述: 俗话说“条条道路通罗马”,我们要从数学上计算出到底有多少条路。已知有N个城市(N<=10),从0到9编号,城市间要么有一条路,要么没有路,请帮忙计算下从城市A到城市B之间到底有多少条路。
运行时间限制: 无限制
内存限制: 128 MByte
输入: 题目首先输入一行“N A B”(1 < N <= 10; 0 <= A,B <= 9; A != B),N表示有多少个城市,A标识从编号为A的城市出发,B标识目的城市。紧接着输入N行,每行包含N个数字,要么为0,要么为1,标识从该行编号标识的城市到其他所有城市是否有路。
输出: 一个整数,标识从A到B有多少条路
样例输入: 3 0 2
1 1 1
1 1 1
1 1 1
样例输出: 2
#include <iostream>using namespace std;void main(){int n,a,b;cin>>n>>a>>b;int **mat=new int*[n];int *visit=new int[n];int *que=new int[n];for(int i=0;i<n;i++){mat[i]=new int[n];visit[i]=0;}for(int i=0;i<n;i++)for(int j=0;j<n;j++)cin>>mat[i][j];int top=0,tail=0,num=0;que[tail++]=a;//起点入栈visit[a]=1;//起点标记为已访问状态while(tail!=top){int s=que[top++];for(int i=0;i<n;i++){if(mat[s][i]==1&&visit[i]==0&&i!=b){que[tail++]=i;visit[i]=1;}else if(mat[s][i]==1&&i==b)//找到一条路径,对b不作处理,继续遍历{num++;}}}cout<<num<<endl;delete []que;delete []visit;for(int i=0;i<n;i++){delete []mat[i];}}此方法是用广度优先搜索(BFS)来寻找路径,第一个寻找到的为最短路径,依次类推。此程序是用数组来实现队列。
直接使用queue结构,示例程序如下(可尝试下打印路径):
#include <iostream>#include <queue>using namespace std;void main(){int n,a,b;cin>>n>>a>>b;queue<int> que;int **mat=new int*[n];int *visit=new int[n];int *pre=new int[n];for(int i=0;i<n;i++){mat[i]=new int[n];visit[i]=0;}for(int i=0;i<n;i++)for(int j=0;j<n;j++)cin>>mat[i][j];que.push(a);//起点入栈visit[a]=1;int num=0;while(!que.empty()){int s=que.front();que.pop();//取出栈顶的值for(int i=0;i<n;i++){if(mat[s][i]==1&&visit[i]==0&&i!=b){que.push(i);visit[i]=1;}else if(mat[s][i]==1&&i==b){num++;}}}cout<<num<<endl;delete []visit;for(int i=0;i<n;i++)delete []mat[i];}
- C/C++程序题(21-25)
- c语言程序题
- C程序题1
- 程序积累(C)
- C程序(1)
- 聊天程序(C++)
- C程序(2)
- C 程序(3)
- C程序(4)
- c程序(6)
- C语言经典100题-程序21
- C/C++程序题(1-5)
- C/C++程序题(5-10)
- C/C++程序题(11-15)
- C/C++程序题(16-20)
- C/C++程序题(26-30)
- C面试宝典-(程序题)1
- C面试宝典-(程序题)2
- Leetcode 110. Balanced Binary Tree
- mysql创建用户和授权的三种方式
- tomcat、servlet学习
- 【spark source】Spark LinearRegression源码解读
- android view 动画学习
- C/C++程序题(21-25)
- 求四个数的最大公约数
- 电脑眼睛保护色
- BZOJ_P1467/POJ_P3243 Clever Y(扩展BSGS+哈希)
- 面向对象OO 设计、架构终极理解, 以及如何学习一个领域
- HDU 1213 How Many Tables(并查集)
- 整数拆分问题
- STL容器的实现原理
- HDU 1064 Financial Management