题一:直接交换
交换两个变量(不创建临时变量)
不允许创建临时变量,交换两个整数的内容
情况如下:
按位异或(相同为0,不相同未1):" ^ ";
a ^ a = 0; a ^ 0 = a; //就有 3 ^ 5 ^3 = 5;
#include <stdio.h> int main() { int a = 0; int b = 0; scanf("%d %d", &a, &b); a = a ^ b; b = a ^ b; a = a ^ b; printf("%d %d\n", a, b); return 0; }
题二:计算二进制数个数
输入一个整数 n ,输出该数32位二进制表示中1的个数。其中负数用补码表示。
#include <stdio.h> int main() { int n = 0; int sum = 0; scanf("%d", &n); while (n != 0) { n = n & (n - 1);//n为00101000;n - 1得到00100111;n & (n - 1)得到00100000 //就会去掉一个1 sum++; } printf("%d\n", sum); 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个比特位,可以采用位运算的方式一位一位的检测,具体如下 */ 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; } /* 方法二优点:用位操作代替取模和除法运算,效率稍微比较高 缺陷:不论是什么数据,循环都要执行32次 方法三: 思路:采用相邻的两个数据进行按位与运算 举例: 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; }
题三:打印二进制奇偶位
打印整数二进制的奇数位和偶数位
获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出二进制序列
#include <stdio.h> int main() { int n = 0; scanf("%d", &n); int i = 0; //奇数位 for (i = 0; i < 32; i += 2) { printf("%d ",(n >> i) & 1); } printf("\n"); //偶数位 for (i = 1; i <= 31; i += 2) { printf("%d ", (n >> i) & 1); } return 0; }
题四:二进制不同个数
输入两个整数,求两个整数二进制格式有多少个位不同
#include <stdio.h> int main() { int a = 0; int b = 0; int n = 0; int i = 0; int count = 0; scanf("%d %d",&a, &b); n = a ^ b; for (i = 0; i < 32; i++) { if (((n >> i) & 1) == 1) count++; } printf("%d\n",count); return 0; }
更好的方法:
/* 思路: 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; }
题五:序列合并
输入两个升序排列的序列,将两个序列合并为一个有序序列并输出。
#include <stdio.h> int main() { int a = 0; int b = 0; scanf("%d %d", &a ,&b); int arr1[1000] = {0}; int arr2[1000] = {0}; int i = 0; for (i = 0;i < a;i++) { scanf("%d",&arr1[i]); } for (i = 0; i < b; i++) { scanf("%d", &arr2[i]); } int q = 0; int j = 0; int n = 0; int arr3[1000] = { 0 }; i = 0; while (j < a && n < b) { if (arr1[j] < arr2[n]) { arr3[i] = arr1[j]; i++; j++; } else { arr3[i] = arr2[n]; i++; n++; } } if (j == a && n < b) { for (; n < b; n++) { arr3[i] = arr2[n]; i++; } } else { for (; j < a; j++) { arr3[i] = arr1[j]; i++; } } q = i; for (i = 0; i < q; i++) { printf("%d ",arr3[i]); } return 0; }
题六:序列排序
输入一个整数序列,判断是否是有序序列,有序,指序列中的整数从小到大排序或者从大到小排序(相同元素也视为有序)。
#include <stdio.h> int main() { int count1 = 0; int count2 = 0; int n = 0; scanf("%d", &n); int i = 0; int arr[50] = { 0 }; for (i = 0; i < n; i++) { scanf("%d ",&arr[i]); } for (i = 0; i < n-1; i++) { if (arr[i] >= arr[i + 1]) { count1++; } if (arr[i] <= arr[i + 1]) { count2++;; } } if (count1 == n - 1) { printf("sorted"); } else if (count2 == n - 1) { printf("sorted"); } else { printf("unsorted"); } return 0; }
题七:计算月份天数
KiKi想获得某年某月有多少天,请帮他编程实现。输入年份和月份,计算这一年这个月有多少天。
多组输入,一行有两个整数,分别表示年份和月份,用空格分隔。
针对每组输入,输出为一行,一个整数,表示这一年这个月有多少天
#include <stdio.h> int is_year(int year) { return (year % 4 == 0 && year % 100 != 0 || year % 400 == 0); } int main() { int year = 0; int month = 0; int sum = 0; while (scanf("%d %d", &year, &month) == 2) { int day[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 }; sum = is_year(year); if (sum == 1) { day[2] = 29; } printf("%d\n",day[month]); } return 0; }
题八:数组打印
使用指针打印数组内容
写一个函数打印arr数组的内容,不使用数组下标,使用指针。
arr是一个整形一维数组。
#include <stdio.h> #include <string.h> void print(int* arr,int len) { int i = 0; for (i = 0; i < len; i++) { printf("%d ",*(arr+i)); } } int main() { int arr[10] = { 0,1,2,3,4,5,6,7,8,9 }; int len = 0; len = sizeof(arr) / sizeof(arr[0]); print(arr,len); return 0; }
题九:颠倒字符串
将一个字符串str的内容颠倒过来,并输出
int main() { char str[10000] = { 0 }; gets(str); int sz = strlen(str); /*print(str, sz);*/ int i = 0; for (i = 0; i < sz; i++) { char tmp = 0; tmp = str[i]; str[i] = str[sz - 1]; str[sz-- - 1] = tmp; } printf("%s\n", str); return 0; }
题十:打印图案
用C语言在屏幕上输出以下图案:
#include <stdio.h> int main() { int line = 0; scanf("%d", &line); int i = 0; int j = 0; //上半部分 for (i = 0; i <= line/2; i++) { for (j = 0; j < (line-2*i)/2; j++) { printf(" "); } for (j = 0; j < 2 * i + 1; j++) { printf("*"); } printf("\n"); } //下半部分 for (i = 1; i <= line / 2; i++) { for (j = 0; j <= i-1; j++) { printf(" "); } for (j = 0; j < (line - (2 * i)); j++) { printf("*"); } printf("\n"); } return 0; }
题十一:变种水仙花
求出0~100000之间的所有“水仙花数”并输出。
“水仙花数”是指一个n位数,其各位数字的n次方之和确好等于该数本身,
如 : 153=1 ^ 3+5 ^ 3+3 ^ 3,则153是一个“水仙花数”。
#include <stdio.h> #include <math.h> int Daffodil(int i) { int sum = 0; int n = 1; int tmp = i; while (tmp / 10) { n++; tmp /= 10; } tmp = i; while (tmp) { sum =(int)pow(tmp % 10,n) + sum; tmp = tmp / 10; } return sum == i; } int main() { int i = 0; for (i = 0; i < 100000; i++) { if (Daffodil(i)) { printf("%d ", i); } } return 0; }
题十二:计算五项和
求Sn = a + aa + aaa + aaaa + aaaaa的前5项之和,其中a是一个数字,
例如:2 + 22 + 222 + 2222 + 22222
#include <stdio.h> int Sn(int a) { int sum = 0; int i = 0; int n = a; for (i = 0; i < 5; i++) { sum = a + sum; a = n + a * 10; } return sum; } int main() { int a = 0; int sum = 0; scanf("%d", &a); sum = Sn(a); printf("%d\n", sum); return 0; }
写错的选择题
下面代码的结果是:
#include <stdio.h> int i; int main() { i--; if (i > sizeof(i)) { printf(">\n"); } else { printf("<\n"); } return 0; }
A.>
B.<
C.不输出
D.程序有问题
C语言中,0为假,非0即为真。
全局变量,没有给初始值时,编译其会默认将其初始化为0。
i的初始值为0,i--结果-1,i为整形,sizeof(i)求i类型大小是4,按照此分析来看,结果应该选择B,但是sizeof的返回值类型实际为无符号整形,因此编译器会自动将左侧i自动转换为无符号整形的数据,-1对应的无符号整形是一个非常大的数字,超过4或者8,
下列程序段的输出结果为( )
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
经典题目
下面关于指针运算说法正确的是:( )
A.整形指针+1,向后偏移一个字节
B.指针-指针得到是指针和指针之间的字节个数
C.整形指针解引用操作访问4个字节
D.指针不能比较大小
注意:此题是有问题的,说法不严谨,如果将整形指针理解成int*类型的指针,那么一下说法解析如下
A:错误,整形指针+1,向后便宜一个整形类型的大小,即4个字节
B:错误,两个指针相减,指针必须指向一段连续空间,减完之后的结构代表两个指针之间相差元素的个数
C:正确,整形指向的是一个整形的空间,解引用操作访问4个字节
D:指针中存储的是地址,地址可以看成一个数据,因此是可以比较大小的