高等程序设计2020-2021夏季小学期训练
问题描述
一个IP地址由32位二进制的数组成,比如:
111111111111111111111111000000002
为了便于记忆,我们将8个二进制位用一个十进制数表示,一个IP地址由四个十进制数表示,上述的IP地址表示为:
255.255.255.0
现在给你一个上述形式的IP地址,请回答IP地址的32个二进制位中,有多少位是1。
如IP地址为255.255.255.0,其中24位是1。
输入形式
有多组测试数据。
测试数据第一行是一个正整数T,表示测试数据组数。
每组测试数据是一个IP地址,形式为:
IP1.IP2.IP3.IP4
其中0 ≤IP1,IP2,IP3,IP4≤ 255,用十进制表示。每个IP地址不保证是实用IP地址。
40%的测试数据组数T 10≤T≤ 102;
30%的测试数据组数T 102≤T≤ 103;
20%的测试数据组数T 103≤T≤ 104;
10%的测试数据组数T 104≤T≤ 105;
输出形式
对于每个IP地址,输出一行包含一个非负整数:该IP地址的32个二进制位中,1的位数。
样例
【样例输入】
5
255.255.255.0
127.0.0.1
0.0.0.1
1.2.3.4
0.0.0.0
【样例输出】
24
8
1
5
0
提示:样例中32位的IP地址为:
111111111111111111111111000000002
011111110000000000000000000000012
000000000000000000000000000000012
000000010000001000000011000001002
000000000000000000000000000000002
思路分析
输入的时候将数据定义为string类型,解题的时候大致是以下几个步骤。
1:从string中提取数字
2:将提取出的数字转化为二进制
3:判断二进制中有多少个1
库函数的使用可以使得代码变得更精简。
代码展示
#include<bits/stdc++.h>
using namespace std;
int getNum(int num)
{
int sum=0;
char ch[8];
for(int i=0;i<8;i++)
ch[i]=0;
itoa(num,ch,2);
for(int i=0;i<8;i++)
{
if(ch[i]=='1')
sum++;
}
return sum;
}
int main()
{
int T;
cin>>T;
for(int m=0;m<T;m++)
{
string s;
cin>>s;
int num=0;
int sum=0;
vector<char>a;
for(int j=0;j<s.length();j++)
{
if(s[j]!='.')
{
num=num*10+(s[j]-'0');
}
else
{
sum+=getNum(num);
num=0;
}}
sum=sum+getNum(num);
cout<<sum<<endl;
}
}
注意
小生在学校的测试系统上提交时,由于学校系统编译器版本的原因,对于库函数itoa()会报错。该函数是将十进制数转化为指定进制,返回类型是字符类型。但是在本地DEV上可以正常运行通过。如果有需要的话,可以自己定义一个函数将其替换掉,补充如下。
string ItoA(int n,int m) //n是待转数字,m是指定的进制
{
string ans="";
do{
int t=n%m;
if(t>=0&&t<=9) ans+=t+'0';
else ans+=t-10+'a';
n/=m;
}while(n!=0); //使用do{}while()以防止输入为0的情况
reverse(ans.begin(),ans.end());
return ans;
}