IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 从0开始学c语言-26-操作符练习、指针练习、调试作业 -> 正文阅读

[C++知识库]从0开始学c语言-26-操作符练习、指针练习、调试作业

本人0基础开始学编程,我能学会的,你也一定可以,学会多少写多少。

下载安装请从官网入手,社区版本即可,这里主要使用的软件是VS2019,图标如下。

?上一篇:从0开始学c语言-25-浮点型在内存中的存储+数据储存练习_阿秋的阿秋不是阿秋的博客-CSDN博客

目录

操作符练习

前置后置++练习

求两个数二进制中不同位的个数

方法1 —— 使用异或^后的p & (1 << a)求不同位

方法2 —— 使用异或^后的a = a&(a-1)求不同位

打印整数二进制的奇数位和偶数位

写成函数

统计二进制中1的个数

方法1——用该数据模2,检测其是否能够被2整除

方法2 ——?n & (1 << i)

方法3——采用相邻的两个数据进行按位与运算

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

杀仁诛心题

求Sn=a+aa+aaa+aaaa+aaaaa的前5项之和,其中a是一个数字

打印水仙花数

代码1

代码2

指针练习

数组和指针

喝汽水问题

代码1

代码2

代码3

利用指针写一个函数实现字符串逆序

调试作业

找问题、解释问题

?调整奇数偶数顺序

模拟字符串实现

实现strcpy

实现strlen


操作符练习

对应文章

从0开始学c语言-18-操作符详解_阿秋的阿秋不是阿秋的博客-CSDN博客

前置后置++练习

int main()
{
	int a, b, c;
	a = 5;
	c = ++a;
	b = ++c, c++, ++a, a++;
	b += a++ + c;
	printf("a = %d b = %d c = %d\n:", a, b, c);
	return 0;
}

直接写过程,不引导。

    a = 5;
	c = ++a;
//c=6,a=6
	b = ++c, c++, ++a, a++;
//从左向右执行,b的结果为最后一个表达式
//b=7,7,7,7 
//后置++会先使用后++,所以c++和a++在等于b的时候并没有进行+1
//上面这个语句执行后的结果:b=7,c=8,a=8
	b += a++ + c;
//b = b + a++ + c = 7+8+8 = 23
//a = 9
	printf("a = %d b = %d c = %d\n:", a, b, c);
//a=9,b=23,c=8
	return 0;

求两个数二进制中不同位的个数

编程实现:两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同??
输入例子:1999 2299
输出例子 : 7

本质是求异或后的1有多少

方法1 —— 使用异或^后的p & (1 << a)求不同位

int main()
{
	int i = 0;
	int	j = 0;
	scanf("%d %d", &i, &j); //scanf需要指针类型的参数
	int p = i ^ j;
	//异或,不同为1
	//算有几个1,就是两个数二进制中不同位的个数
	int a = 0;
	int count = 0;
	for (a = 0; a < 32; a++)
	{
		if (p & (1 << a))
		{
			count++;
		}
	}
	printf("%d\n", count);
	return 0;
}

方法2 —— 使用异或^后的a = a&(a-1)求不同位

这种方法原理:

? ??举例子试试(tmp也就是a)
?? ??? ? tmp = 5 为真进入循环
? ? ? ? ? ? ? ? ? ? ?tmp - 0101 - 5
? ? ? ? ? ? ? ?? ?tmp-1 - 0100 - 4

? ?tmp & (tmp - 1) - 0100 - 5&4 - count++
?? ??? ?
?? ??? ? 下一次循环
? ? ? ? ? ? ? ? ? ? ? ? ? ?tmp - 0100 - 上一次tmp & (tmp - 1)的结果?
? ? ? ? ? ? ? ? ? ? ? ? tmp-1 - 0011 - 3
?? ??? ? tmp & (tmp - 1) - 0000 -?count++
?? ??? ?tmp=0为假,跳出循环

此时count为2,而 5当中 确实是有2个1。

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;
}

打印整数二进制的奇数位和偶数位

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

思路:二进制中只有0和1 ,那就是识别是0还是1。至于奇数和偶数位,不过是加一个循环(奇数位,偶数位)来识别是0还是1罢了。

int main()
{
	int a = 0;
	scanf("%d", &a);
	int i = 0;
	int count1 = 0; //验证一下是否走了16位,其实没必要
	int count2 = 0;
  //从低位置开始打印,高位置打印的话就改一下初始值和调整部分就行
	//打印奇数位
	for (i = 0; i < 32; i += 2)
	{
		if (a & (1 << i))
		{
			printf("%d ", 1);
		}
		else 
		{
			printf("%d ", 0);
		}
		
		count1++;
	}
	printf("\n");
	printf("%d\n",count1);
	
	//打印偶数位
	for (i = 1; i < 32; i += 2)
	{
		if (a & (1 << i))
		{
			printf("%d ", 1);
		}
		else 
		{
			printf("%d ", 0);
		}
		count2++; 
	}
	printf("\n");
	printf("%d\n", count2);
	return 0;
}

写成函数

void Printbit(int num)
{
	for (int i = 31; i >= 1; i -= 2)
	{
		printf("%d ", (num >> i) & 1);
	}
	printf("\n");

	for (int i = 30; i >= 0; i -= 2)
	{
		printf("%d ", (num >> i) & 1);
	}
	printf("\n");
}

统计二进制中1的个数

方法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;
}

上述方法缺陷:进行了大量的取模以及除法运算,取模和除法运算的效率本来就比较低。

方法2 ——?n & (1 << i)

int count_one_bit(unsigned int n)
{
	int count = 0;
	int i = 0;
	for (i = 0; i < 32; i++)
	{
		if ((n >> i) & 1)
			count++;
      //或者
		//if( n & (1 << i))
			//count++;
	}
	return count;
}

用位操作代替取模和除法运算,效率稍微比较高
缺陷:不论是什么数据,循环都要执行32次

方法3——采用相邻的两个数据进行按位与运算

此种方式,数据的二进制比特位中有几个1,循环就循环几次,而且中间采用了位运算,处理起来比较高效

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

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

本质是对 异或^操作符 的运用。

异或的结论:

1· 任何两个相同的数 异或 为0
2· 0和任何数字 异或 是它本身

int main()
{
	int a = 10;
	int b = 20;
	printf("交换前:a = %d b = %d\n", a, b);
	a = a ^ b;
	b = a ^ b;
	a = a ^ b;
	printf("交换后:a = %d b = %d\n", a, b);
	return 0;
}

杀仁诛心题

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

C语言中,0为假,非0即为真。
全局变量,没有给初始值时,编译其会默认将其初始化为0。
i的初始值为0,i--结果 - 1,i为整形,sizeof(i)求i类型大小是4,
按照此分析来看,结果应该是小于<,但是sizeof的返回值类型实际为无符号整形,因此编译器会自动将左侧 i 自动转换为无符号整形的数据,- 1对应的无符号整形是一个非常大的数字,超过4或者8,故实际应该为大于。

求Sn=a+aa+aaa+aaaa+aaaaa的前5项之和,其中a是一个数字

观察aa=a*10+a,aaa=aa*10+a,以此类推

原理就这,可写了

int main()
{
	int a = 0;
	int n = 0;
	int i = 0;
	int sum = 0;
	int tmp = 0;
	scanf("%d %d", &a, &n);
	for (i = 0; i < n; i++)
	{
		tmp = tmp * 10 + a;
		sum += tmp;
	}
	printf("%d\n", sum);

	return 0;
}

打印水仙花数

求出0~100000之间的所有“水仙花数”并输出。
“水仙花数”是指一个n位数,其各位数字的n次方之和确好等于该数本身,
如 : 153=1 ^ 3+5 ^ 3+3 ^ 3,则153是一个“水仙花数”

思路:

1 5 3分别是153、15、3 除10 的余数,所以可以考虑函数递归。3次方就是3位数,需要判断出是几位数,然后专门用一个函数或者变量用来求一个数的n次方,最后相加验证即可。

代码1

//输出i的j次方
int output(int i,int j)
{
	int put = 1;
	int time = 0;
	for (time = 0; time < j; time++)
	{
		put *= i;
	}
	return put;
}
//算  几次方 几位数
int count(int i)
{
	int count = 0;
	while (i > 9)
	{
		i /= 10;
		count++;
	}
	return count+1;
}
//进行水仙花数字的运算
int test(int i,int sum,int a)
{
	if (i > 9)
	{
		sum += output(i % 10,a);
		return test(i / 10, sum,a);
		//函数递归
	}
	else
	{
		sum += output(i % 10, a);
		return sum;
		//求和
	}
}
int main()
{
	int i = 0;
	for (i = 0; i < 1000000; i++)
	{
		int a = count(i); //几位数,几次方
		int sum = 0; //次方和
		//这两个值必须放在循环里
		//因为每个数的位数不同
		//且每次调用test函数前
		//sum必须=0,否则会受到上次循环的sum影响
		
		//等于本身则输出
		if (i == test(i, sum,a))
		{
			printf("%d\n", i);
		}
	}
	return 0;
}

代码2

int main()
{
	int i = 0;
	for (i = 0; i <= 999999; i++)
	{
		int count = 1;
		int tmp = i;
		int sum = 0;
		//判断i是否为水仙花数
		
		//1. 求判断数字的位数
		while (tmp / 10)
		{
			count++;
			tmp = tmp / 10;
		}

		//2. 计算每一位的次方和
		tmp = i;
		while (tmp)
		{
			//double pow( double x, double y );
			//pow计算次方和,返回类型double
			//所以强制类型转换
			sum += (int)pow(tmp % 10, count);
			tmp = tmp / 10;
		}

		//3. 判断
		if (sum == i)
			printf("%d\n", i);
	}
	return 0;
}

指针练习

从0开始学c语言-21-指针和数组、二级指针、指针数组_阿秋的阿秋不是阿秋的博客-CSDN博客

从0开始学c语言-20-指针与地址、指针类型、野指针、指针运算_阿秋的阿秋不是阿秋的博客-CSDN博客

数组和指针

int main()
{
	unsigned long pulArray[] = { 6,7,8,9,10 };
	unsigned long* pulPtr;
	pulPtr = pulArray;
	*(pulPtr + 3) += 3;
	printf("%d %d\n", *pulPtr, *(pulPtr + 3));
	return 0;
}

输出:6,12

牢记数组名是首元素地址就能做出来,搞清楚指针指在了哪里。

喝汽水问题

喝汽水,1瓶汽水1元,2个空瓶可以换一瓶汽水,给20元,可以多少汽水(编程实现)。

思路:?

1.20元首先可以喝20瓶,此时手中有20个空瓶子
2. 两个空瓶子可以喝一瓶,喝完之后,空瓶子剩余:empty/2(两个空瓶子换的喝完后产生的瓶子) + empty%2(手里剩下的空瓶)
3. 如果瓶子个数超过1个,可以继续换(这就是循环条件)

代码1

int num(int money)
{
	//花钱买到的汽水瓶数
	int num_bot = money;
	//空瓶数
	int emp_bot = num_bot;
	//总共瓶
	int sum_bot = emp_bot;
	while (emp_bot>1)
	{
		//加上 新换瓶数
		sum_bot += emp_bot/2;
		//看手里剩多少
		emp_bot = emp_bot / 2 + emp_bot % 2;
		
	}
	return sum_bot;
}
int main()
{
	int money = 0;
	printf("你有多少钱?请输入:>");
	scanf("%d", &money);
	printf("%d\n",num(money));
	return 0;
}

代码2

int main()
{
	int money = 0;
	int total = 0;
	int empty = 0;
	scanf("%d", &money);
	total = money;
	empty = money;
	while (empty > 1)
	{
		total += empty / 2;
		empty = empty / 2 + empty % 2;
	}
	printf("%d\n", total);
	return 0;
}

按照上述喝水和用瓶子换的规则的话,多次运行,其实就是个等差数列:money*2-1

代码3

记得考虑钱<=0的情况

int main()
{
	int money = 0;
	int total = 0;
	int empty = 0;
	scanf("%d", &money);
	if (money <= 0)
	{
		total = 0;
	}
	else
	{
		total = money * 2 - 1;
	}
	printf("total = %d\n", total);
	return 0;
}

利用指针写一个函数实现字符串逆序

void Reverse(char* str)
{
    char* left = str;
    char* right = str + strlen(str) - 1;
    while (left < right)
    {
        char temp = *left;
        *left = *right;
        *right = temp;
        ++left;
        --right;
    }
}

调试作业

从0开始学c语言-23-如何写出好(易于调试)的代码、模拟实现库函数:strcpy、strlen 、编程常见错误_阿秋的阿秋不是阿秋的博客-CSDN博客

找问题、解释问题

int main()
{
    int i = 0;
    int arr[] = {1,2,3,4,5,6,7,8,9,10};
    for(i=0; i<=12; i++)
    {
        arr[i] = 0;
        printf("hello bit\n");
    }
    return 0;
}

以上代码有两个问题:1.数组访问越界 ? 2. 死循环

访问越界不再解释,下标超出了。

每次访问arr数组i号位置时,都会将该位置内容设置为0,当访问到arr[12]时,也会将该位置内容设置为0,而位置恰好为i的位置,即a[12]恰巧将i设置为0,因此造成死循环。

?调整奇数偶数顺序

调整数组使奇数全部都位于偶数前面

输入一个整数数组,实现一个函数,来调整该数组中数字的顺序使得数组中所有的奇数位于数组的前半部分,所有偶数位于数组的后半部分。

思路:对半劈开,各自找到奇数或者偶数就交换。

void swap_arr(int arr[], int sz)
{
	int left = 0;
	int right = sz - 1;
	int tmp = 0;
	while (left < right)
	{
		// 从前往后,找到一个偶数,找到后停止
		while ((left < right) && (arr[left] % 2 == 1))
		{
			left++;
		}

		// 从后往前找,找一个奇数,找到后停止
		while ((left < right) && (arr[right] % 2 == 0))
		{
			right--;
		}

		// 如果偶数和奇数都找到,交换这两个数据的位置
		// 然后继续找,直到两个指针相遇
		if (left < right)
		{
			tmp = arr[left];
			arr[left] = arr[right];
			arr[right] = tmp;
		}
	}
}

模拟字符串实现

从0开始学c语言-23-如何写出好(易于调试)的代码、模拟实现库函数:strcpy、strlen 、编程常见错误_阿秋的阿秋不是阿秋的博客-CSDN博客

实现strcpy

char* my_strcpy(char* dst, const char* src)
{
	char* cp = dst;
	while (*cp++ = *src++);
	return(dst);
}

实现strlen

int my_strlen(const char* str)
{
	const char* eos = str;
	while (*eos++);
	return(eos - str - 1);
}

下一篇:从0开始学c语言-27-字符指针,指针数组和数组指针_阿秋的阿秋不是阿秋的博客-CSDN博客

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-09-25 23:05:06  更:2022-09-25 23:06:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 5:05:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码