培训笔记4
数组
定义
命名相同类型的有限变量的集合,该名称是一个数组名称。
组成数组的变量称为数组的元素。
声明和访问
声明
定义一个数组时所需的基本语法
int scores[5]
初始化
int scores[5] = {90, 85, 80, 75, 70};
初始化部分元素
int scores[5] = {90, 85};
初始化第一,第二元素,其余为0
让编译器自动推断大小
int scores[] = {90, 85, 80, 75, 70};
使用索引访问元素
printf(“%d”, scores[0]); // 输出90
pfor(int i=0;i<=n;i++)
printf(“%d”, scores[i]); // 输出90
注意点:数组的索引从0开始,超出数组范围的索引可能导致未定义的行为
用取模来实现下标循环
多维数组
多维数组就像是个表格,矩阵,有行和列
初始化和声明
声明一个3x4的二维数组
int a [3] [4];
初始化
int a[3] [4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
访问元素
printf(“%d”, a[1][2]); // 输出7
使用双重循环遍历
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++){
printf(“%d “, a[i][j]);
}
printf(“\n”);
}
还可以用取模的方法只用一个循环遍历
字符数组
定义
字符数组可以用来存储一个字符序列。例如:char name[5];
字符串与字符数组
在C中,字符串其实是一个字符数组,其中每个字符都按顺序存储,而且最后有一个额外的字符‘\0’,表示字符串的结束。这就是为什么字符串”John”实际上在内存中占据5个字符的空间:’J’, ‘o’, ‘h’, ‘n’, 和 ‘\0’。
初始化
1 | char name[] = "John"; |
元素为 ‘J’ ‘o’ ‘h’ ‘n’ ‘\0’
访问和修改字符数组
printf(“%c\n”, name[2]); // 输出h
pprintf(“%s\n”, name);// 输出 John
name[2] = ‘a’; //其余元素不变
字符串函数
头文件<string.h>
strlen(): 返回字符串的长度(不包括结束字符\0)。
strcpy将一个字符串拷贝给另一个字符串
返回值会返回被传的字符串
strcat(): 连接两个字符串。
strcmp(): 比较两个字符串。
基本形式为strcmp(str1,str2),若str1=str2,则返回零;若str1<str2,则返回负数;若str1>str2,则返回正数,返回值只与第一个不同字符有关,与第二个不同字符无关
在字符串中找一个字符strchr(左到右),strrchr(从右到左)
返回值为指针,即第一次出现的位置,返回null为没找到
若想找第二个字符,以下为一种方法(左到右):
(p为指针)
p=strchr(str,’a’);
p=strchr(p+1,’a’);
strstr字符串内找字符串
strcasestr找的过程内忽略大小写
函数
定义
函数是C语言中的一个基本构建块,用于封装代码以执行特定的任务
函数是为执行特定任务而组织的一段程序代码,它可以有输入(称为参数)和输出(返回值)
函数就是把实现某一个功能的所有的代码打成一个包,每次需要这个功能的时候不用重复去写实现这个功能的代码,而是使用函数
声明与访问
声明:函数声明告诉编译器函数的名称、返回类型和参数。
int add(int a,int b);
定义:函数的定义提供函数的实际实现
int add(int a, int b) {
return a + b;
}
调用
int sum = add(5, 6);
函数的参数
按值传递:这是C语言的默认参数传递方式,函数接收参数的值,对参数的修改不会影响调用者。
按引用传递:C语言通过传递指针来实现这一点。函数接收参数地址的指针,因此可以修改原始数据。
返回值
函数可以返回一个值给调用栈,这可以通过’return’语句实现
形参与实参
形参
int add(int a, int b) {
return a + b;
}
实参
int sum = add(5, 6);
例子
1 |
|
该函数无返回值,形参改变不影响实参,所以a,b,c,d还是原值
数组做参数
数组做参数时,传达的是一个地址
可在函数内通过对地址上的形参进行修改来修改实参
递归
原理
在一个函数中反复调用它自身
汉诺塔
1 |
|
思路
当n个盘的最大的盘在底部时,可将其看成n-1的盘进行移动
三个柱子,分别为 出发地,中转地,目的地
每次最大盘到达目的地时,随后看成n-1盘
出发地,中转地,目的地改变
如此递归
非尾递归与尾递归
非尾递归
非尾递归意味着递归调用不是函数的最后一个操作,递归调用的结果通常需要进一步处理。
1 |
|
尾递归
尾递归意味着递归调用是函数的最后一个操作。编译器能够优化尾递归,将其转换为迭代调用,这样可以避免栈溢出的问题并提高效率。
尾递归效率比非尾递归快的原因
非尾递归过程中对一相同过程进行了多次反复运行