C语言习题详解

[复制链接]
发表于 2025-12-1 20:15:30 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
目次
C语言习题2.0
删除数组中的指定元素
1)运用双指针
2)创建新数组
在数组中找只出现过一次的数字
1)有一个数字成单,其他成对
2)有两个数字成单,其他成对
递归打印
字符串左旋和右旋
1)运用字符串函数
2)将字符串前移,第一个字符调到末了
 互换整形变量
1)通过创建第三变量来实现
2)不创建第三方变量,利用两数作差的方法实现 
1>.利用a=a-b;
2>.利用a=a+b;
3)运用位异或
4)利用指针变量
求一个数二进制中1的个数的方法
1)利用%和/来盘算
 2)对第一种方法举行改进
3)利用位移操纵符举行盘算
4)利用n&(n-1)的性子盘算
 将数组中全部的奇数放在前面,偶数放在反面
1)运用指针
 2)将奇偶放在两个数组中
strlen的实现
在矩阵中找数字
找凶手
杨辉三角
模仿实现atoi
 offsetof的模仿实现
将一个数二进制的奇数位和偶数位举行互换

C语言习题2.0

C语言习题2.0-CSDN博客
删除数组中的指定元素

1)运用双指针

运用双指针,一个在前面走,另一个来更换;
  1. //方法一:采用双指针
  2. int main()
  3. {
  4.         int arr1[] = { 1,8,6,5,4,8,9,8,5,9,6,8,5,8,5,2,8 };
  5.         int c = 8;
  6.        
  7.         int j = 0, k = 0;
  8.         int num = sizeof(arr1) / sizeof(arr1[0]);
  9.         for(int i=0;i<num;i++)
  10.         {
  11.                 if (arr1[k] != c)
  12.                 {
  13.                         arr1[j] = arr1[k];
  14.                         j++;
  15.                 }
  16.                 k++;
  17.         }
  18.         for (int i = 0; i < j; i++)
  19.                 printf("%d ", arr1[i]);
  20.         return 0;
  21. }
复制代码
2)创建新数组

  1. //方法二:创建新数组,遍历原数组
  2. int main()
  3. {
  4.         int arr[] = { 1,8,6,5,4,8,9,8,5,9,6,8,5,8,5,2,8 };
  5.         int t = 8;//删除数组中的元素8
  6.         int sz = sizeof(arr) / sizeof(arr[0]);
  7.         int new[20] = { 0 };
  8.         int a = 0;
  9.         int* p = arr;
  10.         for (int i = 0; i < sz; i++)
  11.         {
  12.                 if (arr[i] != t)
  13.                 {
  14.                         new[a] = arr[i];
  15.                         a++;
  16.                 }
  17.         }
  18.        
  19.         for (int i = 0; i < a; i++)
  20.         {
  21.                 printf("%d ", new[i]);
  22.         }
  23.         return 0;
  24. }
复制代码
在数组中找只出现过一次的数字

1)有一个数字成单,其他成对

   运用按位或操纵符^,a^a=0;0^a=a;根据这个特性,将数组中全部的数字都举行按位与,得到的效果就是成单的数字;
  1. //找到数组中只出现过一次的数字
  2. int main()
  3. {
  4.         int arr[] = { 1,2,6,5,4,5,6,2,1 };
  5.         int sz = sizeof(arr) / sizeof(arr[0]);
  6.         int differ = 0;
  7.         for (int i = 0; i < sz; i++)
  8.         {
  9.                 differ ^= arr[i];
  10.         }
  11.         printf("%d", differ);
  12.         return 0;
  13. }
复制代码
2)有两个数字成单,其他成对

   将全部数字按位或,得到a^b即两个成单数字按位或的效果。找到其二进制中第一个1的位置,该位置a,b中肯定有一个是1,另一个是0;此时利用该二进制位就可以将他们分开。
  
  1. //有两个成单的元素
  2. int main()
  3. {
  4.         int arr[] = { 1,5,6,9,8,6,5,1,3,3 };
  5.         int sz = sizeof(arr) / sizeof(arr[0]);
  6.         int differ = 0;
  7.         for (int i = 0; i < sz; i++)
  8.         {
  9.                 differ ^= arr[i];
  10.         }
  11.         //此时differ就是两个成单数字按位或的结果
  12.         //找二进制中第一个1的位置
  13.         int num = 0;
  14.         for (int i = 1; i < 31; i++)
  15.         {
  16.                 if (((differ >> i) & 1) == 1)
  17.                 {
  18.                         num = i;
  19.                         break;
  20.                 }
  21.         }
  22.         //此时将数组中的元素分开,依据二进制的num位是否为1
  23.         int diff_1 = 0;
  24.         int diff_2 = 0;
  25.         for (int i = 0; i < sz; i++)
  26.         {
  27.                 if (((arr[i] << num)&1) == 1)
  28.                         diff_1 ^= arr[i];
  29.                 else
  30.                         diff_2 ^= arr[i];
  31.         }
  32.         printf("%d %d", diff_1, diff_2);
  33.         return 0;
  34. }
复制代码
递归打印

运用递归打印一个数中最高位到最低为全部的数;
  1. void Print(int x)
  2. {
  3.         if (x > 9)
  4.         {
  5.                 Print(x / 10);
  6.                 printf("%d ", x % 10);
  7.         }
  8.         else
  9.                 printf("%d ", x % 10);
  10. }
  11. int main()
  12. {
  13.         int a = 15615646;
  14.         Print(a);
  15.         return 0;
  16. }
复制代码
字符串左旋和右旋

   将字符串中的字符向左(向右)移动指定的位数,移动到最左边(右边)的字符会从右边补上。
  原字符串:"abcde"  ,左旋 2 位:"cdeab";原字符串:"abcde" 右旋 2 位:"deabc"。
  1)运用字符串函数

   运用字符串函数。strcpy和strncat函数实现,先将旋转反面的字符串复制到前面,再将前面的字符串追加到反面。
  1. //左旋,右旋
  2. //将"ABCDE"左旋2个单位为"CDEAB"
  3. int main()
  4. {
  5.         char arr[6] = "ABCDE";
  6.         char arr2[6];
  7.         //先将后面的字符串复制到前面
  8.         strcpy(arr2, arr + 2);
  9.         //将前面的追加到后面
  10.         strncat(arr2, arr, 2);
  11.         //将目标字符串复制回来
  12.         strcpy(arr, arr2);
  13.         printf("%s", arr);
  14.         return 0;
  15. }
复制代码
2)将字符串前移,第一个字符调到末了

  1. //方法二:将后面的字符串向前移动,前面的字符调转到后面
  2. //将"ABCDE"左旋2个单位为"CDEAB"
  3. int main()
  4. {
  5.         char arr[6] = "ABCDE";
  6.         int sz = strlen(arr);
  7.         //向前调转2次
  8.         for (int i = 0; i < 2; i++)
  9.         {
  10.                 char a = arr[0];
  11.                 //将字符串向前移动
  12.                 for (int i = 0; i < sz-1; i++)
  13.                         arr[i] = arr[i + 1];   //arr[3]=arr[4]
  14.                 //将第一个字符调转到最后一个字符
  15.                 arr[sz - 1] = a;
  16.         }
  17.         printf("%s", arr);
  18.         return 0;
  19. }
复制代码
 互换整形变量

1)通过创建第三变量来实现

   假设互换a和b,重新界说一个c,利用变量赋值是从左向右的,先将a赋值给c(c=a),再将b赋值给a(a=b),末了再将c赋值给b(b=c);此处可以类比为两个杯子的水互换,假设a是雪碧,b是可乐,c是空瓶,先将a倒入到c中,再将b倒入到a中,末了将c倒入到b中完成互换;此方法可读性较高。
  1. //1)运用第三个变量来交换
  2. int main()
  3. {
  4.         int a = 10;
  5.         int b = 20;
  6.         int c;
  7.         printf("交换前a=%d,b=%d\n", a, b);
  8.         c = a;
  9.         a = b;
  10.         b = c;
  11.         printf("交换之后a=%d,b=%d", a, b);
  12.         return 0;
  13. }
复制代码
2)不创建第三方变量,利用两数作差的方法实现 

1>.利用a=a-b;

此方法与第一种方法雷同,也是运用赋值是从左向右,从上向下,此处不外多赘述
  1. //不创建第三方变量,利用两数作差的方法实现
  2. //利用a=a-b;
  3. int main()
  4. {
  5.         int a = 10;
  6.         int b = 20;
  7.         printf("交换前a=%d,b=%d\n", a, b);
  8.         a = a - b;
  9.         b = a + b;   
  10.         a = b - a;
  11.         printf("交换之后a=%d,b=%d", a, b);
  12.         return 0;
  13. }
复制代码
2>.利用a=a+b;

  1. //利用a=a+b;
  2. //#include <limits.h>  //调用INT_MAX所需要的头文件
  3. int main()
  4. {
  5.         printf("%d\n", INT_MAX);
  6.         int a = 10;
  7.         int b = 20;
  8.         printf("交换前a=%d,b=%d\n", a, b);
  9.         a = a + b;   //注意此处于上一个代码的不同,此处的a=a+b的a可能超出INT_MAX即int类型的最大值
  10.         b = a - b;
  11.         a = a - b;
  12.         printf("交换之后a=%d,b=%d", a, b);
  13.         return 0;
  14. }
复制代码
留意这两种方法的差异,第一种a=a-b大概会导致,a小于INT_MIN,而第二种大概会导致a大于INT_MAX,两种方法都大概导致整数溢出,以是不发起.
3)运用位异或

两个雷同的操纵数位异或的效果为0,即a^a=0;任何数与0位异或还是其自己,即a^0=a;
  1. //运用位异或
  2. int main()
  3. {
  4.         int a = 10;
  5.         int b = 20;
  6.         printf("交换前a=%d,b=%d\n", a, b);
  7.         a = a ^ b;
  8.         b = a ^ b;
  9.         a = a ^ b;
  10.         printf("交换之后a=%d,b=%d", a, b);
  11.         return 0;
  12. }
复制代码
此处形象化明白,a=a^b(此时的a已经不是20了)的a可以当作是一把钥匙,碰到b位异或为a,碰到a位异或为b;此方法不太发起,可读性较低
4)利用指针变量

与创建第三变量雷同,只是通过所在及解引用来互换,此处不再过多赘述
  1. //利用指针即解引用来交换
  2. int main()
  3. {
  4.         int a = 10;
  5.         int b = 20;
  6.         int c = 0;
  7.         printf("交换之前a=%d,b=%d\n", a, b);
  8.         int* p1 = &a;
  9.         int* p2 = &b;
  10.         int* p3 = &c;
  11.         *p3 = *p1;
  12.         *p1 = *p2;
  13.         *p2 = *p3;
  14.         printf("交换之后a=%d,b=%d\n", a, b);
  15.         return 0;
  16. }
复制代码
求一个数二进制中1的个数的方法

1)利用%和/来盘算

(方法类于盘算11111十进制中1的个数);分别利用%2来确定末了一位是否为1,在利用/2往复掉当前的二进制最右侧一位,方法较为质朴,可读性也高,不再过多赘述。但是这个方法不能用来盘算负数。
  1. //利用/和%来计算
  2. int main()
  3. {
  4.         int n = 15;
  5.         //15:  00000......00001111
  6.         int count = 0;
  7.         while (n)                          //此方法不能用来计算负数
  8.         {
  9.                 if (n % 2 == 1)                  //此处的%2是为了确定是否为1
  10.                         count++;
  11.                 n /= 2;                          //利用/2来去掉二进制的最右侧一位
  12.         }
  13.         printf("%d", count);
  14.         return 0;
  15. }
复制代码
 2)对第一种方法举行改进

第一种方法在于n=-1是默认有符号的,n%或/的效果均为负数,且相处后效果为0,无法盘算,我们知道-1的二进制是11111111.....11111111,而输出的效果是0。以是我们只必要将其有符号位的1酿成数字位的1即可,就是将其酿成无符号整形,即m=(unsigned int)n此时的m表现一个很大的整数,而不是-1。
  1. int main()
  2. {
  3.         int n = -1;
  4.        
  5.         int count = 0;
  6.         unsigned int m = (unsigned int)n;     //此处将n改成无符号就可以进行计算了
  7.         while (m)
  8.         {
  9.                 if (m % 2 == 1)                   //此处的%2是为了确定是否为1
  10.                         count++;
  11.                 m /= 2;                           //利用/2来去掉二进制的最右侧一位
  12.         }
  13.         printf("二进制中1的个数为%d", count);
  14.         return 0;
  15. }
复制代码
3)利用位移操纵符举行盘算

利用>>依次向右移动来逐个查抄,此方法简朴,但是其必要循环32次才气竣事,以是其举行了多次无用循环,浪费时间,不发起利用。
  1. //利用移位操作符来计算
  2. int main()
  3. {
  4.         int a = 15;
  5.         int count = 0;
  6.         for (int i = 0; i < 32; i++)
  7.         {
  8.                 if (a & 1 == 1)                         //利用a&1来的出二进制的最右侧移位是0还是1
  9.                         count++;  
  10.                 a >>= 1;                                         //将二进制向右移动,逐个检查
  11.         }
  12.         printf("二进制数字中1的个数为%d", count);
  13.         return 0;
  14. }
复制代码
4)利用n&(n-1)的性子盘算


  1. //利用n&(n-1)的性质计算
  2. int main()
  3. {
  4.         int n = 15;
  5.         int count = 0;
  6.         while (n)
  7.         {
  8.                         count++;               
  9.                 n = n & (n - 1);
  10.         }
  11.         printf("二进制数中的1一共有%d个", count);
  12.         return 0;
  13. }
复制代码
 将数组中全部的奇数放在前面,偶数放在反面

1)运用指针

运用两个指针left,right,分别在两边找到偶数和奇数,再将left和right举行互换。
  1. //将一个数组的所有奇数放在前面,偶数放在后面。
  2. int main()
  3. {
  4.         int arr[] = { 1,6,9,6,2,7,8,6,3,1,4,5,6 };
  5.         int sz = sizeof(arr) / sizeof(arr[0]);
  6.         int left = 0, right = sz - 1;
  7.         while (left < right)
  8.         {
  9.                 //在左半边找到偶数
  10.                 while (arr[left] % 2 == 0)
  11.                         left++;
  12.                 //在右半边找到奇数
  13.                 while (arr[right] % 2 != 0)
  14.                         right--;
  15.                 //交换
  16.                 int tmp = arr[left];
  17.                 arr[left] = arr[right];
  18.                 arr[right] = tmp;
  19.         }
  20.         for (int i = 0; i < sz; i++)
  21.                 printf("%d ", arr[i]);
  22.         return 0;
  23. }
复制代码
 2)将奇偶放在两个数组中

  1. //创建两个数组,专门用来存放奇数,偶数
  2. int main()
  3. {
  4.         int arr[] = { 1,6,9,6,2,7,8,6,3,1,4,5,6 };
  5.         int jji[10] = { 0 };
  6.         int ji = 0;
  7.         int oou[10] = { 0 };
  8.         int ou = 0;
  9.         int sz = sizeof(arr) / sizeof(arr[0]);
  10.         for (int i = 0; i < sz; i++)
  11.         {
  12.                 if (arr[i] % 2 == 0)
  13.                 {
  14.                         oou[ou] = arr[i];
  15.                         ou++;
  16.                 }
  17.                 else
  18.                 {
  19.                         jji[ji] = arr[i];
  20.                         ji++;
  21.                 }
  22.         }
  23.         for (int i = 0; i < ji; i++)
  24.                 printf("%d ", jji[i]);
  25.         for (int i = 0; i < ou; i++)
  26.                 printf("%d ", oou[i]);
  27.         return 0;
  28. }
复制代码
判定一个数是否是2的次方数

1)/2看是否没有余数

将该数字不绝除以2,取模2。
  1. //判断一个数是否是2的次方数
  2. bool IsTow(int a)
  3. {
  4.         while (a!=1)
  5.         {
  6.                 if (a % 2 == 0)
  7.                         ;
  8.                 if (a % 2 == 1)
  9.                         return false;
  10.                 a /= 2;
  11.         }
  12.         return true;
  13. }
复制代码
2)二进制中只有1个是1

  1. //判断一个数是否是2的次方数
  2. //如果其二进制中只有一个1就是2的次方数
  3. bool IsTow(int a)
  4. {
  5.         int count=0;
  6.         while (a)
  7.         {
  8.                 a = a & (a - 1);
  9.                 count++;
  10.         }
  11.         if (count == 1)
  12.                 return true;
  13.         return false;
  14. }
复制代码
strlen的实现

运用指针找到字符串的末端,在减去起始所在即可。
  1. //strlen的是实现
  2. int main()
  3. {
  4.         char arr[] = "asfnkdsbnvfkua";
  5.         char* p = arr;
  6.         while (*(p++))
  7.                 ;
  8.         //地址减去地址表示两个地址中间的元素个数
  9.         int sz = p - arr;
  10.         printf("%d", sz);
  11.         return 0;
  12. }
复制代码
在矩阵中找数字

   找一个矩阵中找到要求的数字,并返回它的坐标;要求时间复杂度小于O(x),即不能一个一个查找;要求:从左到右数字增大,从上到下数字增大,下面是一个4*4的矩阵
  1        2        3        4
  5        6        7        8
  9       10      11      12
  13     14      15      16
  找数字:arr[ i ][ j ]初始时 i=0,j=4数字比找的数字大j--,比找的数字小了i++;
  1. int main()
  2. {
  3.         //生成一个矩阵
  4.         int arr[4][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16} };
  5.         int p;
  6.         scanf("%d", &p);
  7.         int i = 0, j = 4;
  8.         int flag = 0;
  9.         while (i < 4 && j>0)
  10.         {
  11.                 if (arr[i][j] > p)
  12.                         j--;
  13.                 else if (arr[i][j] < p)
  14.                         i++;
  15.                 else
  16.                 {
  17.                         flag = 1;
  18.                         break;
  19.                 }
  20.         }
  21.         if (flag)
  22.                 printf("%d %d\n", i, j);
  23.         else
  24.                 printf("没找到\n");
  25.         return 0;
  26. }
复制代码
找凶手

   A:不是我;
  B:是C;
  C:是D;
  D:C说谎;
  四个人中有一个人说谎,以一个凶手
  运用酿成找到凶手;
  1. //找凶手
  2. int main()
  3. {
  4.         char killer;
  5.         for (char i = 'A'; i <= 'D'; i++)
  6.         {
  7.                 killer = i;
  8.                  //      A                    B                C                  D
  9.                 if ((killer != 'A') + (killer == 'C') + (killer == 'D') + (killer != 'D') == 3)
  10.                         break;
  11.         }
  12.         printf("%c", killer);
  13.         return 0;
  14. }
复制代码
杨辉三角

   1
  1        1
  1        2        1
  1        3        3        1
  通过观察可以看到:二维数组当i=j及i=0的时间是1;其他时间arr[ i ][ j ]=arr[ i-1 ][ j ]+arr[ i ][ j+1 ]
  下面来打印8行杨辉三角。
  1. //打印杨辉三角
  2. int main()
  3. {
  4.         int arr[8][8] = {0};
  5.         for (int m = 0; m < 8; m++)
  6.         {
  7.                 for (int n = 0; n < m + 1; n++)
  8.                 {
  9.                         if (m == n || n == 0)
  10.                         {
  11.                                 arr[m][n] = 1;
  12.                                 printf("%d ", arr[m][n]);
  13.                         }
  14.                         else
  15.                         {
  16.                                 arr[m][n] = arr[m - 1][n-1] + arr[m-1][n];
  17.                                 printf("%d ",arr[m][n]);
  18.                         }
  19.                 }
  20.                 printf("\n");
  21.         }
  22.         return 0;
  23. }
复制代码
模仿实现atoi

   atoi函数是用来舍去字符串前面的空格,找到第一个数字。
  eg:            -651safdafa这个字符串的返回值就是-651。
  写一个自界说函数来实现atoi功能
  此处利用isspace函数查抄空格,isdigit函数查抄数字。
  1. //实现atoi函数
  2. int my_atoi(char* p)
  3. {
  4.         //先将空格跳过
  5.         while (isspace(*p))
  6.                 p++;
  7.         int flag = 1;
  8.         //看有没有'+'或‘-’
  9.         if (*p == '-')
  10.         {
  11.                 flag = -1;
  12.                 p++;
  13.         }
  14.         if (*p == '+')
  15.                 p++;
  16.         //返回数字
  17.         int sum = 0;
  18.         while (isdigit(*p))
  19.         {
  20.                 sum = sum * 10 + flag*(*p - '0');
  21.                 p++;
  22.         }
  23.         return sum;
  24. }
  25. int main()
  26. {
  27.         char arr[100];
  28.         scanf("%s", arr);
  29.        
  30.         int c = my_atoi(arr);
  31.         printf("%d", c);
  32.         return 0;
  33. }
复制代码
 offsetof的模仿实现

   offserof是用来检察一个布局体成员的偏移量的;
  实现原理:offserof(s,m)   s是布局体,m是布局体成员。
  (size_t)&(((s*)0)->m)这就是offsetof的底层逻辑
  1)先将0的所在转换为布局体范例的,再在布局体中找到成员m,对成员m举行取所在,此时成员m的所在就是其相对于0的所在,0所在就是0,以是m的所在转换成size_t范例就是它的偏移量
  将一个数二进制的奇数位和偶数位举行互换

   先得到奇数和偶数位,再将奇数位<<1,偶数为>>1,再将奇偶归并
  1. //将一个数二进制的奇偶交换
  2. int main()
  3. {
  4.         int a = 616;
  5.         //先得到奇数位,用&
  6.         //01010101 01010101 01010101 01010101
  7.         //  55          55     55       55
  8.         int c = a & (0x55555555);
  9.         //得到偶数位
  10.         //10101010 10101010 10101010 10101010
  11.         //   AA       AA        AA       AA
  12.         int d = a & (0xAAAAAAAA);
  13.         //将奇数>>1,偶数<<1
  14.         c <<= 1, d >>= 1;
  15.         //将两者^
  16.         a = c ^ d;
  17.         return 0;
  18. }
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表