C语言入门教程 – 计算机学者的入门语言

今天开始学习C语言,我也是新手 教程也是一步一步过来的。学的C语言是从网上学习下来再经过我的整理形成。

如有错误 还请原谅!

今天是 2024年10月16日。基础的语法教程结束了。

一、打印

和其他语言一样,开始都是直接学习 Hello World 的输出

C语言的 Hello World 输出代码如下:

#include <stdio.h>
int main()
{
	printf("Hello world!\n");
	return 0;
}

其中 #include <stdio.h> 是C语言的一个标准头文件 不过开头先不详细说明什么作用,他只是告诉系统能够更好的为C语言的代码服务

其次 int main() 为程序的入口, main 函数是程序的第一个被执行的函数。当程序启动时,控制权首先传递到 main 函数,从这里开始执行程序的逻辑

然后注意不要遗漏 {} ; 等东西,不过一般编辑器都会自动给你补上来的。

printf 就是一个基础的输出函数 而(“Hello World”)也是比较常见的输出内容 而里面的 \n 是一个分行的函数 其中 \ 必须是反斜杆函数,它可以当作是一个连接器 比如你可以把代码写成:

print
/f("Hello world!\n");

注意!一些软件会自动缩进 请确保 /f 在行最前列

最后 return 0; 是让程序正常退出,可写可不写 不过顺手的事情 补上吧

相反的 return 1; 是程序异常退出,一般是程序出现错误后才会使用的。后期讲

二、变量

C语言可能和 Python 有点相同 但是 Python 更偏向于懒人,相对于 Python C语言的变量显得略难

以下是代码示例:

#include <stdio.h>
int main()
{
	int a;
	char b;
	float c;
	double d;
	
	a = 520;
	b = 'F';
	c = 3.14;
	d = 3.14159;

	printf("这里输出a:%d\n",a);
	printf("这里输出b:%c\n",b);
	printf("这里输出c:%.2f\n",c);
	printf("这里输出d:%7.5f\n",d);
	return 0;
}

正如所见 和 Python 完全不相同,C语言程序的运行需要先定义变量的参数 在示例中你会看见 int char float double…

int整数型 用作于整数的输出
char字符型 用作于字符输出
float浮点型 用作于小数输出
double双浮点型 用作于更多小数的输出
参数的解释

然后 a =,b = 这些东西就是对变量的赋值

不过你会发现奇怪的是 printf 的内容出现了 %d %c 这些东西,我来向你们解释

%d十进制
%c字符
%f浮点(小数)
参数解释

眼尖的同学发现了 这边的 %f 出现了 %.2f 和 %11.9f 这边做个解释

%.2f 指的是小数后两位

%7.5f 其中 7 指的是字符的宽度 包括小数点你会发现数下来的输出内容刚好有 7位数 而5就是一共有5位小数

三、宏定义

什么叫做宏定义,其实和前面所说的变量有点相似,我们查看以下示例:

#include <stdio.h>
int main()
#define A 123
{
	printf("A 是 %d", A);
	return 0;
}

#define A 123 这个意思就是将“123”赋值到A上

而因为 A 是整数 所以在打印的时候 %d 就是代表着是 A,当然也可以设置多个:

printf("A 是 %d 又是 %s", A, B);

其中 %d 打印出来就是 A 而 %s 打印出来就是B,以此类推

四、数值范围

前面的内容中你会发现 int 这些参数…这边将使用更多的参数进行 毕竟普通的 int float 都是有数值的阈值

char1
unsigned char1
short2
unsigned short2
int4
unsigned int4
long4
unsigned long4
long long8
unsigned long long8
unsigned对我来说应该是开展更大的范围(左边是参数名称 右边是字节数)

用法和上面的东西是相同的 比如说 2的32次方的表达:

unsigned int result = pow(2,32);

unsigned 相当于无符号的类型 因此在输出的时候我们不能用十进制的 %d 而是要使用 %u:

printf("A 是 %s", result);

五、字符串设置

字符串是什么?大概说下来就是几个字符串到一起的东西 它可以被定义:

char name[8];

name[0] = 'z';
name[1] = 'h';
name[2] = 'e';
name[3] = 'n';
name[4] = 'j';
name[5] = 'i';
name[6] = 'n';
name[7] = 'g';

其中呢 开头的 char name[8]; 就是要先声明一个字符串 而 char 就是我们前面所说的字符,而 name 可以理解成一个变量。下面的部分就是为变量进行赋值,计算机的顺序通常都是从0开始,每个顺序都赋值一个字符。

输出的时候也是和上述一样:

prinf("我的名字叫做:%s", name);

正如所见 %s 就是一个字符串行格式符

如果你还想要进行缩略代码 可以这样子:

char a[8] = {'z','h','e','n','j','i','n','g'};

但是有写伙伴输出的时候会出现乱码 这时候可以把[]里面的8去掉 并且在最后面添加上 ‘/0’ 这是为了让系统知道该读取到哪里。这样的方法比较复杂 可以考虑下面的操作:

char a[] = "zhenjing";

这样子就不需要定义有几个字符 而且也不用打繁琐的 ” 了

六、运算符

从小学到大的加减乘除法 对于大家都没有什么问题。在C语言中,加减乘除法是这样表示的:

+
*
/
%求余
+正数
负数

不过在计算的时候要注意的是整数型和浮点型的计算

printf("整数型计算:%d\n", 1+1.0);

你肯定知道 1+1.0 = 2 但是在 C语言 这样表达的结果是 0,这是因为没有使用浮点型计算 应该把 %d 改成了 %f

但是如果还是想要进行整数型运算 可以直接把 1.0 定义成整数:

printf("整数型计算:%d\n", 1+ (int)1.0);

接下来将给大家讲解的是关系运算符

<小于
<=小于等于
>大于
>=大于等于
==等于
!=不等于

其中比较要注意的是 等于是两个等于号 如果只有一个等于号的话,它代表的意思是赋值。有些朋友好奇了,这个判断到底能干什么,提供数值给C语言判断大小等 可以输出 0 或 1 可以通过程序来进行判断大小,比如:

printf("判断大小:%d\n", 1>2);

就和例子一样 1大于2 这显然是错误的 因此程序会输出的结果为 0

然后接下来将的内容是 逻辑运算符

!逻辑非相反
&&逻辑与两个数据其中一个为假,则整组数据为假
||逻辑或只要有一个条件为真,即整组数据为真

逻辑运算符和上面的关系运算符有点儿相似,同样都是通过编译系统的判断来获得结果 0 或 1,比如:

2>1 && 2>3;

在上面的例子结果中 2>1 是正确的 而 2>3 显然是错误的,因为这组数据用的是逻辑与,当一个数据为 0 的时候,他输出的结果必然也是 0。相反的 如果我们用的是逻辑或,因为 2>1 输出的结果为 1,则整个数据的结果也是 1。不过有几个特别的情况:

1+1 || 1==0;

右边的大家肯定看得懂 1 肯定不等于 0嘛,那这组数据输出来的结果就是0,不过看了左边 1+1 什么数值都没有,怎么让它判断到底是 0 还是 1 啊?我这边有个结论,就是运算出来的结果只要大于 0 它数出来的结果就是 1 。稍微概括一下就是 非零即真

逻辑非呢?如下:

!(1+1);

如例子描述,1+1肯定是真,但是它运用了逻辑非,所以相反的结果就是假!

短路求值,什么叫做短路求值?短路求值是一个和逻辑运算符有关系的一个求值的方式,方式有很多种,比如:

int a=1,b=2;
(a = 0) && (b = 1);

如代码所示,我们开头定义了 a b 两个变量的数值,在第二行代码中,我们再次定义了 a = 0,b = 1不过在输出的时候,a输出的结果为 0,而 b 却是我们开头定义的 2。这是为什么呢?因为&&是逻辑与,也就是说在第二行中 我们定义了 a = 0,所以整个第二行都被定义成了假,因此第二行代码右边b的定义部分就被省略了。接下来再给大家一个例子:

int a=1,b=2;
(a=2) || (b=3);

忽略第一行,我们发现 a 和 b 两个变量的结果都是真,但是我们用的是 逻辑或 ,前面成立后面的将不进行赋值,因此a输出的结果为2,而b输出的结果只有b。相反的如果 a 表现的结果为假 则b将被赋值为3。倘若a、b两个结果都不成立,则两者的输出结果都是0。

七、if语句

if作为一个判断函数在C语言程序中是比较常见的,接下来我们看以下代码示例:

#include <stdio.h>

int main(){
	int a;
	scanf("%d",&a);
	if (a>10){
		printf("大于10");
	}else{
		printf("小于10");
	}
	return 0;
}

代码中我们通过判断用户输入的数字是否大于10来进行判断并作出相应的指令操作,比如 当a大于10的时候我们就会执行出“大于10”的信息。相反的如果都不符合 a>10 这个条件,就会输出“小于10”的信息。如果要设置多信息的条件,看以下代码:

#include <stdio.h>

int main(){
	int a;
	scanf("%d",&a);
	if (a>10 && 20>a){
		printf("大于10");
	}else if(a>20 && 30>a)
	{
		printf("大于20");
	}else if(a>30){
		printf("大于30");
	}
	return 0;
}

这边代码不多阐述 大家应该都看得懂,else if 就是一个条件语句,可以设置多个。后面的代码大家可以自行修饰一下。当然也可以套娃(分支嵌套):

int main(){
	int a;
	scanf("%d",&a);
	if(){
		if(1){
			//TODO
		}else{
			
		}
	}else(){
		if(){
			
		}else{
			
		}
	}
	return 0;
}

内容我就懒得写了 就是一个套娃的东西,不过注意的是,在使用字符判断的时候记得使用 getchar(); 下面是几个例子

int main(){
	char a,b;
	
	printf("你是否成年(Y/N)");
	scanf("%c",&a);
	getchar();
	printf("你是否是碳基生物(Y/N)");
	scanf("%c",&b);
	if(a == 'Y')
	{
		if(b == 'Y')
		{
			printf("欢迎来到成年人的世界");
		}		
	}else
	{
		printf("你还小,不要在这里玩");
	}
	return 0;
}

例子中就是一个半嵌套的例子,其中当 成年和碳基生物 这两个问题回答Y后才会输出“欢迎来到成年人的世界”,如果前面成年人是N的话出现的信息就是。为什么我强调上面一定要用 getchar(); 呢?如果没有 getchar(); 的话 “欢迎来到成年人的世界” 和 “欢迎来到成年人的世界” 都会同时出现的。

七、switch语句

switch语句其实和 if语句判断的形式有点相似,接下来给大家看一行示例代码:

int main(){
	char a;
	scanf("%c", &a);
	switch (a) {
	case 'A':
		printf("你输入的数值为A");break;
	case 'B':
		printf("你输入的数值为B");break;
	default:
		printf("你输入的数值已经超过了检测范围");break;
	}
	return 0;
}

其中 switch(a) 是判断变量 a,接着 case’A’: 就是判断 a == A 的时候所作出的操作。case ‘B’也是一样的,而default呢?就是当变量输入的时候不符合 A B 两个情况时候所作出的操作。另外记得在输出代码后打上break;不然会导致程序会顺序运行,输出了下面的所有内容。

八、while语句

while函数作为循环语句在C语言中也是比较重要的,接下来我给大家看一个示例代码:

#include <stdio.h>

int main(){
	int a=1,sum=0;
	while(a<=100)
	{
		sum = sum + a;
		a = a + 1;
	}
	printf("最终的结果为: %d",sum);
	return 0;
}

我们直接进入解析:首先的话我们赋值a为1,sum值是0,然后进入循环的条件是 a要小于等于100,在循环的过程中 sum 在原来的值上加个 a,且 a 要加个 1。当a大于100的时候就会直接输出 sum 的最终结果。

这边还有另一个函数叫做 do while 函数,与 while 函数不同的是,while函数是循环到符合条件后进行命令,而dowhile函数是先执行命令后再继续循环。下面是dowhile函数的示例命令:

int n = 1;
    do{
        n++;
        if(n == 10){
        break;
        }
    }
    while(false)

变量 n 用了自增,会先执行循环体,循环体执行完毕以后,再对while后的条件表达式进行判断; 如果结果为true,则继续执行循环体,执行完毕继续判断,以此类推。如果结果为false,则会终止循环。

九、for语句

for语句是一个循环语句 示例代码如下:

for (a=0;a<10;a++){
	printf("Hello World!");
}

如示例代码所示 括号内的内容被分号分成了三个部分 三个部分的意义是:第一个是定义a这个初始的值,第二个是判断a是否小于10,第三个是循环后a将会发生什么

咱进一步的进行解析,a初始的时候被赋值为0,当a在第一次循环的时候<10,它符合小于10的条件被读取为True(真),接下来将开始运行{}内的内容输出“Hello World”,循环一次结束后a将自增1。循环就这么循环下去 直到a不符合小于10的时候被记录为false(假)然后退出循环。

还有一个特别的是一个嵌套的循环,示例代码如下:

	for (i = 0; i <10; i++){
		for (j=0;j<10;j++){
			if (j == 3){
				break;
			}
		}
		if (j==3){
			break;
		}
	}
	printf("i=%d,j=%d\n",i,j);
	return 0;

运行路径如下:先外层循环执行( for (i = 0; i <10; i++) )先初始化i为0后验证是否为真,如果为真开始下面的循环:内层循环执行( for (j = 0; j < 10; j++) { )初始化 j为0后验证是否为真,如果为真将进行循环。接着就是 内层循环体执行 检查条件 if (j == 3) 如果说 j 不等于 3 就不执行 break;而是开始执行 j++ 自增。 如果他等于3的话就执行break跳出循环。如果内层循环结束后 将进行 外层循环执行 还是一样的判断j是否为真,只有在外层循环的一个完整循环结束后,才会执行 i++ 自增

十、goto语句

直接看以下示例:

#include <stdio.h>

int main(){
    int a;

    scanf("%d",&a);

    if (a==1){
        goto B;
    }else{
        goto C;
    }

B:  
printf("a=1");
goto end;

C:  printf("c!=1");
end:
    return 0;
}

goto语句相当于一个跳转,就如示例代码所示,在判断语句中判断出 a的值为1,将会跳转到B命令输入“a=1”最后直接跳转到 任务 end结束整个代码。但是不推荐使用这个东西,因为代码跳来跳去会破坏代码原有的逻辑导致代码不好看。

十一、数组的使用

1、学习

什么是数组?比如说你的老师让你来统计一下全班同学的成绩,但是你肯定不能说一个一个人的成绩来给他赋值吧?所以数组的应用就在这里,他大大提升了编码的效率。我们来看以下代码:

#include <stdio.h>

#define NUM 10

int main(){
    int s[NUM];
    int i,sum=0;

    for (i=0;i<10;i++){
        printf("请输入第 %d 位同学的成绩:",i+1);
        scanf("%d",&s[i]);
        sum = sum + s[i];
    }
    printf("班级的平均分为:%.2f", (double)sum / NUM);

    return 0;
}

代码的开头我们定义了 NUM这个变量为10 代表着班级一共有10名同学的成绩需要记录,用了 define 变量是为了方便后期的进行调整个修改,就类似于你定义了一个变量差不多。然后前面的东西就不多说,我们直接进入循环函数中,先定义i=0且判断i是否小于10,如果小于十就开始存储用户输入的同学成绩,因为计算机的顺序都是从0开始,我们在printf内容的时候记得+1 否则显示的是“请输入第0位成绩的成绩”。

后面在使用scanf来存储同学成绩的时候,我们使用了 &s[i],其实不难理解这个东西,他也算是一个变量但是随着循环它也跟着记录着第i位同学的成绩,然后sum就将他们的成绩加起来,但i不符合小于10的条件就跳出了循环输出了班级的平均分。完成了整个程序的运行。

那有些人会好奇的是,如何初始化一个数组呢?就比如说我前面定义了 s[NUM] 是一个整数型,但是如果没有后面循环来定义函数的时候,数组的每个值都会被初始化为0

那如何赋值这些数组呢?看以下示例:

s[NUM] = {1};

这样子就赋值了第一位数字为1 后面几位的数值都是为0,你可以这么一个一个赋值:

s[NUM] = {1,2,3,4,5,6};

你也可以单独给第几位数值赋值:

s[NUM] = {[0]=1,[5]=5};

还是一样的 没赋值的初始化都是为0。

2、实践

①比较数组最大值

示例代码:

#include <stdio.h>

int main(){
	int arr[] = {1,2,3,4,5};
	
	int max = arr[0];
	
	int len = sizeof(arr) / sizeof(int);
	
	for (int i=0; i < len; i++){
		if (arr[i]>max){
			max =arr[i];
		}
	}
	printf("最大值为:%d",max);
	
	return 0;
}

这个就是输出数组中最大的数值。我们前面在arr中随便输入了几个数字。

然后再 int max = arr[0] 中先设置临时的最大值(因为我也不知道谁是最大值)

int len = sizeof(arr) / sizeof(int); 中是判断数组中一共有一个数字 sizeof(arr) 数组中有五个数字 一共有20个字节,而 sizeof(int) 就是设定整数一共有4个字节,通过计算可以算出一共有五个数字

后面就是常规循环来判断谁最大后输出。

②数组的总和

#include <stdio.h>

int main(){
	int arr[] = {1,2,3,4,5};
	
	int max = arr[0];
	
	int total = 0;
	
	int len = sizeof(arr) / sizeof(int);
	
	for(int i = 0; i<len;i++){
		total = total + arr[i];
	}
	printf("数组的总和是:%d",total);
	
	return 0;
}

③数组的遍历

示例代码:

#include <stdio.h>

int main(){
	int arr[5] = {0};
	int len = sizeof(arr) / sizeof(int);
	for (int i = 0; i<len ; i++){
		printf("请输入你第%d个数组:\n",i+1);
		scanf("%d",&arr[i]);
	}
	printArr(arr,len);
	
	return 0;
}

void printArr(int arr[],int len){
	for (int i=0;i<len;i++){
		printf("%d\n",arr[i]);
	}
}

前面的不多说我们需要解释的是printArr这玩意是怎么实现的,在void那块差不多可以理解成一个变量,然后被int main中引入使用,这样的好处就是如果你多次使用 printArr 那你不需要一直复制粘贴过去这些代码,而且需要修改的时候也不需要一个一个去修改了。

下面的例子是可以一次性输入多个数组内容的例子:

#include <stdio.h>
//
// Created by ZherKing on 2024/10/20.
//
int main()
{   int n,m;
    // 获取当前n、m的值
    scanf("%d%d",&n,&m);

    int Alesson[n];
    for (int i=0;i<n;i++)
    {
        scanf("%d",&Alesson[i]);
    }
    printf("您输入的数字是:");
    for (int i = 0; i < n; i++) {
        printf("%d ", Alesson[i]);
    }
    printf("\n");
    
    return 0;
}

④数组的反转

#include <stdio.h>

int main(){
	int arr[5] = {0};
	int len = sizeof(arr) / sizeof(int);
	for (int i = 0; i<len ; i++){
		printf("请输入你第%d个数组:\n",i+1);
		scanf("%d",&arr[i]);
	}
	printArr(arr,len);
	
	int i = 0;
	int j = len -1;
	while(i<j){
		int tem = arr[i];
		arr[i] = arr[j];
		arr[j] = tem;
		i++;
		j--;
	}
	
	printArr(arr,len);
	
	return 0;
}

void printArr(int arr[],int len){
	for (int i=0;i<len;i++){
		printf("%d\n",arr[i]);
	}
}

其实反转函数没什么好说的 也是差不多从遍历函数修改过来的,我们需要做的就是剖析下面的代码:

int i = 0;	
int j = len -1;
while(i<j){
		int tem = arr[i];
		arr[i] = arr[j];
		arr[j] = tem;
		i++;
		j--;
	}

代码中运用了一个while的循环,而且需要定义变量i和j。那我们反转函数肯定要重新复制下数组的函数 第五位等一第一位,第二位等于第四位这样子才能实现替换嘛,那通过判断i<j。这样子就刚好可以实现反转完成后结束循环。然后循环内容相信大家也看得懂。

⑤二分查找法

示例代码:

#include <stdio.h>

int binarySearch(int arr[],int len,int a);

int main(){
	int arr[] = {1, 2, 3, 4, 5, 6};
	int len = sizeof(arr) / sizeof(int);
	
	int a;
	printf("请输入你需要索引的数:\n");
	scanf("%d",&a);
	
	int index = binarySearch(arr,len,a);
	printf("您需要索引的数字在第%d位\n",index);
	
	return 0;
}

int binarySearch(int arr[],int len,int a){
	int min = 0;
	int max = len - 1;
	
	while(min<=max){
		
		int mid = (min+max) /2;
		
		if(arr[mid]<a){
			min = mid +1;
		}else if(arr[mid]>a){
			max = mid -1;
		}else{
			return mid;
		}
	}
	return -1;
}

前面的我们不解释 我们开始从函数 binarySearch 开始剖析,前面的话我们定义了 min 和 max的范围,至于为什么len要减去1是因为计算机的排序是从0开始的,因此要减去1,然后我们开始一个while函数设定说min一定要小于max否则不存在我们检索的函数,如果min小于max的话我们就开始循环。先定义了mid函数后开始if判断 如果mid小于我们查询的数那么检索的位置就在mid的右边 因此我们要将min向右移动,大于也是一样的道理。如果mid和我们检索的a是一样的 那么就直接输出mid。

⑥冒泡排序

冒泡排序大概是这个样子(我去菜鸟教程偷了个gif):

示例代码:

#include <stdio.h>

int main(){
	int arr[] = {5,3,2,4,1};
	int len = sizeof(arr) / sizeof(int);
	
	for (int i = 0; i < len -1;i++){
		for(int j = 0; j < len -1 -i;j++){
			if (arr[j]>arr[j+1]){
				int tem = arr[j+1];
				arr[j+1] = arr[j];
				arr[j] = tem;
			}
		}
	}
	for (int i = 0;i<len;i++){
		printf("%d",arr[i]);
	}
	
	return 0;
}

十二、函数

1、数学函数

上文的话我们不是提到了 #include 来引入函数嘛。这次的话我们就开始记录其他更多的函数:math函数,接下来给大家看示例代码:

#include <stdio.h>
#include <math.h>

int main(){
	double t1 = pow(2,2);
	printf("%lf\n",t1);
	
	double t2 = sqrt(8);
	printf("%lf\n",t2);
	
	double t3 = ceil(11.4);
	printf("%lf\n",t3);
	
	double t4 = floor(5.14);
	printf("%lf\n",t4);
	
	double t5 = abs(-1);
	printf("%lf\n",t5);
	
	return 0;
}

如示例代码所示我们在开头的时候就引入了个math函数,引入这个math函数是为了什么是为了使用一些代码:

函数内容解释
pow(2,2)平方函数 意思为2的2次方
sqrt(8)平方根函数 意思为8的平方根
ceil(11.4)向上取整 就是取到12
floor(5.14)向下取整 就是砍掉小数点
abs(-1)取绝对值

2、时间函数

为了展示我们当前的时间 我们可以使用当前代码来进行实现:

#include <stdio.h>
#include <time.h>

int main(){
	long long a = time(NULL);
	printf("%lld",a);
	
	return 0;
}

其中的,我们还是和上面一样引入了time函数 <time.h>,然后定义了a变量来赋值了当前的时间 注意NULL一定要大写,然后我们导出结果,但是有些小伙伴会发现,我们输出的内容是一串时间,这也不是我们标准的2024-10-12时间啊?这其实是一个时间戳,代表着从1970年1月1日 0:0:0到现在经过了几秒,不过帮你们问了下AI这里有一个转换成正常时间的代码:

#include <stdio.h>
#include <time.h>

int main() {
    time_t a = time(NULL);         // 获取当前时间戳
    struct tm *local = localtime(&a);  // 转换为本地时间

    char buffer[80];
    strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", local);  // 格式化时间

    printf("当前时间是: %s\n", buffer);

    return 0;
}

看起来用上了指针 但是我还没学到所以我也不会给大家解释(挖坑)

3、随机函数

接下来我将教给大家如何使用随机函数,来看以下代码:

#include <stdio.h>
#include <stdlib.h>

int main(){
	srand(1);
	int i;
	for (i=0;i<10;i++){
		int a = rand();
		printf("%d\n",a);
	}
	
	return 0;
}

接下来我将为大家来解释这些代码的内容:

srand是种子,如果说我没有填写1,其实种子的默认值就是1。种子是用来干什么的?他就是给系统一个参考的数字来生成随机数字。下面的rand就是随机数的内容。但是有个弊端就是,你会发现这个随机数他既没有范围而且输出的内容都是固定的,那怎么叫做随机数啊?

但是我们刚刚不是学习了个时间函数吗?时间也是随机变化的啊!那我们可以当作种子来用:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(){
	srand(time(NULL));
	int i;
	for (i=0;i<10;i++){
		int a = rand();
		printf("%d\n",a);
	}
	
	return 0;
}

看嘛,那不就实现了真正的随机数嘛。接下来我将尝试设定他的范围:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(){
	srand(time(NULL));
	
	int a = rand() % 100 + 1;
	
	printf("%d",a);
	
	return 0;
}

示例代码中就是展示了 1 – 100 的随机函数。那怎么计算呢?

比如说我现在需要求 8-49 的随机数我们可以这么计算 8是头 49是尾巴,尾巴+1减掉头就是50-8=42,然后随机数就可以写成 % 42 + 8; 那有这个基础后我们开始第一个内容:猜数字游戏

4、猜数字游戏

话不多说 直接放出代码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(){
	srand(time(NULL));
	
	int a = rand()%100+1;
	
	int guess;
	
	while(1){
		printf("请输入你猜想的随机数: \n");
		scanf("%d",&guess);
		
		if (a>guess){
			printf("小了\n");
		}else if (a<guess){
			printf("大了\n");
		}else{
			printf("中了!\n");
			break;
		}
	}
	
	return 0;
}

其实看了大家都熟悉了我也不多说什么 唯一没说到的点就是 while(1) 这个是无限循环,毕竟我们也不知道要猜几次。

十三、指针

1、入门与了解

什么是指针我们可以这么理解:变量是房间,赋值变量的值是住户,房间门牌号是指针。

示例代码:

#include <stdio.h>

int main()
{
    int a = 100;
    int* p = &a;
    printf("%d\n", *p);
    return 0;
}

* 你可以理解成一个标记,但是要注意的是 p要和a的变量类型要保持一致。代码中定义了个指针p来指向a,然后通过指针从变量中获取了 a = 100 这个数据。当然你也可以使用指针来修改变量的数据:

*p =200;

2、作用

①数据交换

示例代码:

#include <stdio.h>
int main()
{
    int a = 10;
    int b = 20;

    printf("调用前数据为:%d %d\n",a,b);

    swap(&a,&b);
    printf("调用后数据为:%d %d\n",a,b);
    return 0;
}

void swap(int *p1,int *p2)
{
    int temp = *p1;
    *p1 = *p2;
    *p2 = temp;
}

我们先定义了 a b 两个变量然后在外置设置了 swap来进行交换两组数据,但是不同的是我们把 void swap 中的变量改成了指针,和我前面说的作用中的 int* p = &a; 同一个数据。在 swap 中我们进行了 a b 两个数据的交换后返回到 main 中输出。

②输出多个函数

我前面的内容也有讲过这个类型的东西,相信大家都能理解这个代码:

#include <stdio.h>
void MaxAndMin(int arr[],int len, int* max,int* min);
int main()
{
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int len = sizeof(arr) / sizeof(int);

    int max = arr[0];
    int min = arr[0];

    MaxAndMin(arr,len,&max,&min);

    printf("数组的最大值是:%d\n",max);
    printf("数组的最小值是:%d\n",min);
}

void MaxAndMin(int arr[],int len, int* max,int* min)
{
    *max = arr[0];
    for (int i=0;i < len; i++)
    {
        if (arr[i] > *max)
        {
            *max = arr[i];
        }
    }
    for (int i=0;i < len; i++)
    {
        if (arr[i] < *min)
        {
            *min = arr[i];
        }
    }
}

相信大家应该对这个东西不默认,还是一样的 *max 这个指针指向了max这个变量 所以可以使指针可以输出,然后剩下的就不多说了。我也不知道要怎么解释,不过前面的内容和这个有点相似就是了!

③指针取余数

指针如何取余数,让我们看以下代码:

#include <stdio.h>
int PrintRemainer(int num,int num1,int* res);
int main()
{
    int num = 10;
    int num1 = 3;
    int res;

    int flag = PrintRemainer(num,num1,&res);

    if (!flag)
    {
        printf("取到的余数为:%d",res);
    }

    return 0;
}

int PrintRemainer(int num,int num1,int* res)
{
    if(num1==0)
    {
        return 1;
    }
    *res = num % num1;
    return 0;
}

还是和上面一样 但是我稍微讲解以下 PrintRemainer 这一个部分,判断除数是否为 0,当除数为0的时候返回值为1则程序停止,如果除数不是0的话将返回0这个结果。而if条件语句中判断 !flag 就是当收到返回值为0的时候 !flag 为真,则会输出以下结果:printf(“取到的余数为:%d”,res);

十四、结构体

1、基础入门以应用

①入门及了解

什么叫做结构体呢?看黑马程序员的例子:

看着话其实就像一个登记表一样,一个登记表里面有姓名、年龄、性别和身高,那么登记表的所采集的数据都是一样的,只是每个人所等级的数据是不一样的,那么你可以想象登记表就是结构体。

②结构体的格式

所以接下来就是交给大家如何应用结构体:

struct InputTable
    {
        char name[50];
        int age;
    };

首先的话这是结构体的一个固定的格式,其中呢 struct 就是声明它是一个结构体,InputTable就是一个结构体的姓名。那里面的内容呢?那就是登记表的内容嘛,姓名啊 年龄啊,是吧都可以填。

另外的话就是有一个小细节大家可以注意一下,就是结构体到底是要在main里面还是main外面呢?其实的话两个地方都可以存在,但是所代表的含义都不一样:

在内的话就是相当于局部变量 只能用作于一个main中,而在main外的话就是全局变量这样的话大家都可以用。

③结构体的定义和引用

如何进行定义数据并且说应用呢?比如说输出啊什么的,看示例代码:

    struct InputTable test;
    test.age = 10;
    strcpy(test.name, "John");

首先的话,第一行代码讲结构体InputTable用test来代替,后面的话定义InputTable就是用test来表示,后面的代码大家应该也是可以看懂,其实把它当一整块变量就可以了。包括输出也是一样:

    printf("%s\n", test.name);

然后总结:

2、结构体数组的应用

前面的话登记表的记录年龄一条,姓名一条,一个一个录是不是有点麻烦,现在的话是可以直接同时赋值进行写入数据的,看示例代码:

struct InputTable test = {"Hello World!", 5};

这样的话,登记表中的test就是同时被赋予了姓名和年龄,那如何讲多名学生塞入同一个登记表呢?看示例代码:

    struct InputTable st1 = {"Hello World!", 5};
    struct InputTable st2 = {"Hello World!", 6};
    struct InputTable st3 = {"Hello World!", 7};
    struct InputTable stu[3] = {st1, st2, st3};

示例代码中直接将 st1、st2、st3三名学生直接塞进了 stu[3] 这个数组中。

3、起别名

起别名是什么?直接看黑马程序员的一个解释:

起别名相较于前面比较初始的结构体会方便很多,方便在哪里?就是在赋值的部分中,看示例代码:

typedef struct
{
    char name[20];
    int age;
} Student;
int main()
{
    Student st1 = {"John", 20};
    printf("%s\n", st1.name);
}

看到了嘛,如果说直接用起别名的话是不需要和前面结构体那样定义,就设置别名 Student 后面的话每一名学生就是按照格式那样子,比如说学生 st1 ,直接进行赋值即可。同时数组的话也是一样方便:

Student arr[3] = {st1,st2,st3};

4、结构体作为函数的参数进行传参

对的,结构体我觉得可以当大号变量了,可以直接进行传参到函数,直接看示例代码:

#include <stdio.h>
#include <string.h>
typedef struct
{
    char name[20];
    int age;
} Student;
void method(Student student1);
int main()
{
    Student student;
    strcpy(student.name, "John");
    student.age = 18;
    printf("修改之前%s\n", student.name);
    method(student);
}
void method(Student student1)
{
    Student student;
    strcpy(student.name, "John1");
    student.age = 19;
    printf("修改之后%s\n", student.name);
}

看示例代码的话其实很明显,就是将student这个大号变量直接传入参数到函数method里面了,具体的话其实我觉得很好理解,其实就是大号变量啦!

5、结构体的嵌套

真就万物可以套娃是吧,我们的结构体也是可以进行嵌套的,但是我感觉可能类似于传参了。

#include <stdio.h>
#include <string.h>
struct Message
{
    char number[100];
    char mail[100];
};
struct Student
{
    char name[100];
    int age;
    struct Message msg;
};
int main()
{
    struct Student s;
    strcpy(s.msg.mail, "Hello World");
}

直接看示例代码,其中的话结构体Message直接被嵌套在了Student里面,所以Message中的数据也是同步在Student了,另外的话如果要定义引用的话也是从Student中引用的,就像示例代码中的:s.msg.mail 直接从Student提取嵌套的Message中的mail。直接用就可以了!

暂无评论

发送评论 编辑评论


|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇