c语言经典基础题一(位运算符及递归等)

关于c语言的经典题目,有利于巩固基础,之后会持续更新!


前言

一些比较经典的题目,我会继续更新下去,希望能够给大家一些帮助!


提示:以下是本篇文章正文内容

一、写代码有两种类型:

IO型:从main函数开始写,要写输入、计算、输出。
接口型:不需要写主函数,默认主函数就是存在的,只需要完成函数。

二、一些位运算符题目

1.统计二进制中1的个数

方法一:利用余数和除的方法得到二进制数的每一位。然后用if即可。

int NumberOf1(unsigned int n) 
{
	int count = 0;
	while (n)	
	{
		if (n % 2 == 1)
			count++;
		n = n / 2;
	}
	return count;
}

方法二:利用>>二进制右移i位和与(&)1,进行判断是否为1即可判断二进制中1的存在。

int NumberOf2(int n)
{
	int i = 0;
	int count = 0;
	for (i = 0; i < 32; i++)
	{
		if (((n >> i) & 1) == 1)
		{
			count++;
		}
	}
	return count;

方法三:n的二进制&n-1(因为n-1就是使n最右边的1退位),每一次都使得最右边的1不见,因此每进行一次就去掉了1个。由此可知,进行了几次,它原来就有几个1。

int NumberOf1(int n)
{
	int count = 0;
	while (n)
	{
		n = n & (n - 1);
		count++;
	}
	return count;

扩展:n = n & (n - 1)也可用于判断n是否是2的k次方。
因为2的k次方本身只有1个1,利用if( n & (n - 1)==0)即可。

2.获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出二进制序列

从高位到低位打印。按1-32记录奇偶,因此0位为奇数,31位为偶数。
代码如下:

void Print(int n)
{
	int i = 0;
	printf("奇数位: ");
	for (i = 30; i >=0; i -= 2)
	{
		printf("%d ", (n >> i) & 1);
	}
	printf("\n");
	
	printf("偶数位: ");
	for (i = 31; i >= 1; i -= 2)
	{
		printf("%d ", (n >> i) & 1);
	}
	printf("\n");
}

int main()
{
	int n = 0;
	scanf("%d", &n);
	Print(n);//打印n的2进制中的所有奇数位和所有的偶数位
	return 0;
}

3.两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同?

方法一:利用(m>>i)&1进行比较。

int count_diff_one(int m, int n)
{
	int i = 0;
	int count = 0;
	for (i = 0; i < 32; i++)
	{
		if (((m >> i) & 1) != ((n >> i) & 1))
		{
			count++;
		}
	}
	return count;
}

方法二:异或操作符:相同为0,相异为1

int count_diff_one(int m, int n)
{
	int count = 0;
	int tmp = m ^ n;
	//统计tmp的二进制中有几个1
	while (tmp)
	{
		tmp = tmp & (tmp - 1);
		count++;
	}
	return count;
}

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

#include<stdio.h>

void swrap(int &a,int &b)//异或,相同为0,相异为1
{
	a = a ^ b;

	b= a ^ b;//b=a^b^b=a

	a = a ^ b;//a^b^a=b
}

int main()
{
	int a, b;
	scanf("%d %d", &a, &b);
	swrap(a,b);
	printf("%d %d", a, b);
}

三、递归问题

1.小乐乐走台阶一次可以走一阶或两阶,问有多少种走法?

int Fib(int n)
{
    if (n <= 2)
        return n;
    else
        return Fib(n - 1) + Fib(n - 2);
}

2.正整数n表示为六进制

void Print(int n)
{
	if(n>5)
	{
		Print(n/6);
	}
	printf("%d",n%6);
}
int main()
{
	int n=0;
	scanf("%d",&n);
	Print(n);
	return 0;
}

四、经典题目

1.获得每年某月天数

此方法用数组储存月份比if 或switch-case更加简便。
在数组里面添加0,是为了使下标1就对于1月等。

int get_days_of_month(int y, int m)
{
    int days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
    //                1  2  3  4  5  6  7  8  9  10 11 12
    int day = days[m];
    if ((m == 2) && (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0)))
    {
        day++;
    }
   return day;
}

int main() {
    int y = 0;
    int m = 0;
    while (scanf("%d %d", &y, &m) == 2)
    {
        int ret = get_days_of_month(y, m);
       printf("%d\n", ret);
    }

    return 0;
}

2.下面代码的结果是:

#include <stdio.h>
int i;
int main()
{
    i--;
    if (i > sizeof(i))
    {
        printf(">\n");
    }
    else
    {
        printf("<\n");
    }
    return 0; 
}

A.>
B.<
C.不输出
D.程序有问题
解答:1.全局变量,没有给初始值时,编译其会默认将其初始化为0。
2.i的初始值为0,i–结果-1,i为整形,sizeof(i)求i类型大小是4,按照此分析来看,结果应该选择B。
3.但是sizeof的返回值类型实际为无符号整形,因此编译器会自动将左侧i自动转换为无符号整形的数据,-1对应的无符号整形是一个非常大的数字,超过4或者8,故实际应该选择A

3.矩阵转置

#include <stdio.h>
int main()
 {
    int n, m, i, j;
    int A[10][10];
    scanf("%d %d", &n, &m);
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < m; j++)
        {
            scanf("%d", &A[i][j]);
        }
    }
    for (i = 0; i < m; i++)
    {
        for (j = 0; j < n; j++)
        {
            printf("%d ", A[j][i]);
        }
        printf("\n");
    }
    return 0;

}

4.序列中删除指定数字

#include <stdio.h> 
int main()
{
    int n = 0;
    int arr[50] = {0};
    int del = 0;
    scanf("%d", &n);
    int i = 0;
    for(i=0; i<n; i++)
    {
        scanf("%d", &arr[i]);
    }
    scanf("%d", &del);//要删除的元素
    int j = 0;
    for(i=0; i<n; i++)
    {
        if(arr[i] != del)
        {
            arr[j++] = arr[i];
        }
    }
    
    for(i=0; i<j; i++)
    {
        printf("%d ", arr[i]);    
    }
    return 0;
}

如果有错误或者疑惑,欢迎大家在评论区多多指教!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值