c语言学习笔记(持续更新中)

本文部分代码可能缺少#include <stdio.h>

请大家在使用时自行加上!!!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XZjcCxbU-1646359222366)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220228182413422.png)]
一个.c文件中只能有一个main函数;一个工程中可以有多个.c文件。

1.数据类型

char字符数据类型
short短整型
int整型
long长整型
long long更长的整型
float单精度浮点数
double双精度浮点数

查看数据类型字节数(针对32位或者64位编译器)
在这里插入图片描述
int类型可表示的最大整数为2^31-1=65535
说明:明明是32个Bit为什么是31次方,因为最高位是符号位,不参与计算。那为什么要减1呢?因为我们在计算时把0也算进去了。打个比方,假如是8位的编译器,可以存128个,但是正数从零开始,到127,如果要求最大数就要减1。

那么针对16位的编译器

各种类型占多少字节呢?
对于16位的(signed int)整型最大数可表示为2^15-1=32767
在这里插入图片描述

计算机中单位:

bit - 比特位 byte - 字节 =8bit kb - 1024byte mb - 1024kb

gb - 1024mb

2.变量、常量

2.1变量

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q1jA1JHG-1646359222368)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220228192812866.png)]

变量分类:局部变量、全局变量

//全局变量 - {}外部定义
int a = 100;
int main()
{
	//局部变量 - {}内部定义
	//当局部变量和全局变量名字冲突的情况下,局部优先
	//不建议把全局变量和局部变量名字写成一样
	int a = 10;
	printf("a = %d\n",a);//a = 10
	return 0;
}

2.1.1作用域和生命周期

在这里插入图片描述

除此之外还可以使用两个.c文件,只需声明变量即可
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QeQZ9s3u-1646359222370)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220301101718164.png)]

生命周期
变量的生命周期:变量的创建和销毁之间的时间段
局部变量的生命周期:进入局部范围生命开始,出局部范围生命结束
全局变量的生命周期:整个程序的生命周期

2.2 常量

2.2.1 字面常量

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uPqof9Me-1646359222371)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220301103016768.png)]
无实际含义,但存在。

2.2.2 const修饰的常变量

a为变量,定义a=20后打印出a=20

int main()
{
	//a为常变量 - 具有常属性(不能改变的属性)
	const int a = 10;
	printf("%d\n",a);
	return 0;
}

被const修饰以后,a不能再修改
在这里插入图片描述
**误区:**在创建数组时需要使用常量,此时int n = 10;n为变量,纵使使用const,n为常变量但n的本质还是一个变量,所以报错。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RCEDrVh8-1646359222374)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220301104671773.png)]

2.2.3 #define定义的标识符常量

#include <stdio.h>
#define min 100
int main()
{
	int a = min;
	//min = 2000;//标识符常量不能修改
	printf("a = %d\n",a);
	return 0;
}

2.2.4 枚举常量

在这里插入图片描述
可以赋初值,当赋2时,就是2,3,4
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r0OXWP5F-1646359222375)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220301113033787.png)]

3. 字符串

定义:双引号引起的一串字符

注:字符串以\0结尾为标志
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lxWHb3WP-1646359222376)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220301137236988.png)]
arr1的字符串是abc\0,打印到c后有\0,不再继续打印
arr2打印abc后后面的数字未知,继续打印
我们手动添加一个\0后充分证明\0是字符串的结束标志
在这里插入图片描述
当我们计算字符串长度时,\0不算字符串内容,仅仅只是一个标志。

引入strlen时会报错,只需在前面插入

#include <string.h>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i0jIySgT-1646359222377)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220301137838466.png)]
此时arr1的长度为3,arr2的长度为一个随机值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3gkfhwtB-1646359222379)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220301141077947.png)]

4.转义字符

#include <stdio.h>
int main()
{
	printf("(are you ok??)"); //??)  -  ]  三字母词
    //printf("are you ok\?\?)");//使用\转义,这样?就能够被顺利打印出
	return 0;
}//部分编译器以无法显示出三字母词
printf("%d",100);打印整型
printf("%c",'a');//打印字符
printf("%s","ab");//打印字符串

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

字符串长度

strlen遇到 \0 停止读取
\t\v\0will\n 字符串长度为3

\t一个转义字符,算1个
\\t 拆分为 \ 和 \t,\ 是防止 \ 被转义,算一个,\t 算一个,共两个
\t拆分为 \ 和 t,也算两个
\328 一般 \ddd 表示八进制,但前提是每一位都要小于8(八进制没有8),所以这里将\328拆分为 \32 和 8算成两位
所以结果为13

易错:若八进制为\182 那么就拆分为\1 和82,一共就是三位,\1、8、2

#include <stdio.h>
#include <string.h>
int main()
{
    printf("%d\n",strlen("c:\tes\\\t\328\\t.c"));
	return 0;
}

4.1 进制转换

(1)十进制转化为八进制

[1].67D=101Q

67=26+20=1 000 001=1 0 1(先转化为二进制)

1000000 1

[2].10.68D=Q(精确到小数点后2位)

整数部分按照上述[1]的方法,小数部分精确到小数点后几位,小数部分就乘以几次8,然后从上往下的顺序读取。

10D=23+21=1 010=12Q

0.68*8=7.44 取7

0.44*8=3.72 取3

10.68D=12.73Q

(2)八进制转化为十进制

130Q=88D

1 3 0 =1 *8^2+3 *8^1+0 *8^0=88

(3)十六进制转十进制

23daH=D

23da=2 *16^3+3 *16^2+d *16^1+a *16^0=9178D

(4)十进制转为十六进制

27.68H=D(精确到小数点后2位)

27=24+23+2^1=1 1010=19

小数部分0.68*16=10.88 取a

0.88*16=14.08 取e

27.68H=19.aeD

5.数组

5.1 一维数组的创建和初始化

5.1.1 创建

定义:一组相同类型的元素的集合
在这里插入图片描述

int arr[10];
//输入数组时,没有&
scanf("%s",arr);//数组名本就是一个地址,没有&

在这里插入图片描述
在这里插入图片描述
分析:ch5打印到\0停止;而ch6从b开始往后打印时,一直没有遇到\0,便一直打印知道栈溢出
在这里插入图片描述

C99 标准中引入一个概念:变成数组
支持在数组创建的时候,用变量指定大小,但数组不能初始化;部分编译器支持此操作。

int n = 10;
int arr[n];

在这里插入图片描述

5.1.2 初始化

在这里插入图片描述

5.2 一维数组的使用

在这里插入图片描述

int sz sizeof(arr) / sizeof(arr[0]);//计算数组个数

5.3 一维数组在内存中的存储

在这里插入图片描述
1.一维数组在内存中连续存放
2.随着数组下标的增长,地址由低到高变化
在这里插入图片描述
在这里插入图片描述

5.4 二维数组的创建和初始化

在这里插入图片描述
在这里插入图片描述

5.5 二维数组在内存中的存储

在这里插入图片描述

二维数组在内存中也是连续存放
一行内部连续,换行也是连续。

5.6 数组作为函数参数

数组传参。调用部分(实参部分)写的数组名,形参部分,既可以 写成数组,也可以写成指针,但本质上都是指针,数组传参时传过去的时数组首元素地址
在这里插入图片描述

有两个例外

  1. sizeof(数组名) - 数组名表示整个数组 - 计算整个数组的单位大小(单位是字节)
  2. &数组名 - 数组名表示整个数组 - 取出的是整个数组的地址
    在这里插入图片描述
    练习:将数组按照升序输出
void bubble_sort(int arr[],int sz)
{
	int i = 0;
	//趟数
	for (i = 0;i < sz - 1;i++)
	{
		int j = 0;
		//一个数字一趟交换次数
		for(j = 0;j < sz - 1 - i;j++)
		{
			if (arr[j] > arr[j+1])
			{
				int tmp = arr[j+1];
				arr[j+1] = arr[j];
				arr[j] = tmp;
			}
		}
	}
	
}

#include <stdio.h>
int main()
{
	int arr[] = {10,9,8,7,6,5,4,3,2,1};
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort (arr,sz);
	//printf("%d",ret);
	return 0;
}

在这里插入图片描述

6.函数

6.1 函数是什么

在这里插入图片描述

6.2 函数分类

(1)库函数;(2)自定义函数

6.2.1 库函数

编译器发布的时候携带了一些库函数,在实际操作中,频繁大量出现的一些操作不需要进行实现,提高我们的效率。

https://www.cplusplus.com/
https://msdn.itellyou.cn/

在这里插入图片描述
以strcpy库函数为例

#include <string.h> //调用头文件
int main()
{
	char arr1[20] = {};
	char arr2[] = {"abc"};
	strcpy(arr1,arr2);//strcpy作用是copy值
	printf("%s",arr1);
	return 0;
}

在这里插入图片描述

6.2.2 自定义函数

自定义函数和库函数一样,有函数名,返回值类型和函数参数。但不一样的是这些都是我们可以自己设计的。

比较两数大小
int max(int x,int y)
{
	if(x>y)
		return x;
	else
		return y;
}
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d",&a,&b);
	int mm = max(a,b);
	printf("%d\n",mm);
	return 0;
}

两数进行交换
在这里插入图片描述
由此可见并没有交换成功。
分析:在main的主函数中,a = 10,b = 20 都有各自的地址,而在test函数中的x,y也有各自的地址,交换x,y的值与a,b的值并无瓜葛,因此交换失败。这时我们需要使用指针变量解决问题。
在这里插入图片描述
使用指针变量
在这里插入图片描述

6.3 函数参数

函数定义时使用的参数为形式参数,
a,b真实传给swap1和swap2的参数为实际参数
在这里插入图片描述
在这里插入图片描述

6.3.1 实际参数

实际参数也可以为表达式,函数等
在这里插入图片描述

6.3.2 形式参数

形式参数在函数调用以后就销毁。

6.4 函数调用

分类:传值调用;传址调用
传值调用:形参与实参之间没有什么必然联系,只是把值传过去。
传址调用:函数内部可操作和函数外部,形参与实参之间有联系,这时就为传址调用。
在这里插入图片描述

练习1:使用函数打印出100-200之间的素数
int ss (int n)
{
	int j = 0;//此时上面已经赋n为Int类型,无需再次赋值
	for (j = 2;j < n;j++)
	{
		if (n % j == 0)
		{
			return 0;
		}
	}
	return 1;
	
}

int main()
{
	int i = 0;
	for(i = 100;i <= 200;i++)
	{
		if(ss(i) == 1)
		{
			printf("%d ",i);
		}
	}
	return 0;
}
练习2:打印出1000-2000之间的闰年
int ryear(int y)
{
	if(((y % 4 == 0) && (y % 100 != 0))||(y % 400 == 0))
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

int main()
{
	int n = 0;
	int x = 0;
	int count = 0;
	for (n = 1000;n <=2000;n++)
	{
		if (ryear(n) == 1)
		{
			count ++;
			printf("%d ",n);
		}
	}
	printf("count = %d\n",count);
	return 0;
}

**易错点:**使用下面这种写法,例如1600,能被4整除以后进入下一个if语句,但也可以被100整除,所以直接return 0,但实际上也可以被400整除,是满足闰年条件的。因为在进入一个if语句之后便不会再进行下面的语句。
在这里插入图片描述
在这里插入图片描述

练习3:实现整型有序数列的二分查找
int test (int a[],int k,int s)
{
	int left = 0;
	int right = s - 1;
	while(left <= right)
	{
		int mid = (left+right) / 2;
		if(a[mid] < k)
		{
			left = mid + 1;
		}	
		else if (a[mid] > k)
		{	
			right = mid - 1;
		}
		else
		{
			return mid;
		}	
	}
	return -1;
}

int main()
{
	int arr[] = {1,2,3,4,5,6,7,8,9,10};
	int key = 7;
	int ss = sizeof(arr) / sizeof(arr[0]);
	int asd = test (arr, key ,ss);//数组,要找的数,数组个数
	if (asd == -1)
	{
		printf("找不到\n");
	}
	else
	{
		printf("找到了,下标为:%d\n",asd);
	}
	return 0;
}

在这里插入图片描述

练习4:每使用一次函数就加1
void add(int* pa)
{
	(*pa)++;
}

int main()
{
	int p = 0;
	add(&p);
	add(&p);
	add(&p);//传址调用
	printf("%d ",p);
	return 0;
}

6.5 函数的嵌套调用和链式访问

6.5.1 嵌套调用

误区:一个函数内不能定义一个函数

void two()
{
	printf("hahaha\n");
}

int one()
{
	int i = 0;
	for(i = 1;i <= 3;i++)
	{
		two();
	}
}

int main()
{
	one();//打印三次hahaha
	return 0;
}

6.5.2 链式访问

把一个函数的返回值作为另一个函数的参数。

#include <string.h>
#include <stdio.h>
int main()
{
	int len = strlen("asdf");
	printf("%d\n",len);
	
	//链式访问
	printf("%d\n",strlen("asdf"));
	return 0;
}

在这里插入图片描述
分析:
我们先了解printf函数
在这里插入图片描述
因此,在完成printf(“%d”,43)后,第二个printf(“%d”,2).而最外面的第一个printf(“%d”,2),打印出来为1。

6.6 函数的声明和定义

  • 函数先声明后使用。当函数定义在main函数之前时,不用声明
    在这里插入图片描述
    在这里插入图片描述

  • 函数声明一般放在头文件

例如在实际生活中,一个工程由几个工程师同时完成,当某工程师想要汇总所有人的代码时,直接调用头文件。
在这里插入图片描述
在这里插入图片描述
优点:当我们不想把.c文件直接给其他人但又想让他用到时,用.c和.h文件创建一个静态库,将静态库和,h文件给出去,使用#include <文件名.h>声明,#pragma导入静态库,即可实现函数功能。
在这里插入图片描述

6.7 函数递归

在这里插入图片描述
练习1:要求输入一个无符号整数,按照输入1234,1 2 3 4的模式输出
分析:1234
1234%10 4
1234/10 =123 % 10 = 3
1234/10 =123/10 = 12 % 10 = 2
1234/10 =123/10 =12 ./ 10 = 1 % 10 = 1
在这里插入图片描述
进行递归时函数内部具体操作见下图。
在这里插入图片描述
练习2:编写函数求字符串长度,不允许函数创建临时变量

int ss(char* arr)
{
	if(*arr != '\0')
	{
		return 1+ss(arr+1);
	}
	else
	{
		return 0;
	}
}

int main()
{
	char arr[] = "two";
	printf("%d",ss(arr));
	return 0;
}

在这里插入图片描述
递归与迭代
练习1 求阶乘

方法一:递归写法
int jc(int m)
{
	if(m <=1)
	{
		return 1;
	}
	else
	{
		return m * jc(m-1);
	}
}

int main()
{
	int n = 0;
	scanf("%d",&n);
	printf("%d\n",jc(n));
	return 0;
}


方法二:迭代法
int main()
{
	int n = 0;
	scanf("%d",&n);
	int i;
	int sum = 1;
	//循环也被称为迭代
	for (i = 1;i <= n;i++)
	{
		sum = i * sum;
	}
	printf("%d\n",sum);
	return 0;
}

练习2 斐波那契数列

#include <stdio.h>
int fib(int n)
{
	if (n <= 2)
		return 1;
	else
		return fib(n-1)+fib(n-2);
}

int main()
{
	int n = 0;
	scanf("%d",&n);
	int te = fib(n);
	printf("%d\n",te);
	return 0;
}

7. 操作符

7.1 算数操作符

在这里插入图片描述
% 操作符两端必须为整数
在这里插入图片描述
在这里插入图片描述

7.2 移位操作符

左移操作符<<
右移操作符>>

7.2.1 左移操作符

#include <stdio.h>
int main()
{
	int a = 3;
	//左移操作符针对的是二进制位
	int b = a << 1;
	printf("%d\n",b);
	return 0;
}

a=3是int类型,int类型是4个字节,一个字节8个bit,一共为32bit,a转化为二进制为00000000000000000000000000000011,整体向左移一位,右边空缺用0补充,那么结果为00000000000000000000000000000110,b=6
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-31S0mIcr-1646359222382)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220302093801497.png)]
整体原则就是,左边丢弃,右边补0

7.2.2 右移操作符

1.算术右移
右边丢弃,左边补原符号位
当为正时,符号位本就为0,为负数时为1

整数在内存中存储的是补码

一个整数在二进制中的表示有三种:原码,反码,补码

负数原码,反码,补码的计算,以-1为例:

  • 原码:-1的二进制位
    整数最高位表示符号位,最高位1表示负数
    10000000 00000000 00000000 00000001(原码)

  • 反码:符号位不变,其他位按位取反,1变0,0变1
    11111111 11111111 11111111 11111110(反码)

  • 补码:反码二进制序列加1
    11111111 11111111 11111111 11111111(补码)
    在这里插入图片描述

对于正整数,原码,反码,补码相同

2.逻辑右移
右边丢弃,左边补0

去判断当前右移操作符为逻辑右移还是算术右移时,只需使用负数,以-1为例,输出为-1是说明32个bit全为1,左边最高位补原符号位,属于算术右移。
在这里插入图片描述

7.3 位操作符

位操作符含义
&按位与
|按位或
^按位异或
操作数必须为整数
在这里插入图片描述
0 ^ a = a;
a ^ a = 0

练习:在不借助第三个变量的情况下,交换a = 3,b = 5的值

方法一:
#include <stdio.h>
int main()
{
	int a = 3;
	int b = 5;
	printf("a = %d,b = %d\n",a,b);
	a = a + b;
	b = a - b;
	a = a - b;
	printf("a = %d,b = %d",a,b);
	return 0;
}
缺点:数字太大可能产生溢出

方法二:
#include <stdio.h>
int main()
{
	int a = 3;
	int b = 5;
	printf("a = %d,b = %d\n",a,b);
	a = a ^ b;
	b = a ^ b;
	a = a ^ b;
	printf("a = %d,b = %d",a,b);
	return 0;
}

在这里插入图片描述
分析:
a = a ^ b;
b = a ^ b = a ^ b ^ b = a ^ 0 = a;
a = a ^ b = a ^ b ^ a = b;

7.4 赋值操作符

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pOIzQlsJ-1646359222382)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220302094379737.png)]

=  赋值
== 判断

7.5 单目操作符

a + b  //+ 双目操作符,有两个操作数

单目操作符:只有一个操作数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GDntMTth-1646359222383)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220302094347644.png)]

7.5.1 !操作符

在这里插入图片描述

7.5.2 sizeof操作符讲解

在这里插入图片描述
在这里插入图片描述
分析:打印第一个值时,a + 2结果放s中,sizeof结果取决于s,不论a类型是否为整型,short字节数为2;
一个.c文件到一个.exe文件需要经历编译>>链接>>运行三个阶段,而s = a + 2在编译阶段已经完成,到运行时只运行了打印2,因此在执行打印s的操作时,s的值并没有改变,还是5。

char c[] ={"china"} //sizeof c = 6  \0也计算在内
char c[] = {'c'.'h','i','n','a'};//sizeof c = 5

7.5.3 ~操作符

int main()
{
	int a = 0;
	//~按(二进制)位取反,0变1,1变0
	printf("%d\n",~a);
	return 0;
}

对于int a=0,二进制为00000000 00000000 00000000 00000000

~a为 11111111 11111111 11111111 11111111(补码)

而%d输出的是原码,(原码按位取反符号位不变,得到反码,加一得到补码。相反补码减一,按位取反得到原码。)因此需要将~a减1,符号位不变,按位取反,

得到10000000 00000000 00000000 00000001,最终打印出-1
具体原码,反码,补码的介绍请参考7.2.2 右移操作符。

7.5.4 前置++ 后置++

int main()
{
	int a = 1;
	int b = a++;//后置++,先使用,后++
	printf("%d\n",b);//b=1
	printf("%d\n",a);//a=2
		
	int c = 10;
	int d = ++c;//前置++,先++,后使用
	printf("%d\n",d);//d=11
	printf("%d\n",c);//c=11
	return 0;
}//前置--  后置--  同理

7.5.5 & 和 * 操作符

在这里插入图片描述
在这里插入图片描述

7.5.6 (类型)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kd0fhcHa-1646359222384)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220302112600981.png)]
3.14本质上是一个double类型,因此需要强制类型转换。

int main()
{
	int a =(int)3.14;
	printf("%d\n",a);
	return 0;
}

下面这个例子有异曲同工之妙

#include <stdio.h>
int main()
{
	int a[] = {10000,5000,2000,1000,500,200};
	int b[] = {100,50,25,10,5,1};
	double w = 0;
	int i;
	scanf("%lf",&w);
	int n = 100 * w;
	printf("NOTAS:\n");
	for (i = 0;i < 6;i++)
	{
		printf("%d nota(s) de R$ %d.00\n",n / a[i],a[i] /  100);
		n %= a[i];
	}
	
	printf("MOEDAS:\n");
	for (i = 0;i < 6;i++)
	{
		printf("%d moeda(s) de R$ %.2lf\n",n / b[i],b[i] / 100.0);
		//%lf不对结果本质进行改变,%.2lf出现的意义就是将结果保留两位小数
		//若想将结果变为浮点数,就需要将被减数进行强制转换,原先是整型,100.0强制变为浮点型,随后输出的结果就是浮点型,随后使用%.2lf保留两位小数
		n %= b[i];
	}
	return 0;
} 

7.6 关系操作符

>=大于等于
<=小于等于
!=不等于
==测试是否等于
两个字符串的比较不能用==

7.7 逻辑操作符

&&逻辑与
||逻辑或
可用于if语句
在这里插入图片描述

7.8 条件操作符(三目操作符)

?    :
exp1 ? exp 2 : exp 3

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d7T8O2j3-1646359222386)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220302114273681.png)]

7.9 逗号表达式

int main()
{
	int a = 1;
	int b = 2;
	int c = 3;
	int d = (b = a + 2,c = b - 1,a = c + 2);
	//逗号表达式从左向右计算,前面表达式可能影响后面表达式
	//整个表达式结果是最后一个表达式结果
	printf("%d\n",d);//d=4
	return 0;
}

在这里插入图片描述

7.10下标引用、函数调用、结构成员

  • 下标引用
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YcJ3cux3-1646359222386)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220302117311482.png)]
  • 函数调用
    在这里插入图片描述
  • 结构成员

结构体.成员名
在这里插入图片描述

7.11 整型提升

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

7.12 算术转换

精度由高到低排列:
long double
double
float
unsigned long int
long int
unsigned int
int

当操作数属于不同类型时,就需要将其中一个操作数的类型向另一个操作数类型转换,否则无法正常运行,通常是由精度低的向高的转换。
在这里插入图片描述

操作符属性
1.优先级
2.结合性
3.控制求值顺序
在这里插入图片描述

8. 关键字

c语言的关键字

1.c语言提供,不能自己创建关键字

2.变量名不能是关键字

常见关键字
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XgDjHWX8-1646359222387)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220302137722637.png)]
误区:define 使用 #define

include 使用#include 均为预处理指令

auto 是自动的 - 每个局部变量都是auto修饰的

extern 用来申明外部符号

register 寄存器关键字

#include <stdio.h>
int main()
{
    //大量频繁被使用的数据,存放在寄存器中,提升效率
    register int num = 1;//建议num的值存到寄存器中,是否存在寄存器中由编译器决定
    return 0;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tnlm9e7B-1646359222388)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220302140847743.png)]

8.1 typedef 类型重定义

#include <stdio.h>
typedef unsigned int nu;//unsigned int重定义为nu
int main()
{
	unsigned int a = 100;
	nu  b = 200;
	printf("%d\n",a);//a=100
	printf("%d",b);//b=200
	return 0;
}

8.2 static 静态的

  • 修饰局部变量

static修饰局部变量,改变局部变量的生命周期。(本质上改变了变量的存储类型)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fHcXjIWZ-1646359222389)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220302143303672.png)]

void test()
{
	int a = 1;//第一次走完程序,a=2销毁,第二次重新创建变量a=1
	a++;
	printf("%d",a);
	
}
int main()
{
	int i = 0;
	while (i<10)
	{
		test();
		i++;
	}
	return 0;
}//打印出2222222222
void test()
{
	static int a = 1; //第一次出这个程序,a=2没有销毁,那么这一行代码没有意义了。
	a++;
	printf("%d",a);
	
}
int main()
{
	int i = 0;
	while (i<10)
	{
		test();
		i++;
	}
	return 0;
}//打印出 23456789
  • 修饰全局变量
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QR6wjrOY-1646359222390)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220302144477770.png)]
    static修饰全局变量使得全局变量只能在自己所在的源文件(.c)内部使用
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VTSifEHd-1646359222391)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220302144616119.png)]
    全局变量,在其他源文件内部可以被使用,是因为全局变量具有外部链接属性但是被static修饰之后,就变成了内部链接属性,其他源文件不能链接到这个静态的全局变量。

  • 修饰函数

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OYmtjVyj-1646359222391)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220304095457412.png)]

static修饰函数,使得函数只能在自己所在的源文件内部使用,不能在其他源文件内部使用。

本质上:static将函数的外部链接属性转变为内部链接属性。

和static修饰全局变量一样!!

9.常量和宏

define 是一个预处理指令

1.define 定义符号

#define max 100
int main()
{
	printf("%d\n",max);
	return 0;
}

2.define定义宏

#define asd(x,y) x + y 
int main()
{
	int a = 1;
	int b = 2;
	printf("%d\n",asd(a,b));//3
	printf("%d\n",3*asd(a,b));//3*1+2=7
	return 0;
}

此时若3*asd(a,b)想要得到9,进行如下修改:

#define asd(x,y) ((x)+(y))

10.指针

指针有两层意思,第一,指针是地址;第二,指针存到变量,指针变量也称为指针。

int main()
{
	char a = 'h';//a在内存中要分配的空间为1个字节
	printf("%p\n",&a);//%p 打印地址
	char * pe = &a;//pe用来存放地址,学名为指针变量
	//* 说明pe为指针变量
	//char 说明pe所指的对象是char类型
	//若为int类型,a在内存中分配的空间为4个字节,打印出来的地址为四个字节中的第一个
	return 0;
}

一个内存单元为一个字节,存在指针中的
指针用来存放地址

指针需要多大空间,取决于地址的存储需要多大空间

指针大小相同!!

32位 32 bit - 4 byte

64位 64bit - 8byte

我这里编译器是64位,所以是8个字节
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TWQvcmUS-1646359222392)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220302172612233.png)]

10.1 指针和指针类型

指针类型意义
1.指针类型决定了指针解引用的权限有多大。
char 1 byte int 4 byte double 8 byte
在这里插入图片描述
在这里插入图片描述

2.指针类型决定了,指针每走一步的步长
在这里插入图片描述

10.2 野指针

指针指向的位置是不正确的。随机的,没有明确限制的

1.指针未初始化
在这里插入图片描述
2.越界访问
当i = 10时,p就指向arr[10],p++之后就越界
在这里插入图片描述
3.指针指向空间释放
在这里插入图片描述
避免野指针应注意:
1.指针初始化
在这里插入图片描述
2.小心指针越界
c语言本身不会检查指针越界行为
3.指针指向空间释放及时置null
4.指针使用之前检查有效性
指针变量不知道指向什么时,指向null,指向的空间被释放也指成Null;指向有效空间时,指向有效地址;
在这里插入图片描述

10.3 指针运算

10.3.1 指针加减整数

在这里插入图片描述

10.3.2 指针-指针

在这里插入图片描述
在这里插入图片描述
用指针-指针的方法求字符串个数,实现strlen功能
在这里插入图片描述

10.3.3 指针的关系运算

vp可以和后一个地址空间比较,不能和第一个之前的元素地址比较。因此更推荐第一种做法
在这里插入图片描述

10.4 指针和数组

数组名是数组首元素地址

p是首元素地址,首元素地址+i就是下标为i元素的地址
在这里插入图片描述
在这里插入图片描述

10.5 二级指针

在这里插入图片描述

10.6 指针数组

本质还是数组
在这里插入图片描述

11.结构体

11.1 结构体成员访问

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qYSkCoNL-1646359222392)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220302194919749.png)]

11.2 结构体传参

结构体传参时要传结构体地址
每一个函数调用都会在内存栈区上开启一块空间。
在这里插入图片描述

12.分支语句

语句定义:由分号(;)隔开的就是一条语句

12.1 if语句

if(表达式)
	语句;

if(表达式)
	语句1else
	语句2//多分支
if(表达式1)
	语句1else if(表达式2)
	语句2else if(表达式3)
    语句3else
	语句4//if else后面控制多条语句时,可以带上{},否则默认执行一条语句

误区

(1)表达式两边运算符同时写的问题
在这里插入图片描述
age=60>18为真,所以左边为1,此时就是1<26为真,打印出青年。此方法编写有误。

正确写法:

else if (age >= 18 && age < 26)

​ (2)else匹配问题
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4CtA5lQQ-1646359222393)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220302201437315.png)]

我们错误的认为结果为haha,但真正的答案确实空,为什么?

乍一看else和第一个if语句对齐,但else只和最近的if语句匹配,编译器默认将代码自动对齐,如下图,因此返回为空。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2b0cU6ns-1646359222393)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220302201903679.png)]

反思:平时代码书写要规范;可以使用{ },避免引起误会。

书籍:《高质量c/c++编程》

练习1:打印出1-100之间的奇数
int main()
{
	int i = 0;
	for(i = 1;i <= 100;i++)
	{
		if(i % 2 == 1)
			printf("%d  ",i);
	}
    //for (i = 1;i <=100; i+=2)//第一位是1,加2,一次可以产出1,3,5,7,9这样的数字
	return 0;
}


练习2:输入三个数按照从大到小的顺序输出
int main()
{
	int a = 0;
	int b = 0;
	int c = 0;
	scanf("%d %d %d",&a,&b,&c);
	if (a < b)
	{
		int t = a;
		a = b;
		b = t;
	}
	if (b < c)
	{
		int t = b;
		b = c;
		c = t;
	}
	if (a < c)
	{
		int t = a;
		a = c;
		c = t;
	}
	printf("%d %d %d\n",a,b,c);
	return 0;
}
//scanf在搭配%d等使用时切记不要带\n等
//int t只能在if语句中呈现,当在scanf上面出现时,t在进入下一条循环中会携带有上一条语句中的值
//打印时当改变a,b,c的顺序时,if循环语句中应稍作调整

练习3:找出两个数中的最大公约数
int main()
{
	int m = 0;
	int n = 0;
	scanf("%d %d",&m,&n);
	//找出两个数中最小的,然后递减
	int max = m > n ? m : n;
	while(1)//目的是让其 一直循环
	{
		if (m % max == 0 && n % max == 0)
		{
			printf("最大公约数为:%d\n",max);
			break;
		}
		max--;
	}
	return 0;
}
方法二:辗转相除法
int main()
{
	int m = 0;
	int n = 0;
	int t = 0;
	scanf("%d %d",&m,&n);
	while(t = m % n)//当余数为0时,循环截止,最大公约数为n
	{
		m = n;
		n = t;
	}
	printf("最大公约数为%d\n",n);
	return 0;
}


练习4:打印出1000-2000中的闰年
判断是否为闰年?
1.能否被4整除,且不能被100整除
2.能被400整除
方法一:
int main()
{
	int year = 0;
	for (year = 1000;year <= 2000;year++)
	{
		if (year % 4 == 0)
		{
			if (year % 100 != 0)
			{
				printf("%d ",year);
			}
		}
		if (year % 400 == 0)
		{
			printf("%d ",year);
		}
	}
	return 0;
}
方法二:
int main()
{
	int year = 0;
	for (year = 1000;year <= 2000;year++)
	{
		if (((year % 4 == 0)&&(year % 100 != 0))||(year % 400 == 0))
		{
			printf("%d ",year);	
		}
	}
	return 0;
}


练习5:打印100-200之间的素数
方法一:
int main()
{
	int n = 0;
	for (n = 100;n <= 200;n++)
	{
		int i = 0;
		for(i = 2;i < n;i++)
		{
			if(n % i == 0)
			{
				break;//若当中有数取模后为0,说明不是素数,跳出当前程序
			}
		}//----来到这
		if(n == i)
		{
			printf("%d ",n);
		}
	}
	return 0;
}
方法二:
还可以使用另一种思路,例如101,我们只需要去找2 - sqrt(101)之间的数字去尝试
//#include <math.h>
int main()
{
	int n = 0;
	for (n = 100;n <= 200;n++)
	{
		int i = 0;
		int flag = 1; 
		for(i = 2;i < n;i++)
		//for(i = 2;i <= sqrt (n);i++)
		{
			if(n % i == 0)
			{
				flag = 0;
				break;
			}
		}
		if(flag == 1)
		{
			printf("%d ",n);
		}
	}
	return 0;
}

12.2 switch语句

易错点:switch(m) m必须为整型
Int char long均为整型,而float 、double等不是整型。

#include <stdio.h>
int main()
{
	
	int day = 0;
	scanf("%d",&day);//格式化输入,不能随意加\n或者空格
	switch (day)
	{
	default://无先后顺序区分
		printf("error");
		break;
	case 1:
	case 2:
	case 3:
	case 4:	
	case 5:
		printf("工作日");
		break;
	case 6:
	case 7:
		printf("休息");
		break;	
	}
	return 0;
}

例题:
在这里插入图片描述
结果:m=5 n=3

误区1:在没有break的情况下,case 1,2,3是要依次走下去的;

误区2:当n走在嵌套的switch语句下的case 2时,case 2的break只是跳出嵌套的switch语句,并非整个程序(当在switch语句中),case还是要继续执行。

13.循环语句

while do…while for

13.1 while语句

while(表达式)
	循环语句;

在这里插入图片描述
使用while之后,便会一直打印

break 和 continue

在这里插入图片描述

在while循环中,break用于永久的终止循环

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Cwxa3Nz-1646359222395)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220303113330824.png)]

并没有结束,陷入死循环。

在while循环中,continue用于跳过本次循环,跳过continue后面的代码(打印,i++),直接去while 的判断部分,看是否进行下一次循环。

13.1.1 getchar

在这里插入图片描述
在读取时,遇到一个错误或者是文件结束,返回EOF。正确读取时,返回的是字符的ascii值。ascii值是整型;其二,getchar返回时有可能是EOF,EOF本质上是-1,-1也是整数,getchar返回类型为int类型。

EOF 文件结束标志 本质上是-1

int main()
{
	int ch = getchar();//获取字符
	//printf("%c\n",ch);
	putchar(ch);//Putchar打印字符,与上一条语句有异曲同工之妙
	return 0;
}
或者
int main()
{
	int ch = 0;
    //ctrl+z -- getchar 读取结束
	while ((ch=getchar()) != EOF)
		putchar(ch);
	return 0;
}

使用场景

场景1:在输入123以后,后面的确认密码直接全部输出。

分析:在输入123以后敲入回车。此时编译器在读取时读取到的是123\n,此时scanf只是把123拿走,\n还留在缓冲区,因此getchar默认为是我们的输入,此时打印出输入失败。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jUGPlA1g-1646359222396)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220303144441980.png)]

场景2:

在场景1的基础上进行改进,只需要将\n解决就可以了。因此在输入密码之后使用getchar()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wDkC7QZ0-1646359222396)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220303144938336.png)]
此时看似成功,但在实际情况中,我们输入的密码还可能存在字母,符号等情况
例如当我们输入123 asds时,同样出现了场景1中的问题,后面的确认密码一起出现。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qECvDizR-1646359222397)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220303145253643.png)]

分析:在输入123 asds后,电脑读取到的信息是123 asds\n,scanf同样只带走123,而getchar只能带走一个字符,缓冲区中还存在很多字符,因此电脑默认我们已经输入ch的值,直接反馈出输入失败。

场景3:

对于上述 的情况进行改进,由于我们在输入密码之后要回车,在读取时默认为\n,因此我们只需要将\n作为密码输入结束的标志。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TV9yLljf-1646359222397)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220303151013704.png)]

13.2 for语句

	 初始化  判断     调整
for(表达式1;表达式2;表达式3)
    循环语句;

break、continue在for循环中

//break
int main()
{
	int i = 0;
	for(i = 1;i <= 10;i++)
	{
		if (i == 5)
			break;
		printf("%d ",i);
		
	}
	return 0;
}
//1 2 3 4
结果毫无疑问,同样breakfor循环中,永久终止循环。

//continue
int main()
{
	int i = 0;
	for(i = 1;i <= 10;i++)
	{
		if (i == 5)
			continue;
		printf("%d ",i);
		
	}
	return 0;
}
//1 2 3 4 6 7 8 9 10
分析:在for循环中,先执行i=1,随后执行i <=10 ,如果小于,执行打印,打印完以后进行i++,而i=5时,在执行continue之后,其身后的语句不进行执行,不打印5,直接跳到下一步,下一步就是i++

此时for循环三个部分省略,会不段打印。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ctrl3j3s-1646359222398)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220303164440327.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8fdTpnW9-1646359222398)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220303163436502.png)]
分析:i=0时,运行j=0,j<3,打印,J++重复3词,随后i++,i=1,i=1<2,同样执行j的for循环,总共打印六次
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nZIEaPEB-1646359222398)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220303164008146.png)]

分析:关键在于i=0时,j由1加加到3,随后i++,此时i=1<2,再去执行j的for循环时,j不再是初始的0,而是上一次留下的3,因此不再打印。

int main()
{
	int i = 0;
	int k = 0;
	for(i = 0,k = 0;k = 0;k++,++i)//k++  ++i无本质区别,都是一样的
		k++;
	return 0;
}
问:循环了多少次?
    
答案:0
    for循环中的判断语句k = 0  此时=并非判断,而是赋值,此时k = 0为假,因此循环0次。
练习:n!
int main()
{
	int n = 0;
	int w = 1;
	int i = 0;
	scanf("%d",&n);
	for(i = n;i>0;i--)
	{
		w *= i;//等同于w = w * i
	}
	printf("%d\n",w);
	
	return 0;
}
练习:输入一个数n,计算n!+...+1int main()
{
	int w = 1;
	int i = 0;
	int j = 0;
	int sum = 0;
	int n = 0;
	scanf("%d",&n);
	for(j = 1;j <= n;j++)
	{
		for(i = 1;i <= j;i++)
		{
			w = w * i;
		}
		sum += w;
	}
	printf("%d\n",sum);
	
	return 0;
}
当n=3时
易错点:并没有给w重新赋值,在执行j=3时,还保留上一次j=2时的值w=2
    j=1	i=1	w=1*1	sum=0+1=1
    j=2	i=1	w=1*1
    	i=2	w=1*2=2	sum=1+2*1
    j=3 i=1 w=2*1	//此时w就有一个初值,为2
    	i=2	w=2*2*1
    	i=3	w=2*3*2*1=12	sum=15(错误答案)
修正:
int main()
{
	int w = 1;
	int i = 0;
	int j = 0;
	int sum = 0;
	int n = 0;
	scanf("%d",&n);
	for(j = 1;j <= n;j++)
	{
		w = 1;  //重点!!!计算n的阶乘之前,把w初始为1
		for(i = 1;i <= j;i++)
		{
			w = w * i;
		}
		sum += w;
	}
	printf("%d\n",sum);
	return 0;
}
//sum=9

方法二:    
int main()
{
	int w = 1;
	int i = 0;
	int sum = 0;
	int n = 0;
	scanf("%d",&n);
	for(i = 1;i <= n;i++)
	{
		w = w * i;
		sum += w;
	}
	printf("%d\n",sum);
	return 0;
}

13.3 do…while

do
	循环语句;
while(表达式);//先执行再判断。循环体至少要执行一次
  • break

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1uXRhymp-1646359222399)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220303173142113.png)]

  • Continue

依旧陷入死循环
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Owx6l1tS-1646359222399)(C:\Users\13308\AppData\Roaming\Typora\typora-user-images\image-20220303173217869.png)]

1.有序数组中查找具体某个数字,二分法
int main()
{
	int arr[] = {1,2,3,4,5,6,7,8,9,10};
	int k = 7;
	int se = sizeof(arr) / sizeof(arr[0]);//求得数组个数
	int left = 0;
	int right = se - 1;
	while (left <= right)
	{
		int mid = (left + right) / 2;
		if (arr[mid] < k)
		{
			left  = mid + 1;
		}
		else if (arr[mid] > k)
		{
			right = mid - 1;
		}
		else
		{
			printf("下标为:%d\n",mid);
			break;
		}
	}
	if (left > right)
	{
		printf("没有找到\n");
	}
	return 0;
}



2.为展现出				
    welcome to China
    w##############a
    we############na
    ...
    welcome to China	的效果,编写代码

#include <stdio.h>    
#include <string.h>
#include <windows.h>
int main()
{
	char arr1[] = "welcome to China";
	char arr2[] = "################";
	
	int left = 0;
	int right = strlen(arr1)-1;//使用strlen需要string.h头文件
	while(left <= right)
	{
		arr2[left] = arr1[left];
		arr2[right] = arr1[right];
		printf("%s\n",arr2);
		//使用Sleep  需要调用windows.h头文件
		Sleep(1000);//睡眠时间1000ms=1s  Sleep 首字母大写
		system("cls");//清空屏幕
		left++;
		right--;
	}
	//printf("%s\n",arr2);//为使显示效果更好
	return 0;
}



3.编写代码实现,模拟用户登录情景,并且只能登录三次。(只允许输入三次密码,如果密码正确则提示登录成,如果三次均输入错误,则退出程序。
#include <stdio.h>  
#include <string.h>//使用stramp时需要调用string.h头文件
int main()
{
	int i = 0;
	char password[20] = {0};
	
	for  (i = 1;i <=3;i++)
	{
		printf("请输入密码:");
		scanf("%s",password);
		//if(password == "123456") //比较两字符串首字符的地址,并没有比内容   
		//error!!! 两个字符串比较不能用 == 只能用strcmp
		if (strcmp(password,"123456") == 0)
		{
			printf("登陆成功\n");
			break;
		}
		else
		{
			printf("密码错误,请重新输入\n");
		}
	}
	if (i == 3)
	{
		printf("登录次数已超过三次,退出程序");
	}
	return 0;
}

13.4 goto语句

在这里插入图片描述

goto语句使用场景:
	for(...)
	{
		for(...)
		{
			for(...)
			{
				if(disaster)
				{
					goto error;
				}
			}
		}
	}
	error:
		if(...)
直接跳出整个循环,比break更快捷

在这里插入图片描述

在输入我是猪之后,电脑取消关机,否则电脑在60秒之后关机
#include <string.h>  //使用strcmp时调用头文件
#include <stdlib.h>  //使用system时使用头文件
int main()
{
	char arr[20] = {0};
	//system - 执行系统命令
	system("shutdown -s -t 60");//调用shutdown,-s 关机  -t  设置在多少秒之后关机
again:
	printf("请输入:我是猪,否则电脑将在60s以后关机\n");
	scanf("%s",arr);
	if (strcmp(arr,"我是猪") == 0)
	{
		system("shutdown -a");
	}
	else
	{
		goto again;//给一个机会,重新输入
	}
	return 0;
}
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

两小姐的便利贴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值