目录
一.求二进制位中数字1的个数
1.算法一
2.算法二
3.算法三
二.打印一个十进制数的二进制位的奇偶位(牛客网)
结束
三.结构体
1.结构体类型的两种声明方式
2.结构体变量的初始化
3.结构体类型中结构成员的访问
4.结构体变量的值传递和址传递
模2余2法
int Calc_late(unsigned int a)//值传递a,进入函数体
{
int count = 0;//统计数字1的个数
while (a)//当a=0即为假时结束循环
{
if (a % 2 == 1)
{
count++;
}
a /= 2;
}
return count;//返回计数器,即为十进制数字转化为二进制后二进制位1的个数
}
模2余2法解释,举例:
例如十进制数字1231:
①.123%2==1,count++,123/2==61
②.61%2==1,count++,61/2==30
③.30%2==0;count不变,30/2==15
④.……
直到a==0停止循环,count则统计了数字1的个数
注意点:
unsigned int a,传值进去时a应当被看做无符号数,符数再内存中的存储方式为补码,例如:统计十进制-1二进制位中数字1的个数:
-1补码:11111111111111111111111111111111,若将其当作有符号数,程序进入第一次循环时-1/2==0!=1,count==0,-1/2==0结束循环,返回count=0出错,将其看作无符号数则将这一问题解决,适用于正负数统计
按位与(&)法:
int Calc_late( int a)
{
int count = 0;
for (int i = 0; i < 32; i++)
{
if ((a & 1) == 1)//&:有假则假
{
count++;
}
a >>= 1;每进行一次判断语句,(a>>1)&1
}
return count;
}
主要点:按位与(&),移位(>>)
一个整型占4个字节,32个比特位,循环体设置i<32,共进行32次循环,将32个比特位的0/1序列全都各自&1,判断其结果是否为1,若为1,说明判断数字的二进制位最后一位为1,若为1,计数器++;然后a>>1,继续进入执行循环体,直到循环结束,负数补码存储并不受影响,因此此处不需要用无符号数
举例:a=13
13的二进制序列为00000000000000000000000000001101,1的二进制序列为00000000000000000000000000000001。
①第一次循环,13&1==1,count++;
②13>>1二进制序列变为00000000000000000000000000000110(末尾舍弃,首位补0),(a>>1)&1==0!=1,count不变,
③……依次循环32次,a>>1共进行31次即可得出count的值
按位与(&)法
int Calc_late( int a)
{
int count = 0;
while (a)
{
a = a & (a - 1);//一个十进制数每与该数减一进行按位与的结果的数的二进制位上的数字1的个数减一
count++;//每减少一位,count+1,当a=0时结束
}
return count;
}
原理:一个十进制数每与该数减一进行按位与的结果的数的二进制位上的数字1的个数减一,知道该数变为0时,结束循环。相对于前两种算法效率更高
void Print(int a)
{
printf("偶数位为:");
for (int i = 32; i >= 1; i -= 2)
{
printf("%d ", (a>>(i-1)) & 1);
}
printf("\n奇数位为:");
for (int i = 31; i >= 0; i -= 2)
{
printf("%d ", (a>>(i-1)) & 1);
}
}//下边进行解释
原理:传值传递a到函数体内,首先看偶数位的打印
由于要求顺序输出奇偶位,所以此处for循环设置为负向,一个整型,4个字节,32个比特位,每个比特位存放相应的0/1序列,要打印偶数位的序列,不妨设想把每一个偶数位都移位到末尾上,将移位后的二进制&上十进制1,结果便得到末尾上的数字。奇数同理。
a.
第一种声明方式:
struct Stu//创建了一个结构体类型。struct Stu称为结构体类型,struct成为结构体关键字,Stu称为结构体标签,下列大括号内的变量称为成员列表
{
char name[20];//姓名
char sex[3];//性别
int ID;//学号
int age;//年龄
};
int main()
{
struct Stu s1;//结构体变量的创建方式①
return 0;
}
第二种声明方式:
typedef struct Stu//typedef起到将结构体类型重命名的作用
{
char name[20];
char sex[3];
int ID;
int age;
}Stu;//此处的Stu即为结构体类型的新名字
int main()
{
Stu s1;//结构体变量的创建方式②
return 0;
}
两种声明方式的注意事项:首先是声明不占用内存空间,创建变量时才开辟储存空间;其次,结构体中成员列表中变量可以是不同类型的变量
a.简单结构体的初始化
采用第一种声明方式时:
初始化时写:struct Stu s1{"韩信","男",2109066666,20};
采用第二种声明方式时:
初始化时写:Stu s1 = {"韩信","男",2109066666,20};
b.嵌套结构体的初始化
typedef struct Stu
{
char name[20];
char sex[3];
int ID;
int age;
}Stu;
typedef struct Tur
{
char love[20];
struct Stu s;
char* p;//嵌套结构体变量
}Tur;
int main()
{
char arr[]="hvgsh";
Tur s1 = { "她",{"韩信","男",21666666,20},arr};//初始化Tur结构体变量时在大括号内用大括号初始化Stu结构体变量
return 0;
}
结构变量初始化注意事项:
.格式:{ }将要初始化的变量的内容收纳,字符串类型成员变量初始化要用” “,字符类型变量初始化用‘ ’,整形直接初始化即可。嵌套初始化时,将结构体类型中成员变量有结构体类型的变量的变量用{ }再次在结构体变量的初始化括号内初始化。
Tur s1 = { "她",{"韩信","男",21666666,20},arr};
Stu s2 = { "小明","男",21666666,20 };
printf("%s\n", s1.s.name);//通过访问结构成员操作符s1.找到Tur结构体类型中的成员变量s,而s又是结构体成员变量,再次s.访问Stu结构体类型中的结构成员
printf("%s\n%s\n", s2.name,s1.s.name);
printf("%s\n", s1.p);//s1.进入结构体变量中找到*p从而找到char arr并访问
printf("%d\n", pi->s.age);//第二种访问方式(->),Tur* pi=&s1;访问时即可使用上述操作符
结构体类型中结构成员的访问的注意事项:
访问结构成员操作符的两种使用方法,对应结构体类型的成员变量的类型.
#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable:6031)
#include
typedef struct Stu
{
char name[20];
char sex[3];
int ID;
int age;
}Stu;
void Print1(Stu temp)
{
printf("姓名:%s\n", temp.name);
printf("性别:%s\n", temp.sex);
printf("学号:%d\n", temp.ID);
printf("年龄:%d\n", temp.age);
}
void Print2(Stu* ps)
{
printf("姓名:%s\n", ps->name);
printf("性别:%s\n", ps->sex);
printf("学号:%d\n", ps->ID);
printf("年龄:%d\n", ps->age);
}
int main()
{
Stu s1 = { "李明","男",666666,20 };
Print1(s1);
Print2(&s1);
return 0;
}
说明:Print1函数进行的是值传递,Print2函数进行的是址传递 ;应当注意形参的类型,进行值传递时形参为结构体变量类型即可,通常用”.“对成员变量进行访问;进行址传递时,形参应为指针类型,通常用”->“对成员变量进行访问。