C语言综合练习(1)

  1. 判断整形数二进制中有多少个1:
//主函数统一为:
```c
#include<stdio.h>
int main()
{
	int num1 = 1111;  //‭0100 0101 0111‬,6个1
	unsigned int num2 = -1111;  //‭0100 0101 0111‬,6个1
	unsigned int num3 = -1;  //无符号整型消除bug,表示正的整型的最大值
	printf("num1(1111)二进制中1的个数为:%d\n", count1(num1));
	printf("num1(-1111)二进制中1的个数为:%d\n", count2(num2));
	printf("num2(正整型最大数)二进制中1的个数为:%d\n", count3(num3));
	return 0;
}
/*将变量num的数据类型改为unsigned int (无符号整型),此时表示的是正的整型的最大值,所以当num=-1时,表示二
进制为32个1的正数,通过循环可以输出正确的个数。*/

①通过模2(%2、/2)的方法:
通过while循环, 依次判断二进制形式最后一位数字是否为1, 若为1则count++, 当最后一位变为0时循环结束。

int count1(unsigned int num)
{
	int count = 0;//计数
	while (num)
	{
		if (num % 2 == 1)  //取出二进制的最后一位
			count++;
		num = num / 2;  //右移去掉二进制的最后一位
	}
	return count;
}

②通过右移操作符(>>)及按位与操作符(&)实现:

int count2(unsigned int num)
{
	int count = 0;
	int i = 0;
	for (i = 0; i < 32; i++)  //运算一个数据需要循环32次,效率太低
	{
		if ((num >> i) & 1 == 1)  //每右移一位,同位均为1则执行count++
			count++;
	}
	return count;  
}

③通过按位与操作符(&)运算实现:

int count3(unsigned int num)
{
	int count = 0;
	int i = 0;
	while (num)
	{
		num = num & (num - 1);  //每执行一次就去掉了最右边的1,循环执行几次就有几个1
		count++;
	}
	return count;
}
  1. 分别输出一个数二进制序列中所有的偶数位和奇数位:
    ①数组实现
#include<stdio.h>
int main() {
	int arr[32];
	int i, count;
	int m = 98;
	printf("请输入一个数:\n");
	for (i = 0; m != 0; i++) {
		arr[i] = m % 2;
		m = m / 2;
		count = i + 1;
	}
	for (; count < 32; count++) {
		arr[count] = 0;
	}
	printf("二进制奇数位为:\n");
	for (i = 31; i >= 0; i -= 2) {
		printf("%-1d ", arr[i]);
	}
	printf("\n");
	printf("二进制偶数位为:\n");
	for (i = 30; i >= 0; i -= 2) {
		printf("%-1d ", arr[i]);
	}
	printf("\n");
	return 0;
}

②按位实现

int main() {
	int i, num = 98;
	for (i = 31; i >= 1; i -= 2)
		printf("%-2d", ((num >> i) & 1));  //偶数
	printf("\n");
	for (i = 30; i >= 0; i -= 2)
		printf("%-2d", ((num >> i) & 1));  //奇数
	return 0;
}
  1. 输出一个整数的每一位:
#include <stdio.h>
void show(int n) {
	if (n > 9)	show(n / 10);
	printf("%-3d", n % 10);
}
int main() {
	int num = 2019;
	printf("2019的各个位分别是:\n");
	show(num);
	return 0;
}
  1. 两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同?
#include<stdio.h>
int main() {
	int a = 1998, b = 2019, count = 0;
	int ret = a ^ b;
	while (ret) {
		ret = ret & (ret - 1);
		count++;
	}
	printf("不同位共有:%d位\n", count);
	return 0;
}
  1. A说:不是我;B说:是C;C说:是D;D说:C在胡说。
    已知3个人说了真话,1个人说的是假话;谁说了假话?
#include<stdio.h>
int main() {
	char killer;
	for (killer = 'A'; killer <= 'D'; killer++) {
		if (((killer != 'A') + (killer == 'C') + (killer == 'D') + (killer != 'D')) == 3)
			break;
	}
	printf("%c在胡说!\n", killer);
	return 0;
}
  1. 输出一个整数的二进制位翻转后的整数值(两种方法):
#include<stdio.h>
#include<math.h>
unsigned int reverse_bit1(unsigned int val) {
	int i = 0, j = 0, k = 0;
	for (i = 0; i < 32; i++) {  //val右移32位,补0
		j = j << 1;  //左移一位,保存前一位
		k = val & 1;  //取出最后一位
		val = val >> 1;  //值右移,取下一位
		j = k | j;  //最后一位赋给ret
	}
	printf("bit1函数的val的值:%d\n", val);
	return j;
}
unsigned int reverse_bit2(unsigned int val) {
	int i = 0, j = 0, k = 0;
	for (i = 0; i < 32; i++) {  //翻转权重,不改变原val的值
		k = k + ((val >> i) & 1)*pow((double)2, 31 - i);
	}
	printf("bit2函数val的值:%d\n", val);
	return k;
}
int main() {
	int i = 25;
	printf("25的二进制形式翻转后的数为:\n%u\n", reverse_bit1(i));
	printf("25的二进制形式翻转后的数为:\n%u\n", reverse_bit2(i));
	return 0;
}
  1. 不使用(a+b)/2这种方式,求两个数的平均值。
#include<stdio.h>
int main() {
	int a = 4;
	int b = 2;
	int c, d;
	c = (((a&b) << 1) + a ^ b) >> 1;
	d = ((a&b) + (a ^ b)>>1);
	printf("平均数为:%d\n", c);
	printf("平均数为:%d\n", d);
	return 0;
}
  1. 一组数据中只有一个数字出现了一次;其他所有数字都是成对出现的。找出这个数字。(使用位运算)
#include<stdio.h>
int main() {
	int i;
	int arr[7] = { 1,2,3,4,3,2,1 };
	int j = arr[0];
	for (i = 1; i < 7; i++) {
		j ^= arr[i];
	}
	printf("单独出现的数字是:%d\n", j);
	return 0;
}
  1. 数组中只有两个数是单独出现的,其余数都成对出现,找出这两个数
#include<stdio.h>
void show(int arr[], int len)
{
	int i ,ret = 0;  //记录所有值异或的结果
	int k = 0;  //记录ret二进制为第一个为1的位置
	int x = 0,y = 0;  //分别将两组值异或在x和y,得到2个没有相同数字的值
	for (i = 0; i < len; i++)
		ret ^= arr[i];  //将数组的所有值异或
	for (i = 0; i < 32; i++)
	{
		if ((ret >> i) & 1)
		{
			k = i;
			break;
		}
	}  //找到ret二进制为第一个为1的位置
	for (i = 0; i < len; i++)
	{//1011 1001
		if ((arr[i] >> k) & 1)
			x ^= arr[i];
		else
			y ^= arr[i];
	}  //分组异或
	printf("%d,%d\n", x, y);
}
int main()
{
	int arr[] = { 1, 9, 3, 1, 9, 3, 5, 40 };
	int len = sizeof(arr) / sizeof(arr[0]);
	show(arr, len);
	getchar();
	return 0;
}
  1. 有一个字符数组的内容为:“student a am i”,
    请你将数组的内容改为"i am a student".
    要求:不能使用库函数;只能开辟有限个空间(空间个数和字符串的长度无关)。
#include <stdio.h>
void reverse_str(char* str, int i, int j) {   //翻转一个字符串
	char tmp;
	for (; i < j; ++i, --j) {
		tmp = str[i];
		str[i] = str[j];
		str[j] = tmp;
	}
}
void reverse_word(char* str) {  //将目标字符串以单词为最小单元逆置
	int i = 0;
	int start = 0, end = 0;
	for (i = 0; str[i]; ++i) {
		if (str[i] == ' ') {  //以空格为判断条件
			end = i - 1;  //i现在指向空格,要逆置字符串需要将end前移一位。
			reverse_str(str, start, end);
			start = i + 1;
		}
	}
	reverse_str(str, start, i - 1);  //最后一个单词后面没有空格,所以要手动传参逆置。
	reverse_str(str, 0, i - 1);  //将整个字符串都逆置一次,就会的得到结果。
}
int main() {
	char str[] = "student a am I";
	reverse_word(str);
	puts(str);
	return 0;
}
没有限制的情况:
#include <stdio.h>
#include <string.h>
int main() 
{
	char str[] = "beijing. like I";
	char nstr[100];
	int i, start,len = strlen(str), total = 0;
	for (i = len - 1; i >= 0;) 
	{
		start = i;
		while (str[i] != ' '&&i >= 0)  //以空格为界,逆转每一段字符串
		{
			i--;
		}
		for (int j = i + 1; j <= start; j++) 
		{
			nstr[total++] = str[j];
		}
		nstr[total++] = ' ';
		i--;
	}
	nstr[total] = '\0';
	puts(nstr);
	return 0;
}
  1. A选手说:B第二,我第三;B选手说:我第二,E第四;C选手说:我第一,D第二;D选手说:C最后,我第三;E选手说:我第四,A第一;比赛结束后,每位选手都说对了一半,请编程确定比赛的名次。
#include<stdio.h>
int Forecast(int arr[]) {  //判断预测结果 
	if ((arr[1] == 2) + (arr[0] == 3) == 1
		&& (arr[1] == 2) + (arr[4] == 4) == 1
		&& (arr[2] == 1) + (arr[3] == 2) == 1
		&& (arr[2] == 5) + (arr[3] == 3) == 1
		&& (arr[4] == 4) + (arr[0] == 1) == 1)
		return 1;
	else
		return 0;
}
int Repetition(int arr[]) {  //判断数组内的值是否有重复的
	int i = 0;
	int j = 0;
	for (i = 0; i < 5; i++)
		for (j = i + 1; j < 5; j++) {
			if (arr[i] == arr[j])
				return 0;
		}
	return 1;
}
int main() {
	int arr[5] = { 0 };  //数组arr[0]~arr[4]分别代表A B C D E,arr[i]的值表示其名次
	for (arr[0] = 1; arr[0] <= 5; arr[0]++) {
		for (arr[1] = 1; arr[1] <= 5; arr[1]++) {
			for (arr[2] = 1; arr[2] <= 5; arr[2]++) {
				for (arr[3] = 1; arr[3] <= 5; arr[3]++) {
					for (arr[4] = 1; arr[4] <= 5; arr[4]++) {
						if (Forecast(arr) == 1)
							if (Repetition(arr) != 0)
								printf("A:为第%d名\nB:为第%d名\nC:为第%d名\nD:为第%d名\nE:为第%d名\n", arr[0], arr[1], arr[2], arr[3], arr[4]);
					}
				}
			}
		}
	}
	return 0;
}
  1. 输出杨辉三角形:
#include<stdio.h>
int main() {
	int num = 0, i, j;
	int arr[20][20];
	printf("请输入你想要的行数:\n");
	scanf("%d", &num);
	for (i = 0; i < num; i++) {
		for (j = 0; j <= i; j++) {
			arr[i][0] = 1;
			arr[i][j] = 1;
		}
	}
	for (i = 1; i < num; i++) {
		for (j = 1; j < i; j++) {
			arr[i][j] = arr[i - 1][j - 1] + arr[i - 1][j];
		}
	}
	printf("所需要的杨辉三角为:");
	for (i = 0; i < num; i++) {
		for (j = 0; j < i; j++) {
			printf("%-4d", arr[i][j]);
		}
		printf("\n");
	}
	return 0;
}
  1. 调整数组使奇数全部都位于偶数前面;输入一个整数数组,实现一个函数,来调整该数组中数字的顺序使得数组中所有的奇数位于数组的前半部分,所有偶数位于数组的后半部分:
#include<stdio.h>
int show(int *a, int i, int j, int len) {
	while (i < j) {
		while ((i < j) && (a[i] % 2 != 0))  //从头开始找第一个偶数
			i++;
		while ((i < j) && (a[j] % 2 != 1))  //从尾开始找第一个奇数
			j--;
		if (i < j) {
			int temp = a[i];  //交换找到的从头开始的第一个偶数;与从尾开始的第一个奇数
			a[i] = a[j];
			a[j] = temp;
		}
	}
	for (i = 0; i < len; i++)
		printf("%d ", a[i]);
}
int main() {
	int a[] = { 44,16,59,64,25,37,26,19,43,65,19,64,11 };
	show(a, 0, sizeof(a) / sizeof(a[1]) - 1, sizeof(a) / sizeof(a[1]));  //函数址传递数组
	return 0;
}
  1. 一个二维数组,数组的每行从左到右是递增的,每列从上到下是递增的,在这样的数组中查找一个数字是否存在:(时间复杂度小于O(N);杨氏矩阵)
    数组:
1 2 3   1 3 4   1 2 3
2 3 4   2 4 5   4 5 6
3 4 5   4 5 6   7 8 9
#include<stdio.h>
#define ROW 3
#define COL 3
int Findnum(int arr[ROW][COL], int row, int col, int key) {
	int left = 0;
	int right = col - 1;
	while ((left >= 0) && (right < col) && (left < ROW)) {
		if ((arr[left][right] < key))  //如果这个数字小于key,则向后移一位;
			left++;
		if (arr[left][right] > key)  //如果这个数字小于key,则向前移一位;
			right--;
		if (arr[left][right] == key) {  //如果这个数字等于key,则返回1;
			printf("下标为%d,%d\n", left, right);
			return 1;
		}
	}  //否则返回1;
	return 0;
}
int main() {
	int arr[ROW][COL] = { 1,2,3,4,5,6,7,8,9 };
	int key = 9;	//找出这个数组中9这个数字;
	int ret = Findnum(arr, ROW, COL, key);	//找到了返回1,找不到返回0;
	if (1 == ret)
		printf("找到了!\n");
	if (0 == ret)
		printf("找不到!\n");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值