目录
3. 输入5个学生各5科成绩,输出5个学生各5科成绩及总分。
7.计算1/1-1/2+1/3-1/4+1/5 …… + 1/99 - 1/100 的值
18.写一个函数,每调用一次这个函数,就会将 num 的值增加1
20.编写一个print函数把num的每一位按照顺序打印出来
25.写一个递归函数DigitSum(n),输入一个非负整数,返回组成它的数字之和
30.将数组A中的内容和数组B中的内容进行交换(数组一样大)
34.编写代码实现:求一个整数存储在内存中的二进制中1的个数
35.C语言中C99之前没有表示真假的类型 C99中引用了布尔类型
49.写一个函数打印arr数组的内容,不使用数组下标,使用指针
1.static
#include <stdio.h>
int sum(int a) //8, 10, 12, 14, 16,
{
int c = 0;
static int b = 3;
c += 1;
b += 2;
return (a + b + c);
}
int main()
{
int i;
int a = 2;
for (i = 0; i < 5; i++)
{
printf("%d", sum(a));
}
}
结果:8, 10, 12, 14, 16
2.根据公式计算m的值
其中 max3函数为计算三个数的最大值,如: max3(1, 2, 3) 返回结果为3。
#include<stdio.h>
int max3(int a, int b, int c)
{
int max = a;
if (max < b)
max = b;
if (max < c)
max = c;
return max;
}
int main() {
int a=0, b=0, c=0;
double m=0.0;
scanf("%d %d %d", &a, &b, &c);
m = max3(a + b, b, c) * 1.0 / (max3(a, b + c, c) + max3(a, b, b + c));
printf("%.2lf", m);
return 0;
}
3. 输入5个学生各5科成绩,输出5个学生各5科成绩及总分。
循环
int main()
{
int i, j;
double a;
double sum;
for (i = 0; i < 5; i++)
{
sum = 0.0;
for (j = 0; j < 5; j++)
{
scanf("%lf", &a);
sum += a;
printf("%.1f ", a);
}
printf("%.1f\n", sum);
}
}
数组
int main()
{
float arr[5][6];
int i, j;
for (i = 0; i < 5; i++)
{
float sum = 0;
for (j = 0; j < 5; j++)
{
scanf("%f", &arr[i][j]);
sum += arr[i][j];
}
arr[i][5] = sum;
}
for (i = 0; i < 5; i++)
{
for (j = 0; j < 6; j++)
{
printf("%.1f ", arr[i][j]);
}
printf("\n");
}
return 0;
}
4.最大公约数
辗转相除法
#include<stdio.h>
int main()
{
int a, b, i, gcd;
scanf("%d %d", &a, &b);
for (i = 1; i < a && i < b; i++)
{
if (a % i == 0 && b % i == 0)
gcd = i;
}
printf("%d和%d的最大公约数为%d\n", a, b, gcd);
return 0;
}
逐一试
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
int m = (a > b ? b : a);
//假设m就是最大公约数
while (1)
{
if (a % m == 0 && b % m == 0)
{
break;
}
m--;
}
printf("%d\n", m);
return 0;
}
5.闰年
#include <stdio.h>
int main()
{
int year = 0;
for (year = 1000; year <= 2000; year++)
{
if ((year % 4 == 0 && year % 100 != 0)||( year % 400 == 0))
printf("%d\n", year);
}
return 0;
}
6.素数
#include <stdio.h>
int main()
{
int i = 100;
int j = 200;
int m = 2;
for (i = 101; i <= j; i += 2)
{
for (m = 3; m < i; m++)
{
if (i % m == 0)
{
break;
}
if ((i % m != 0) && (m >= i / 2))
{
printf("%d ", i);
break;
}
}
}
return 0;
}
int main()
{
int i = 0;
int count = 0;
for (i = 101; i <= 200; i+=2)
{
int flag = 1;//假设i是素数
//判断i是否为素数
int j = 0;
for (j = 2; j<=sqrt(i); j++)
{
if (i % j == 0)
{
flag = 0;//i不是素数
break;
}
}
if (flag == 1)//说明i是素数
{
printf("%d ", i);
count++;
}
}
printf("\ncount = %d\n", count);
return 0;
}
7.计算1/1-1/2+1/3-1/4+1/5 …… + 1/99 - 1/100 的值
#include<stdio.h>
int main()
{
int n;
float i = 1.0;
float sum = 0;
for (n = 1; n <= 100; n++)
{
sum = sum + (i / n) * j;
j = -j;//用于正负号转换
}
printf("%f\n", sum);
return 0;
}
8.求10个整数中最大值
#include <stdio.h>
int main() {
int i = 0;
int Max = 0;
int arr[10] = { 0 };
for (i = 0; i < 10; i++)
{
scanf("%d", &arr[i]);
}
Max = arr[0];
for (i = 0; i < 10; i++)
{
if (arr[i] > Max)
{
Max = arr[i];
}
}
printf("最大的数为%d ", Max);
return 0;
}
9.输出9*9乘法口诀表
int main()
{
int i = 0, j = 0;
for (i = 1; i <= 9; i++)
{
for (j = 1; j <= i; j++)
{
printf("%d*%d=%d ", i, j, i * j);
}
printf("\n");
}
return 0;
}
10.能把arr1中的abcdef拷贝到arr2中
int main()
{
char arr1[] = "abcdef";
char arr2[20] = "XXXXXXXXXXX";
strcpy(arr2, arr1);
printf("%s\n", arr2);
return 0;
}
11.调用memset()函数
int main()
{
char arr[] = "hello bit";
memset(arr + 6, 'X', 3);
//1. 设置内存的时候是以字节为单位的
//2. 每个字节的内容都是一样value
printf("%s\n", arr);//XXXXX bit 输出hello XXX
return 0;
}
12.写一个函数可以找出两个整数中的最大值
int get_max(int x, int y)
{
return (x > y ? x : y);
}
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
int m = get_max(a, b);
printf("%d\n", m);
return 0;
}
13.写一个函数可以交换两个整形变量的内容
//当实参传给形参的时候,形参是实参的一份临时拷贝,对形参的修改不会影响实参
//实现成函数,但是不能完成任务 形参 传值
void Swap1(int x, int y)
{
int tmp = 0;
tmp = x;
x = y;
y = tmp;
}
正确的版本 实参 传址
void Swap2(int* px, int* py)
{
int tmp = 0;
tmp = *px;
*px = *py;
*py = tmp;
}
int main() //Swap1::num1 = 1 num2 = 2 输出结果
//Swap2::num1 = 2 num2 = 1
{
int num1 = 1;
int num2 = 2;
Swap1(num1, num2);
printf("Swap1::num1 = %d num2 = %d\n", num1, num2);
Swap2(&num1, &num2);
printf("Swap2::num1 = %d num2 = %d\n", num1, num2);
return 0;
}
14.通过指针位置来修改数据
int main()
{
int a = 10;
int* pa = &a;
*pa = 20;
printf("%d\n", a);
return 0;
}
15.写一个函数可以判断一个数是不是素数
#include <math.h>
int is_prime(int n)
{
int j = 0;
for (j = 2; j <= sqrt(n); j++)
{
if (n % j == 0)
{
return 0; //返回0 表示不是素数
}
}
return 1; //返回1 表示是素数
}
int main()
{
int i = 0;
for (i = 100; i <= 200; i++)
{
if (is_prime(i) == 1)
{
printf("%d ", i);
}
}
return 0;
}
16.写一个函数判断一年是不是闰年
int is_leap_year(int y)
{
if (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))
return 1;
else
return 0;
}
int is_leap_year(int y)
{
return ((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0);
}
int main()
{
int y = 0;
for (y = 1000; y <= 2000; y++)
{
if (is_leap_year(y) == 1)
{
printf("%d ", y);
}
}
return 0;
}
17.写一个函数,实现一个整形有序数组的二分查找
正确代码
int binary_search(int arr[], int k, int sz)
{
int left = 0;
int right = sz - 1;
while (left<=right)
{
int mid = left + (right - left) / 2;
if (arr[mid] < k)
{
left = mid + 1;
}
else if (arr[mid] > k)
{
right = mid - 1;
}
else
{
return mid;
}
}
return -1;//找不到
}
int main()
{
//数组在传参的时候,传递不是整个数组
//传递是数组首元素的地址
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int k = 0;
scanf("%d", &k);
int sz = sizeof(arr) / sizeof(arr[0]);
int ret = binary_search(arr, k, sz);
if (-1 == ret)
printf("找不到\n");
else
printf("找到了,下标是:%d\n", ret);
return 0;
}
错误代码
int binary_search(int arr[], int k)
{
int sz = sizeof(arr) / sizeof(arr[0]); //error
int left = 0;
int right = sz - 1;
while (left <= right)
{
int mid = left + (right - left) / 2;
if (arr[mid] < k)
{
left = mid + 1;
}
else if (arr[mid] > k)
{
right = mid - 1;
}
else
{
return mid;
}
}
return -1;//找不到
}
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int k = 0;
scanf("%d", &k);
int ret = binary_search(arr, k); //错误的示范
if (-1 == ret)
printf("找不到\n");
else
printf("找到了,下标是:%d\n", ret);
return 0;
}
18.写一个函数,每调用一次这个函数,就会将 num 的值增加1
void test(int *p)
{
*p = *p + 1; //(*p)++ 等价
}
int main()
{
int num = 0;
test(&num);
printf("%d\n", num); //1
test(&num);
printf("%d\n", num); //2
test(&num);
printf("%d\n", num); //3
test(&num);
printf("%d\n", num); //4
return 0;
}
19.strlen()和printf()函数演示
int main()
{
int len = strlen("abcdef");
printf("len1 = %d\n", len);
printf("len2 = %d\n", strlen("abcdef"));
printf("%d", printf("%d", printf("%d", 43)));
//4321 printf的返回值是字符的个数
return 0;
}
20.编写一个print函数把num的每一位按照顺序打印出来
void print(int n)
{
if (n > 9)
{
print(n/10);
}
printf("%d ", n % 10);
}
int main()
{
unsigned int num = 0;
scanf("%d", &num);
print(num);
return 0;
}
21.编写函数不允许创建临时变量,求字符串的长度
#include <string.h>
int my_strlen(char* str) //这是创建临时变量count的写法
{
int count = 0; //统计字符的个数
while (*str != '\0')
{
count++;
str++;
}
return count;
}
//my_strlen("abcdef")
//1+my_strlen("bcdef")
//1+1+my_strlen("cdef")
//1+1+1+ my_strlen("def")
//1+1+1+1+ my_strlen("ef")
//1 + 1 + 1 + 1 +1+my_strlen("f")
//1 + 1 + 1 + 1 + 1 + 1+ my_strlen("")
//1 + 1 + 1 + 1 + 1 + 1 + 0 = 6
int my_strlen(char* str)
{
if (*str != '\0')
return 1 + my_strlen(str+1);
else
return 0;
}
int main()
{
char arr[] = "abcdef";
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
22.求阶乘
int fac1(int n) //递归法
{
if (n <= 1)
return 1;
else
return n * fac(n - 1);
}
int fac(int n)
{
int i = 0;
int ret = 1;
for (i = 1; i <= n; i++)
{
ret = ret * i;
}
return ret;
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = fac(n);
printf("%d\n", ret);
return 0;
}
23.斐波那契数列
int count = 0;
int fib(int n) //递归法 占用内存过大 计算较慢
{
if (n == 3)
count++; //count用来计算求这个斐波那契数列的次数
if (n <= 2)
return 1;
else
return fib(n - 1) + fib(n - 2);
}
int fib(int n) //循环法 优先选择
{
int a = 1;
int b = 1;
int c = 1;
while (n>2)
{
c = a + b;
a = b;
b = c;
n--;
}
return c;
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = fib(n);
printf("%d\n", ret);
printf("count = %d\n", count);
return 0;
}
24.字符串逆序输出
方法一:指针
void reverse_string(char* str)
{
int len = strlen(str);
char* left = str;
char* right = str+len-1;
while (left<right)
{
char tmp = *left;
*left = *right;
*right = tmp;
left++;
right--;
}
}
方法二:数组
void reverse_string(char arr[])
{
int len = strlen(arr);
int left = 0;
int right = len - 1;
while (left<right)
{
char tmp = arr[left];
arr[left] = arr[right];
arr[right] = tmp;
left++;
right--;
}
}
方法三:递归
void reverse_string(char* str)
{
int len = strlen(str);
char tmp = *str;
*str = *(str + len - 1);
*(str + len - 1) = '\0';
if(strlen(str + 1) >= 2)
reverse_string(str+1);
*(str + len - 1) = tmp;
}
主函数main()
int main()
{
char arr[] = "abcdef";//fedcba
reverse_string(arr);
printf("%s\n", arr);
return 0;
}
25.写一个递归函数DigitSum(n),输入一个非负整数,返回组成它的数字之和
int DigitSum(unsigned int n)
{
if (n > 9)
{
return DigitSum(n / 10) + n % 10;
}
else
{
return n;
}
}
int main()
{
unsigned int num = 0;
scanf("%d", &num);
int ret = DigitSum(num);
printf("%d\n", ret);
return 0;
}
26.编写一个函数实现n的k次方,使用递归实现
//pow是内置函数的名字 不能重复
double Power(int n, int k)
{
if (k > 0)
return n * Power(n, k - 1);
else if (k == 0)
return 1;
else
return 1.0/Power(n, -k);
}
int main()
{
int n = 0;
int k = 0;
scanf("%d %d", &n, &k);
double ret = Power(n, k);
printf("%lf\n", ret);
return 0;
}
27.逗号表达式的数组大小
#include <stdio.h>
int main()
{
int arr[] = { 1,2,(3,4),5 };
printf("%d\n", sizeof(arr)); //16
return 0;
}
28.区分sizeof( )和 strlen( )
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "hello bit"; // [h e l l o _ b i t \0]
printf("%d %d\n", sizeof(str), strlen(str)); //10 9
char acX[] = "abcdefg";
printf("%d %d\n", sizeof(acX), strlen(acX)); //8 7
char acY[] = { 'a','b','c','d','e','f','g',};
printf("%d %d\n", sizeof(acY), strlen(acY)); //7 23 这个23是随机值
return 0;
}
29.创建一个整形数组,实现以下功能
void init(int arr[], int sz) //实现函数init()初始化数组为全0
{
int i = 0;
for (i = 0; i < sz; i++)
{
arr[i] = 0;
}
}
void print(int arr[], int sz) //实现print()打印数组的每个元素
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
void reverse(int arr[],int sz) //实现reverse()函数完成数组元素的逆置
{
int left = 0;
int right = sz - 1;
while (left < right)
{
int tmp = arr[left];
arr[left] = arr[right];
arr[right] = tmp;
left++;
right--;
}
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);
print(arr, sz);
reverse(arr, sz);
print(arr, sz);
init(arr, sz);
print(arr, sz);
return 0;
}
30.将数组A中的内容和数组B中的内容进行交换(数组一样大)
int main()
{
int arr1[] = { 1,3,5,7,9 };
int arr2[] = { 2,4,6,8,0 };
//arr3 = arr1; //错误写法 数组不能直接交换
//arr1 = arr2;
//arr2 = arr3;
int sz = sizeof(arr1) / sizeof(arr1[0]);
int i = 0;
for (i = 0; i < sz; i++)
{
int tmp = arr1[i];
arr1[i] = arr2[i];
arr2[i] = tmp;
}
return 0;
}
31.左移、右移操作符
int main()
{
int a = 5;
int b = a << 1;
printf("%d\n", a); //5
printf("%d\n", b); //10
return 0;
}
int main()
{
int a = -5;
int b = a << 1;
printf("%d\n", a); //5
printf("%d\n", b); //-10
return 0;
}
int main()
{
int a = -5;
int b = a >> 1;
printf("a=%d b=%d\n", a, b); //-5 -3
return 0;
}
32.按位与、按位或、按位异或
int main()
{
int a = 3;
int b = -5;
int c = a & b; //两个1才是1否则都是0 除不尽除2减一除的尽除二即可
int d = a | b; //两个0才是0否则都是1
int e = a ^ b; //对应的二进制位:相同为0,相异为1
printf("c=%d d=%d e=%d\n", c,d,e); //3 -5 -8
return 0;
}
a^a = 0 0^a = a
对于多个数字进行异或计算后可以得知哪个数字只出现过一次
1 2 3 4 5 1 2 3 4
33.不创建临时变量(第三个变量),实现两个数的交换
方法一
int main() //方法一
{
int a = 3;
int b = 5;
printf("a=%d b=%d\n", a, b);
int tmp = a;
a = b;
b = tmp;
printf("a=%d b=%d\n", a, b);
return 0;
}
方法二
int main() //方法二 当数字超过内存最大值时会溢出
{
int a = 3;
int b = 5;
printf("a=%d b=%d\n", a, b);
a = a + b;
b = a - b;
a = a - b;
printf("a=%d b=%d\n", a, b);
return 0;
}
方法三
int main() //方法三 只能作用于整数互换
{
int a = 3;
int b = 5;
printf("a=%d b=%d\n", a, b);
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("a=%d b=%d\n", a, b);
return 0;
}
34.编写代码实现:求一个整数存储在内存中的二进制中1的个数
5
00000000000000000000000000000101
00000000000000000000000000000001
5&1
int main()
{
int num = 0;
scanf("%d", &num);
int i = 0;
int count = 0;
for (i = 0; i < 32; i++)
{
if (1 == ((num >> i) & 1))
{
count++;
}
}
printf("%d\n", count);
return 0;
}
35.C语言中C99之前没有表示真假的类型 C99中引用了布尔类型
#include <stdbool.h>
int main()
{
_Bool flag1 = false;
bool flag2 = true;
if (flag2)
{
printf("hehe\n");
}
int num = 10; //C语言中0表示假,非0表示真
if (num)
{
}
if (!num)//num为假,做事情
{
}
return 0;
}
36.sizeof()
sizeof是一个操作符,不是函数,计算类型创建的变量所占内存的大小,单位是字节
int main()
{
int a = 10;
printf("%d\n", sizeof(a)); //4
printf("%d\n", sizeof(int)); //4
int arr[10] = { 0 };
printf("%d\n", sizeof(arr)); //40
return 0;
}
int main()
{
int a = 10;
short s = 0;
printf("%d\n", sizeof(s = a + 2)); //sizeof()中的表达式不参与计算
printf("%d\n", s); //输出 2 0
return 0;
}
37.按位取反~
{
int a = 0;
printf("%d\n", ~a);
//00000000000000000000000000000000 - 0的原码
//11111111111111111111111111111111 - 按位取反 这是补码
//11111111111111111111111111111110 - 这是反码
//10000000000000000000000000000001 ->这是原码 -1
return 0;
}
38.把二进制里面的倒数的第三个数字0换做1
int main()
{
int a = 11;
//方法一 按位或
//00000000000000000000000000001011 把倒数的第三个数字0换做1
//00000000000000000000000000000100 这是4
//11111111111111111111111111111011
//00000000000000000000000000000100 把数字1进行二进制左移两位得到4
a |= (1<<2); //实质就是a|= 4
printf("%d\n", a); //15
//方法二 按位与
//00000000000000000000000000001011 把倒数的第三个数字0换做1
//00000000000000000000000000000100 把数字1进行二进制左移两位得到4
//11111111111111111111111111111011 对数字4进行按位取反得到
a &= (~(1 << 2));
printf("%d\n", a); //11
return 0;
}
39.++和--
int main()
{
int a = 3;
int b = ++a;//前置++,先++后使用 a=a+1,b=a
int b = a++;//后置++,先使用后++ b=a,a=a+1
int b = --a;//前置--,先--后使用 a=a-1,b=a
int b = a--;//后置--,先使用再-- b=a,a=a-1
printf("%d\n", b);
return 0;
}
40.&&和| |
&& 一旦有假出现,后面的便不再运算
int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ && ++b && d++;
//&& 一旦有假出现,后面的便不再运算
printf("a = %d\nb = %d\nc = %d\nd = %d\n", a, b, c, d);
return 0; //1 2 3 4
}
| | 一旦有真出现,后面的便不再运算
int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ || ++b || d++;
//|| 一旦有真出现,后面的便不再运算
printf("a = %d\nb = %d\nc = %d\nd = %d\n", a, b, c, d);
return 0; //1 3 3 4
}
41.逗号表达式
int main()
{
int a = 1;
int b = 2;
int c = (a > b, a = b + 10, a, b = a + 1);
printf("a=%d b=%d\n", a, b); //12 13
printf("%d\n", c); //13
return 0;
}
42.输出数组指定元素
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
printf("%d\n", arr[4]);
printf("%d\n", 4[arr]);
printf("%d\n", *(arr+4));
printf("%d\n", *(4+arr)); //结果都是5
return 0;
}
43.修改结构体内数据及调用输出
#include <string.h>
struct Stu
{
char name[20];
int age;
float score;
};
void print1(struct Stu ss) //结构体变量.成员名
{
printf("%s %d %f\n", ss.name, ss.age, ss.score);
}
void print2(struct Stu* ps) //结构体指针->成员名
{
printf("%s %d %f\n", ps->name, ps->age, ps->score);
}
void print3(struct Stu* ps)
{
printf("%s %d %f\n", (*ps).name, (*ps).age, (*ps).score);
}
int main()
{
struct Stu s = {"张三", 20, 90.5f};
strcpy(s.name, "张三丰"); //或者scanf("%s", s.name);都可以修改里面的数据
print1(s); //张三丰 20 90.500000
print2(&s); //张三丰 20 90.500000
print3(&s); //张三丰 20 90.500000
return 0;
}
44.整体提升
int main() //整体提升
{
char c1 = 3;
//00000000000000000000000000000011
//00000011 - c1 //char只能放下八个字节 因此只保留八位
char c2 = 127;
//00000000000000000000000001111111
//01111111 - c2
char c3 = c1 + c2;
//按照c1和c2在char里面存储的二进制数值的符号位进行部位
//正数前面补0 负数前面补1
//00000000000000000000000000000011 - c1
//00000000000000000000000001111111 - c2
//00000000000000000000000010000010 -再进行相加
//10000010 - c3 最后只保留后面的八位
//11111111111111111111111110000010 负数前面补1 得到存储的补码
//11111111111111111111111110000001 减一得到反码
//10000000000000000000000001111110 最后得到原码 -126
printf("%d\n", c3); //-126
return 0;
}
int main() //整体提升
{
char a = 0xb6;//10110110
short b = 0xb600;
int c = 0xb6000000;
if (a == 0xb6)
printf("a");
if (b == 0xb600)
printf("b");
if (c == 0xb6000000)
printf("c"); //a和b都发生了整体提升,因此不输出,最后只输出c
return 0;
}
int main() //整体提升
{
char c = 1;
printf("%u\n", sizeof(c)); //1 算的是char类型的大小
printf("%u\n", sizeof(+c));//4 由于进行了加减运算所以算的是int类型的大小
printf("%u\n", sizeof(-c));//4
return 0;
}
45.求两个数二进制中不同位的个数
编程实现:两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同?
思路:
1. 先将m和n进行按位异或,此时m和n相同的二进制比特位清零,不同的二进制比特位为1
2. 统计异或完成后结果的二进制比特位中有多少个1即可
#include <stdio.h>
int calc_diff_bit(int m, int n)
{
int tmp = m ^ n;
int count = 0;
while (tmp)
{
tmp = tmp & (tmp - 1);
count++;
}
return count;
}
int main()
{
int m, n;
while (scanf("%d %d", &m, &n) == 2)
{
printf("%d\n", calc_diff_bit(m, n));
}
return 0;
}
46.打印整数二进制的奇数位和偶数位
获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出二进制序列
思路:提取所有的奇数位,如果该位是1,输出1,是0则输出0。以同样的方式提取偶数位置
检测num中某一位是0还是1的方式:
1. 将num向右移动i位
2. 将移完位之后的结果与1按位与,如果:结果是0,则第i个比特位是0,结果是非0,则第i个比特位是1。
void Printbit(int num)
{
for (int i = 31; i >= 1; i -= 2)
{
printf("%d ", (num >> i) & 1);
}
printf("\n");
for (int i = 30; i >= 0; i -= 2)
{
printf("%d ", (num >> i) & 1);
}
printf("\n");
}
int main()
{
int num = 0;
printf("请输入一个数: ");
scanf("%d", &num);
Printbit(num);
return 0;
}
47.统计二进制中1的个数
#include<stdio.h>
int Hamming_weight_2(int number) //只考虑1的位数
{
int count_ = 0; //声明计数变量
while (number != 0) //遍历
{
number &= number - 1;
count_++;
}
return count_;
}
int main()
{
int n;
while (scanf("%d", &n) != EOF) //读入整数和打印1的个数
{
printf("%d \n", Hamming_weight_2(n));
}
return 0;
}
方法一:
思路:
循环进行以下操作,直到n被缩减为0:
1. 用该数据模2,检测其是否能够被2整除
2. 可以:则该数据对应二进制比特位的最低位一定是0,否则是1,如果是1给计数加1
3. 如果n不等于0时,继续1缺陷:进行了大量的取模以及除法运算,取模和除法运算的效率本来就比较低。
int count_one_bit(int n)
{
int count = 0;
while (n)
{
if (n % 2 == 1)
count++;
n = n / 2;
}
return count;
}
方法二:
思路:一个int类型的数据,对应的二进制一共有32个比特位,可以采用位运算的方式一位一位的检测优点:用位操作代替取模和除法运算,效率稍微比较高
缺陷:不论是什么数据,循环都要执行32次
int count_one_bit(unsigned int n)
{
int count = 0;
int i = 0;
for (i = 0; i < 32; i++)
{
if (((n >> i) & 1) == 1)
count++;
}
return count;
}
方法三:
思路:采用相邻的两个数据进行按位与运算
举例:
9999:10 0111 0000 1111
第一次循环:n=9999 n=n&(n-1)=9999&9998= 9998
第二次循环:n=9998 n=n&(n-1)=9998&9997= 9996
第三次循环:n=9996 n=n&(n-1)=9996&9995= 9992
第四次循环:n=9992 n=n&(n-1)=9992&9991= 9984
第五次循环:n=9984 n=n&(n-1)=9984&9983= 9728
第六次循环:n=9728 n=n&(n-1)=9728&9727= 9216
第七次循环:n=9216 n=n&(n-1)=9216&9215= 8192
第八次循环:n=8192 n=n&(n-1)=8192&8191= 0
可以观察到:此种方式,数据的二进制比特位中有几个1,循环就循环几次,而且中间采用了位运算,处理起来比较高效
int count_one_bit(int n)
{
int count = 0;
while (n)
{
n = n & (n - 1);
count++;
}
return count;
}
48.求代码输出结果
#include <stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5 };
short* p = (short*)arr;
int i = 0;
for (i = 0; i < 4; i++)
{
*(p + i) = 0;
}
for (i = 0; i < 5; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
解析:
arr数组在内存中的存储格式为:
0x00ECFBF4: 01 00 00 00
0x00ECFBF8 : 02 00 00 00
0x00ECFBFC : 03 00 00 00
0x00ECFC00 : 04 00 00 00
0x00ECFC04 : 05 00 00 00
指针p的类型为short * 类型的,
因此p每次只能所有两个字节,for循环对数组中内容进行修改时,一次访问的是:
arr[0]的低两个字节,arr[0]的高两个字节,arr[1]的低两个字节,
arr[1]的高两个字节,
故改变之后,数组中内容如下:
0x00ECFBF4 : 00 00 00 00
0x00ECFBF8 : 00 00 00 00
0x00ECFBFC : 03 00 00 00
0x00ECFC00 : 04 00 00 00
0x00ECFC04 : 05 00 00 00
故最后打印:0 0 3 4 5
unsigned long pulArray[] = { 6,7,8,9,10 };
unsigned long* pulPtr;
pulPtr = pulArray;
*(pulPtr + 3) += 3;
printf(“% d, % d\n”, *pulPtr, *(pulPtr + 3));
unsigned long pulArray[] = { 6,7,8,9,10 };
unsigned long* pulPtr;
pulPtr = pulArray;
数组名代表数组首元素地址,因此pulptr指向的是数组中第一个元素的位置
*(pulPtr + 3) += 3;
pulptr+3访问的是数组中第三个元素(数组下标从0开始),故将9改为9+3=12
printf(“% d, % d\n”, *pulPtr, *(pulPtr + 3));
打印第一个和第三个元素,因此:打印6和12
#include <stdio.h>
int main()
{
int a = 0x11223344;
char* pc = (char*)&a;
*pc = 0;
printf("%x\n", a);
return 0;
}
假设,a变量的地址为0x64,则a变量在内存中的模型为:
0x64 | 44 |
0x65 | 33 |
0x66 | 22 |
0x67 | 11 |
char* 类型的指针变量pc指向只能指向字符类型的空间,
如果是非char类型的空间,必须要将该空间的地址强转为char * 类型。
char* pc = (char*)&a; pc实际指向的是整形变量a的空间,即pc的内容为0x64,即44,
* pc = 0,即将44位置中内容改为0,修改完成之后,a中内容为:0x11223300
49.写一个函数打印arr数组的内容,不使用数组下标,使用指针
#include <stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
//分析:因为数组中存储的元素类型是int类型的,因此只要给一个int的指针依次取索引数组中的每个元素即可
int* p = arr; // 数组名代表数组首元素的地址
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i)
{
printf("%d ", *p); // *p: 取到p所指向位置的元素
++p; // 获取p的下一个位置
}
return 0;
}
50.求出0~100000之间“水仙花数”,打印菱形
“水仙花数”是指一个n位数,其各位数字的n次方之和确好等于该数本身,
如:153=1 ^ 3+5 ^ 3+3 ^ 3,则153是一个“水仙花数”。
#include <stdio.h>
#include <math.h>
int main()
{
int i = 0;
for (i = 1; i <= 99999; i++)
{
int tmp = i;//各位数
int count = 0;//n
int sum = 0;
while (tmp)
{
tmp /= 10;//各位数
count++;
}
tmp = i;
while (tmp)
{
sum += pow((tmp % 10), count);
tmp /= 10;
}
if (sum == i)
{
printf("%d是水仙花数\n", i);
}
}
return 0;
}
#include<stdio.h>
#include<stdlib.h>
void PrintLine(int blank_count, int start_count)
{
int i = 0;
for (; i < blank_count; i++)
{
printf(" "); //打印空格
}
for (i = 0; i < start_count; i++)
{
printf("*");
}
printf("\n");
}
void PrintLingxing(int n)
{
//打印上半部分
int i = 1;
for (i = 1; i < n; i++)
{
PrintLine(n - i, 2 * i - 1); // 打印每一行的空格和每一行的星号
}
//打印中间部分
PrintLine(0, 2 * n - 1);
//打印下半部分
for (i = n - 1; i > 0; i--)
{
PrintLine(n - i, 2 * i - 1);
}
}
int main()
{
PrintLingxing(7); //对半的行数
system("pause");
return 0;
}
*
***
*****
*******
*********
***********
*************
***********
*********
*******
*****
***
*