C语言:练习4

简介: C语言:练习4

 

题一:直接交换

交换两个变量(不创建临时变量)

不允许创建临时变量,交换两个整数的内容

情况如下:

按位异或(相同为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:指针中存储的是地址,地址可以看成一个数据,因此是可以比较大小的

目录
相关文章
|
7月前
|
C语言 数据安全/隐私保护
C语言初阶②(分支语句和循环语句)编程练习
C语言初阶②(分支语句和循环语句)编程练习
65 1
|
7月前
|
算法 C语言 容器
从C语言到C++_18(stack和queue的常用函数+相关练习)力扣(上)
从C语言到C++_18(stack和queue的常用函数+相关练习)力扣
51 0
|
7月前
|
C语言
C语言指针——练习
C语言指针——练习
|
7月前
|
编译器 C语言
C语言进阶⑪(指针上)(知识点和对应练习)回调函数模拟实现qsort。(下)
C语言进阶⑪(指针上)(知识点和对应练习)回调函数模拟实现qsort。
57 0
|
6月前
|
C语言
C语言练习代码第一篇
C语言练习代码第一篇
|
7月前
|
编译器 C语言 C++
从C语言到C++⑥(第二章_类和对象_中篇_续)大练习(日期类)+笔试选择题(下)
从C语言到C++⑥(第二章_类和对象_中篇_续)大练习(日期类)+笔试选择题
62 2
从C语言到C++⑥(第二章_类和对象_中篇_续)大练习(日期类)+笔试选择题(下)
|
7月前
|
存储 前端开发 算法
从C语言到C++_18(stack和queue的常用函数+相关练习)力扣(下)
从C语言到C++_18(stack和queue的常用函数+相关练习)力扣
27 0
|
6月前
|
C语言
|
6月前
|
编译器 C语言
|
6月前
|
C语言