实习集训【阶段1】 | 第2周

Day1【normal】

相关知识点

函数

(一) 概念:完成某个特定功能的指令序列的封装
作用:
	(一) 用来实现代码的复用
	要求:(高内聚【相关功能集中在一个函数】,低耦合【函数与函数之间没有什么关系】)
	(二) 实现模块化设计 ——> 结构非常清晰
	(三) 可以灵活组合调用
(二) 设计:
(一) 需求分析:要完成什么功能?需要什么资源【输入、输出】 ——> 从而确定了 “函数名 和 形参列表”
(二) 功能实现 ——> 算法
(三) 定义:
格式:
	返回值类型 函数名(形参列表)
	{
		功能语句;
		return ;
	}
注意:
	1、返回值类型:return后面表达式值的类型
		【一般为单值类型(基本类型、指针类型),也可以不需要返回值(void),如果不指定时,默认为int类型】
	2、函数名:须符合C语言标识符的规则
	3、形参列表:【void】数据类型1 形参1,数据类型2 形参2...
	4、不可在函数内部定义函数
(四) 调用:

1、主调函数和被调函数:调用和被调用
2、实际参数和形式参数

(五) 数据传递:
“分时”:
	主调函数 ——> 传参 ——> 被调函数
	主调函数 <—— return <—— 被调函数
“实时”:
	1、全局变量
(六) 作用域与生存期:
作用域:变量名能够产生作用的范围
1、全局变量:函数体外,定义在头文件之下
	作用域范围:从定义开始到整个文件结束
  	注意:
  		1、全局变量在别的文件也可以调用,但要extern声明(不可赋值,否则会从声明变成定义)
  		2、对于每一个函数来说,在函数前都有一个extern
  		3、如果不想让其他文件修改全局变量和调用函数【保护】在定义之前加上static修饰
------------------------------------------------------------------------------------------------------
2、局部变量:在函数体内或者某个复合语句内
		作用域范围:从定义开始到复合语句结束【即"}"】
------------------------------------------------------------------------------------------------------
【重点!!!!】
(一) 不同作用域的两个变量(就算两个变量同名),存在不同的两个不同的空间【就近往上寻找】
(二) 当主调函数调用被调函数的时候,就相当于只是简单赋值而已
生存期:变量过了生存期就会释放空间
1、全局变量:随进程持续存在
------------------------------------------------------------------------------------------------------
2、局部变量
	(一) 普通局部变量:从定义处到函数结束或者复合语句结束
	(二) static修饰的局部变量:随进程持续存在
(七) 递归:在函数调用中,直接或间接调用自己
经典例题:求阶乘 n!

练习作业

1、作业

作业1
例题1:
	递归求数列
	a1=10,an=a(n-1)+15
	求出输入第n项的值和前n项的和	
arg:
	n 第n项的值
作业2
例题2:
		求最近的质数  
			如果输入的数本身就是质数,输出它自己
			如果输入的数最近的质数有两个,输出小的那个
arg:
	n 输入的参数
作业3
例题3:
	汉诺塔   打印出移动的路径
arg:
	n 汉诺塔的层数

思考拓展

(一) 形参列表相关拓展

(一) main函数默认的两个参数:argc、argv【虽然我们一般不写但是它们是存在的】:
	1、argc【arguments count】:必须是整型变量
	2、argv【arguments value/vector】:必须是指向字符串的指针数组
(二) 可变形参【待补充】

(二) for循环的两个生存周期

例题:
	#include <stdio.h>
	
	int main()
	{
	    for (int i = 0; i < 5; i++)
	    {
	        for (int i = 0; i < 5; i++)
	        {
	            printf("%2d", i);
	        }
	        printf("%5d\n",i);
	    }
	}
结果:
	0 1 2 3 4      0
	0 1 2 3 4      1
	0 1 2 3 4      2
	0 1 2 3 4      3
	0 1 2 3 4      4
分析:
	说明在for循环内部定义的生存周期只是在其对应的循环体中

(三) 函数返回值类型不一定是单值类型

之前笔记中有说过函数返回值一般是单值类型,但不是说只能返回单值类型【复合类型也是可以的】

(四) 函数指针和指针函数

(一)、函数指针【本质为指针】
	格式:
		数据类型 (*函数名)(形参列表)
	例子:
		int (*fun)(void);	-------> 	是一个int类型函数的指针
(二)、指针函数【本质为函数】
	格式:
		数据类型* 函数名(形参列表)
	例子:
		int * fun(void);	-------> 	返回一个int*类型的数据

(五) void*类型

1、void【补充】(无类型):
	对函数返回的限定和对参数返回的限定,即可以不用输入值和输出值
2、void*(无类型指针):
	其他类型指针可以不需要强转为(void*),直接给void*变量赋值
例如:
	void *p1;
	int *p2;
	p1 = p2;

Day2 + Day3 + Day4【normal】

相关知识点

数组(一组具有相同数据类型的数据集合)

【如果有多个同类型的变量,就可以用到数组】

(1) 分类
1、一维数组
1、定义格式:
		类型说明符	数组名[整型表达式]  
		【以 int a[4];为例子:本质还是int[4] a;相当于有一种数据类型叫int[4],这个对二维数组的理解很重要】
	 说明:
	 	(一) 类型说明符:只要是合法的类型即可
	 	(二) 数组名:1、要符合C语言标识符规则规范	2、数组名为数组的首地址(常量),所以一定【不能修改】
	 	(三) 整型表达式
2、使用:
	引用:数组名[下标]	<————————>	跟普通变量用法一致
	【注意】:下标从0开始,可以是常量表达式也可以是变量表达式
	初始化:"{ }"
	【注意】:1)、只能在定义的时候初始化
			 2)、在进行全部初始化时,注意不能越界
			 3)、可以只对部分元素进行初始化,没有赋值到的部分自动赋值为0
			 4)、 如果对数组元素赋值,那么我们就可以不指定数组长度,例如 int a[]={1,2,3,4};
			 5)、一个特殊数组:int a[]={};	 数组长度为0的数组【然而并没有什么很大的用处】
			 6)、对于一个可变数组时,不可进行初始化【补充:只能通过scanf循环来循环赋值】
2、二维数组
1、定义格式:
		类型说明符	数组名[整型表达式1][整型表达式2]  
	 说明:
	 	(一) 类型说明符:只要是合法的类型即可
	 	(二) 数组名:1、要符合C语言标识符规则规范	2、数组名为数组的首地址(常量),所以一定【不能修改】
	 	(三) 整型表达式
2、使用:
	引用:数组名[行][列]	<————————>	跟普通变量用法一致
	【注意】:下标从0开始,可以是常量表达式也可以是变量表达式
	初始化:"{ }"
	【注意】:1)、只能在定义的时候初始化
			 2)、在进行全部初始化时,可以用{}来区分(没什么很多用),注意不能越界
			 3)、可以只对部分元素进行初始化,可以用{}来区分(会把一列没有不全的值补齐),没有赋值到的部分自动赋值为0
			 4)、 如果对数组元素赋值,那么我们就可以不指定数组长度,例如 int a[][3]={1,2,3,4,5,6};
			 5)、对于一个可变数组时,不可进行初始化【补充:只能通过scanf循环来循环赋值】
3、字符数组
1)、定义
	两种定义方法:
		1、char c1[]={'c','h','i','n','a'};	【sizeof(c1) --> 5】
		2、char c2[]="china";				【sizeof(c2) --> 6】
   【易错点】:
   		char c2[]="china";--->char c2[]={'c','h','i','n','a','\0'};
2)、相关函数
	(一) gets、puts
		1、gets【BUG】
		【注意】:
			a. gets有巨大的BUG,gets函数不会考虑保存这个字符串的数组的空间是否足够,如果超出了分配的范围还会继续写数据,可能会改变其他变量的数据。
			b. gets函数不会获取到'\n',当遇到'\n'的时候,会补一个'\0'并且结束输入,puts函数在输出的时候会自动换行
			c. gets获取字符串的时候,还可以获取空格,tab等空白字符,回车结束输入 
		2、puts
		【注意】:把str指向的空间中保存的字符串打印出来,直到遇到第一个'\0',且自动换行
----------------------------------------------------------------------------------------------------------
	(二) scanf
		【注意】:scanf函数遇到空格、tab、回车结束输入
----------------------------------------------------------------------------------------------------------
	(三) strcpy/strncpy 
		1、 char *strcpy(char *dest, const char *src);
				@dest:指向用来保存的字符串数据
				@src:指向要拷贝的字符串的数据
			返回值:
				如果成功,返回拷贝后字符串的首地址,就是dest指向的地址
				如果失败,返回NULL 
		【注意】:
				a.不会关心dest指向的空间是否够用,造成内存溢出
				b.strncpy函数就是为了修复strcpy函数的BUG的,它的功能与strcpy一样,只不过顶多拷贝n个字节
				
		2、 char *strncpy(char *dest, const char *src, size_t n);
				@dest:指向用来保存的字符串数据
				@src:指向要拷贝的字符串的数据
				@n:最多拷贝n个字节 
			返回值:
				如果成功,返回拷贝后字符串的首地址,就是dest指向的地址
				如果失败,返回NULL 
		【注意】:
			strncpy到底拷贝了多少个字节?
			(1)在还没有拷贝n个字节的时候,提前遇到src的'\0',剩余的字节也会拷贝'\0'
			(2)没遇到'\0',但是已经拷贝了n个字节,结束拷贝。(不会补'\0')	
----------------------------------------------------------------------------------------------------------			
	(四) strcat/strncat 
		1、char *strcat(char *dest, const char *src);
			@dest:指向用来保存的字符串的空间,注意空间是否够用
			@src:指向要追加的字符串
		返回值: 
			如果成功,返回追加后字符串的首地址,就是dest指向的地址
			如果失败,返回NULL 
		【注意】:
				a.strcat函数也有bug,不关系dest指向的空间是否够用,可能会造成内存溢出
				b.strncat与strcat功能类似,只不过只追加n个字节
				
		2、char *strncat(char *dest, const char *src, size_t n);
			@dest:指向用来保存的字符串的空间,注意空间是否够用
			@src:指向要追加的字符串
			@n:至多追加n个字节
		返回值:
			如果成功,返回追加后字符串的首地址,就是dest指向的地址
			如果失败,返回NULL 
		【注意】:
			strncat到底追加了多少个字节?
			(1)正常追加了n个字节的数据后,会在末尾补一个'\0' 
			(2)在还没有拷贝到n个字节的时候,遇到了src的'\0',提前结束追加(会在末尾补一个'\0')
----------------------------------------------------------------------------------------------------------			
	(五) strcmp/strncmp 
		都是从第一个字符开始比较,一个一个字符的比较ASCII码的大小
			if(c1 > c2)则返回c1的ASCII-c2的ASCII  >0
			if(c1 < c2)则返回c1的ASCII-c2的ASCII  <0
			if(c1 == c2) 则继续比较下一个,如果全部相等则返回0
			   
			1、int strcmp(const char *s1, const char *s2);
			2、int strncmp(const char *s1, const char *s2, size_t n);
	【注意】:strncmp与strcmp功能类似,只不过只比较两个字符串的前n个字符
----------------------------------------------------------------------------------------------------------			   
	(六) strlen 
		【注意】:strlen函数遇到'\0'自动结束计数且不包括'\0',与sizeof有很大区别

练习作业

1、作业

作业1
// 	例题1:冒泡排序法
/*
	功能:
		完成冒泡排序法的算法
	输入:
		void
	输出:
		void	
*/
作业2
// 	例题2:斐波那契数列
/*
	功能:
		输出斐波那契数列第n项的值
	输入:
		n	第n项
	输出:
	   -1   参数有误
   其他值		斐波那契数列第n项的值
*/
作业3
// 	例题3:判断数组类型
/*
	功能:
		判断数组类型:【升序、降序、平序、乱序】
	输入:
		void
	输出:
		void
*/
作业4
// 	例题4:二分查找法
/*
	功能:
		输入指定元素,找到对于下标
	输入:
		void
	输出:
	   -1	无对应元素的下标	
   其他值		所查元素所在的下标	
*/

思考拓展

(一) printf( )的执行顺序

例子:
	int num=0;
	int add()
	{
		num++;
		return num;
	}

	int main()
	{
		printf("%d %d\n",num,add());
		printf("%d %d\n",add(),num);
	}
结果:
	1 1
	2 1
分析:
	【由于printf输出的顺序实际是从右向左】
	所以第一个是先add()再输出,结果:1 1
	同理第二个是先再输出add(),结果:2 1

(二) 排序【待补充】

1、冒泡排序
请添加图片描述

2、插入排序
请添加图片描述

3、选择排序
4、快速排序
5、堆排序
6、希尔排序
7、归并排序
8、基数排序
9、计数排序
10、桶式排序

(三) 查找(基于C)【待补充】

1、顺序查找

int sequentialSearch(int[] array, int target) {
       for (int i = 0; i < array.length; i++) {
           if (array[i] == target) {
               return i;
           }
       }
       return -1;
   }

2、二分查找

int binarySearch(int[] array, int target) {
        int left = 0, right = array.length - 1;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (array[mid] == target) {
                return mid;
            } else if (array[mid] < target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return -1;
    }
3、插值查找
4、斐波那契查找
5、树表查找
6、分块查找
7、哈希表查找

(四) 数组指针和指针数组

(一)、数组指针【本质为指针】
	格式:
		数据类型 (*函数名)[整型表达式]
	例子:
		int (*nums)[4];	-------> 	是一个指向int[4]类型数组的指针
(二)、指针数组【本质为数组】
	格式:
		数据类型* 函数名[整型表达式]
	例子:
		int * nums[4];	-------> 	是一个4个单元且每个单元是一个指针的一维数组

(五) int a[ ][3]

int a[ ][3] 的本质就是 	------->	int[3] a[],即不定长的以int[3]为一个单元的数组

(六) 数据库知识的基础复习

对于表操作:
1、“增”
2、“删”
3、“改”
4、“查”

(七) 字符串可读可写性【常量的判断,很重要!!!】

例题:
	1、char str1[10] = "abcd";
	2、char str2*="abcd";
	
	对于上述两种表达式,判断以下操作是否是正确的?
		a.str1[0]='z';
		b.str2[0]='z';
		c.str1++;
		d.str2++;.
结果&分析:
		a.right		char str1[10] = "abcd";是已经向系统申请了空间来存放"abcd"并将其放在栈里【可读可写】
		b.error		char str2*="abcd",只是将指针指向"abcd"空间,没有单独开辟空间,此时“abcd”是常量,如果赋值就犯了1=2;的问题【赋值符号左边必须是变量】
		c.error		由于对于数组名来说是一个常量,所以如果赋值就犯了1=2;的问题【赋值符号左边必须是变量】
		d.right		由于str2是变量,可以进行赋值操作

Day5【easy】

相关知识点

C程序的组成部分:

1、c文件
	(1)、预处理语句
		a.文件包含命令	#include
			【注意】(再次提到):#include <> 和 #include ""的区别:
					1、前者在库函数指定的路径去搜索(/usr/include,......)
					2、后者
						1、先在工程目录(当前目录)下去查找头文件
						2、找不到再去指定的路径去搜索(必须是编译命令+ -I[你自己指定的位置])
						3、还是找不到再去库函数指定的路径
					
		b.宏定义			#define
			【注意】 
				1、#define 可以不带参数,即我们”熟知“的【符号常量】
				2、#define 可以带入参数,但是这是简单的替换,一般需要我们添加括号
					【例如】 #define Fun(a,b) a*b 和 #define Fun(a,b) (a)*(b) 的区别 
		c.条件定义
			1、#ifdef  +  #endif
			2、#ifndef +  #endif
			2、#if 	   +  #endif
			
【拓展】:查看预处理: gcc 1.c -E -o 1.i //用gcc把1.c进行预处理,还没有编译,然后生成1.i 

	(2)、全局声明
		"声明":C语言中的声明就是把一个名字的属性进行说明。
		
		一般在定义变量或者函数的时候,就规定了变量或者函数的属性 所以称之为定义也属于声明
		
		C语言的编译顺序是从上到下,所以我们在调用某个变量或者函数的时候,必须要先声明(定义),让系统知道它们属性之后,再调用它们。
		
		声明的分类:
			变量的声明(定义变量,声明外部变量)
			函数的声明(定义函数,声明函数)
			类型声明(定义类型) -->构造类型  【补充】
			
	(3)、函数
		1、main函数(由它开始【唯一入口】,由它结束)	【由操作系统调用main函数】
		2、其他函数
------------------------------------------------------------------------------------------------------------------
2、h文件【来进行一些声明,比如导出一个函数接口(API)或者全局变量 】
	内容:
		1、函数声明
		2、构造类型声明【拓展:结构体/联合体的构建是不会占据内存】
		3、全局变量的外部声明
【提示】: 每个独立的模块引用其他模块的时候,尽量不用放在h文件中,重复引用

工程搭建的结构:

project【工程名字】
| ----- bin 			程序运行文件
| ----- src				所有的源文件(.c文件)
| ----- lib 			可能用的到的外部的库文件
| ----- inc 			所有的自定义的头文件(.h文件)
| ----- LICENSE.txt 	项目的说明书(项目名称,启动时间,负责人,功能介绍.....)

思考拓展

(一) 随机函数的使用

1.播放随机数种子  
	srandom(time());
2.随机数获取
	int num = random();

(二) 考试错题总结

1、对于笔试考试时,一定要堤防变量是否舒适化的问题
2、关系运算符的先后顺序【以后再错,就抄10边那个关系比较式!!!】
3、if - else的组合关系 【注意看if()后是否有;】
4、对于任意一个数组,都不可直接对数组名直接进行赋值【懂得都懂,但考试的时候很容易被迷惑】
	例如:char str[4];	str = "123"; 【错误】
5、如果出现野指针,栈溢出等问题时,系统的提示是"段错误",不是"下标越界"!!!!!
6、字符长度	----->	strlen() 判断结果			数组长度	----->	sizeof() 判断结果

(三) EasyX图像库【待了解】

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值