函数、数组的学习

发布时间:2026/10/29 19:52:40
函数、数组的学习

一、函数的定义和调用

1、格式:

注意:
定义的函数不能写在 main 里面。函数里面不能再写其他函数。
应用时直接写函数名加括号。

eg:①

//#include <stdio.h> //void look() //{ // printf("打开手机\n"); // printf("打开小视频\n"); // printf("拨动\n"); // printf("赏析\n"); //} //int main() //{ // look(); // printf("吃一块饼干\n"); // look(); // return 0; //}

注意,函数定义了不会主动运行,因为运行时会去找 main 这个主入口,我们要在 main 中调用我们定义的这个函数

②计算10+20的和

//#include <stdio.h> //void sum() //{ // int a = 10; // int b = 20; // printf("%d", a + b); //} //int main() //{ // sum(); // return 0; //}

①当函数需要计算的参数不明确时,我们可以把参数定义在小括号中。此时只定义不给值,在调用时会根据实际情况传入不同的值。

②函数定义的小括号中叫形式参数,即形参,形参间用逗号隔开。函数调用的小括号中叫实际参数,即实参。形参与实参必须一一对应。

eg:①定义一个函数,求两数之和,并把结果输出到控制台上

//#include <stdio.h> //void sum(int num1,int num2) //{ // int sum = num1 + num2; // printf("%d\n", sum); //} //int main() //{ // sum(7,8); // sum(10, 20); // // return 0; //} 注注意上面的sum是函数名称,下面的sum是变量名

②定义一个函数打印多次“我想吃饭”,打印的次数由传入的参数决定

//#include <stdio.h> //void a(int b) //{ // for (int c = 1;c <= b;c++) // { // printf("我想吃饭\n"); // } //} //int main() //{ // a(100); // return 0; //}

3、带有返回值的函数最终完整格式

原来格式:

当题目复杂时,比如调用只需拿到函数计算的结果进行比较时,我们需要换一种方式,将最后的值不是打印出来,而是交给调用值→完整格式:

eg:

注意,返回值类型与返回值对应,返回的调用值需要用一个变量去吸收.

定义函数的终极绝招,问三个问题:
1. 我定义函数是为了干什么?确定函数体。
2. 我干这件事情需要什么才能完成?确定形参。
3. 我干完了调用处是否需要继续使用?确定返回值类型。

eg:①小明考试成绩:基础题93分,附加题10分。小红考试成绩:基础题87分,附加题9分。问谁的分高?

//#include <stdio.h> //int score(int a, int b) //{ // int score = a + b; 注,两个int score意义不同 // printf("%d\n", score); // return score; //} //int main() //{ // int c = score(93, 10); // int d = score(87, 9); // if (c > d) // { 调用方式,用变量去接收函数的结果 // printf("小明成绩更高"); printf("占位符”,函数的调用) // } // else if (d > c) // { 函数的好处:提高代码复用性,提高代码可维护性 // printf("小红成绩更高"); // } // else // { // printf("他们一样高"); // } // return 0; //}

②:

//#include<stdio.h> //int sum(int a, int b, int c) //{ // int sum = a + b + c; // return sum; //} //int main() //{ // int equal1 = sum(10, 20, 15); // int equal2 = sum(20, 30, 17); // int equal3 = sum(19, 17, 20); // int equal4 = sum(23, 21, 19); // int max_money = equal1; // int max_month = 1; // if (equal2 > max_money) // { // max_money = equal2; // max_month = 2; // } //if (equal3 > max_money) // { // max_money = equal3; // max_month = 3; // } // if (equal4 > max_money) // { // max_money = equal4; // max_month = 4; // }// printf("第%d个季度营业额最高\n", max_month); // return 0; // //}

函数的注意事项:
1. 函数不调用就不执行。
2. 函数名不能重复。
3. 函数与函数之间是平级关系,不能嵌套定义。4. return 下不能写代码。
5. 自未定义的函数写在 main 函数下面,需要在上方声明。

6. 函数返回值类型为 void,表示没有返回值,return 可以省略不写。如果书写了 return,后面不跟具体的数据,仅表示结束函数

4、C语言中常见的函数:

C语言会把这些函数放入不同的头文件中

使用#include <math>此类型

eg:①不同头文件中函数使用

//#include <stdio.h> //#include <time.h> //int main() //{ // long long res = time(NULL); // printf("%lld\n", time); 形参表示,获取的当前值是否需要在其他地方进行存储?一 //} 般来讲,不需在其他地方进行存储写NULL //#include <stdio.h> //#include <math.h> //int main() //{ // double a = pow(2,3); // printf("%lf\n", a); // double b = sqrt(8); // printf("%lf\n", b); // double c = ceil(3.1); // printf("%lf\n", c); // double d = floor(3.1); // printf("%lf\n", d); // double e = abs(-1); // printf("%lf\n", e); // return 0; //}

②获取随机数的函数

//#include<stdio.h> //#include<stdlib.h> 随机数头文件//#include<time.h> //int main() //{ //srand(time(NULL)); 设置种子// for (int i = 1;i <= 10;i++) // { //int num = rand() % 100 + 1;// printf("%d\n", num); // } // // // return 0; //}

注意:种子不变,随机数结果是固定的,所以用一个变化的量充当种子,即时间。

随机数的范围没有办法自行指定,

绝招:是用于生产任意范围之内的随机数:
1. 把这个范围变成包头不包尾、包左不包右的。
2. 拿着尾巴剪开头。
3. 修改代码。int num=rand()%100+1

二、递归函数(递归是一种解决问题的方法):

1、递归就是函数自己调用自己

2、递归的思想,把一个大型复杂问题,层层转化为一个与原题相似但规模较小的子问题来求解,直到子问题不能再拆分,递归就结束了。所以,递归的思考方式就是把大事化小的过程。递归中的“递”就是递推的意思,“归”就是回归的意思。

3、递归的限制条件递归在书写中有两个必要条件:
1. 递归存在终止条件,当满足这个终止条件时,递归便不再继续。
2. 每次递归调用之后,越来越接近这个终止条件。

eg:①求N的阶乘:

//#include <stdio.h> //int Fac(int n) //{ // if (n == 0) // { //return1; return,把后面的值交给调用处,并转化为一个与原问题相似、但 // } 较小的子问题。 // else // { //return Fac(n - 1) * n; // } //} //int main() //{ //int n; // scanf("%d", &n); // int a=Fac(n); // printf("%d\n", a); // return 0; //}

②顺序打印一个整数的每一位

//#include <stdio.h> //void print(int n) //{ //if (n > 9) // { // print(n / 10); // } // printf("%d", n % 10);// //} //int main() //{ // int n; // printf("请你输入一个数字:\n"); // scanf("%d", &n); //print(n); 没有返回值定义,一个变量去接纳。// return 0; // //}

3、递归与迭代

eg:求N的阶乘

法一:递归法。 法二:循环。

:递归函数调用的过程中涉及一些运行的开销

循环及迭代,当问题非常复杂时,难以用迭代的方式实现,此时递归实现的简洁性便可以补偿它所带来的运行时开销。

eg:斐波那契数列

法一:

//#include <stdio.h> //int Fib(int n) //{ // if (n <= 2) // { // return 1; // } // else // { // return Fib(n - 1) + Fib(n - 2); // } //} //int main() //{ // int n; // while (1) // { // printf("请输入一个数字:\n"); // scanf("%d", &n); // int a = Fib(n); // printf("相应的斐波那契数字为:%d\n", a); // } // return 0; // //} 法二: #include <stdio.h> int Fib(int n) { int a = 1; int b = 1; int c =1; while(n>=3) { c = a + b; a = b; b = c; n--; } return c; } int main() { int n; printf("请输入一个数字:\n"); scanf("%d", &n); int c = Fib(n); printf("%d\n", c); return 0; }

二、数组

1、定义:存储一批同类型数据的地方(同类型数据有隐式转换,取值范围小的赋值给取 · 值范围大的也可以)

2、格式:

3、特点:①:连续的空间。②维数组一旦定义,长度不可变,且写在开头。

//#include <stdio.h> //int main() //{ // /*int arr[80]; // double hight[50]; // int a[3];*/

4、数组的初始化:定义数组时,第一次给数组赋值。

格式:

细节:1. 长度省略:数据值的个数就是数组长度。
2. 长度未省略:数据值的个数小于等于长度。未赋值部分有默认值

eg:

/*int arr1[5] = { 17,18,19,18,19 }; // int hight[1] = { 1.68 };

5、元素访问:....获取、修改

①索引:是数组的一个编号,也叫角标、下标、编号。特点:从 0 开始的连续加 1 不 间断。
②获取:变量 = 数组名[索引]。

③修改:数组名「索引」=数据值

eg:

/*int arr[5] = { 1,2,3,4,5 };*/ // /*int a = arr[0]; // int b = arr[2]; // int c = arr[4]; // printf("%d\n", a + b + c); // arr[4] = 10;*/

6、数组遍历:依次获取数组中的每一个元素。

eg:

/*int arr[5] = { 1,2,3,4,5 };*/
/*for (int i = 0;i <= 4;i++) // { // arr[i]; // printf("%d\n", arr[i]); // }*/

7、内存中的变量数组,内存软件运行时用来临时存储数据

8.数组中的常见问题

9.数组的算法题练习

①求最值:已知数组元素为 [33,5,22,44,55],请找出数组中的最大值并打印在控制台

/#include <stdio.h> //int main() //{ // int arr[] = { 33,5,22,44,55}; // int len = sizeof(arr) / sizeof(int); // int max = arr[0]; // for (int i = 1;i < len;i++)注:max的默认值不可以写为0// {如果数组中的数都为负数,循环后最大值为0// if (max < arr[i])所以 max 的默认值一定要是数组中已经存在的数,// {一般把0索引当默认值// max = arr[i]; // } // } // printf("%d\n", max); // // return 0; //}

②

/遍历数组求和(基础版) // 生成10个1~100之间的随机数,存入数组 //#include <stdio.h> //int main() //{ // int arr[10] = {0}; // int len = sizeof(arr) / sizeof(int); // srand(time(NULL)); // for (int i = 0;i < len;i++)注:len表示长度,即元素个数// { // int num = rand() % 100 + 1; // arr[i] = num; // printf("%d\n", num); // } // int sum = 0; // for (int i = 0;i < len;i++) // { // sum = sum + arr[i]; // } // printf("%d\n",sum); // // return 0; //}

③

////遍历数组求和升级版:生成 10 个 1~100 之间的随机数,存入数组,要求数据不能重复 //// 1、求出所有数据的和。2、求出所有数据的平均数。3、统计有多少个数据比平均值小。 //#include <stdio.h> //#include <time.h> //#include <stdlib.h> //int contains(int arr[], int len, int num) //{ // for (int i = 0;i < len;i++) // { // if (arr[i] == num) // { // return 1; // } // }////问题一:为什么不能写 else return 0一触发return就结束//return 0; //}//int main() //{ // srand(time(NULL)); // int arr[10] = { 0 }; // int len = sizeof(arr) / sizeof(int); // for (int i = 0;i < len;) // { //int num = rand() % 100+ 1;// int flag = contains(arr, len, num); //if (!flag) // { // arr[i] = num; // i++; // printf("%d\n", num); // // } //// } // /*for (int i = 0;i < len;i++) // { // printf("%d\n", arr[i]); // }*/ // int sum = 0; // for (int i = 0;i < len;i++) // { // sum = sum + arr[i]; // } // printf("%d\n", sum); // int sve = sum / len; // printf("%d\n", sve); // int count=0; // for (int i = 0;i < len;i++) // { // if (arr[i] < sve) // { // count++; // } // } // printf("%d\n", count); // // return 0; //}

④

////反转数组:要求键盘录入 5 个数据并存入数组,完成以下需求:1. 遍历数组2. 反转数组 //#include <stdio.h> //void printArr(int arr[], int len) //{ // for (int i = 0;i < len;i++) // { // printf("%d\n", arr[i]); // } //} //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 num = arr[i]; // arr[i] = arr[j]; // arr[j] = num; // i++; // j--; // }// printArr(arr, len); // return 0; //}

⑤打乱数组中的数据:需求定义一个数组,存入1~5,要求打乱数组中所有数据的顺序

/#include <stdio.h> //#include <time.h> //#include <stdlib.h> //int main() //{ // int arr[] = { 1,2,3,4,5 }; // int len = sizeof(arr) / sizeof(int); // srand(time(NULL)); // for(int i=0;i<len;i++) // { // int num = rand()%len; // int temp = arr[i]; // arr[i] = arr[num]; // arr[num] = temp; // } // for (int i = 0;i < len;i++) // { // printf("%d\n", arr[i]); // } // return 0; //}

10.常见算法

1️⃣查找算法:①基本查找:核心思路就是从数值中的0开始,依次往后查找。如果找到了,就会返回数据对应的索引;如果没有找到,就会返回-1

eg:

///数组的基本查找 //#include <stdio.h> //int order(int arr[], int len, int num) //{ // for (int i = 0;i < len;i++) // { // if (arr[i] == num) // { // return i; // } // //为什么不可以写成else?要把return -1写在for循环的外面 // /*else // { // return -1; // }*/ // // } //return -1; //循环结束后,都无符合条件的才返回负一// //} //int main() //{ // int arr[] = { 2,23,43,55,65 }; // int len = sizeof(arr) / sizeof(int); // int num = 55; // int temp = order(arr, len, num); // printf("%d\n", temp); // return 0; // // //}

2️⃣:二分查找(折半查找):前提条件,数组中的数据必须是有序的

核心逻辑:每次排除一半的查找范围。

min 和 max 表示当前要查找的范围,mid 是在 min 和 max 中间的。

1. 如果查找的元素在 mid 左边,缩小范围时 min 不变,max = mid - 1。
2. 如果查找的元素在 mid 右边,缩小范围时 max 不变,min = mid + 1。

eg:

//#include <stdio.h> //int binarySearch(int arr[], int len, int num) //{ // int min = 0; // int max = len - 1; // //二分查找 // /*while (min <= max) // { // int mid = (min + max) / 2; //if (arr[mid] < num) // { // min = mid + 1; // } // else if (arr[mid] > num) // { // max = mid - 1; // } // else // { // return mid; // }// } // return -1;*/ // //插值查找 // while (min <= max && num >= arr[min] && num <= arr[max]) // { // // 防止除以 0 的错误(如果区间内所有数字都一样) // if (arr[max] == arr[min]) // { // if (arr[min] == num) return min; // else break; // } // // // 插值查找核心公式 // // 注意:必须"先乘后除"!防止类似 33/44 变成 0 导致死循环。 //int mid = min + (num - arr[min]) * (max - min) / (arr[max] - arr[min]);// // // 打印每次计算的mid,方便你观察过程 // printf("当前 min=%d, max=%d, 计算出的 mid=%d\n", min, max, mid); // // if (arr[mid] < num) // { // min = mid + 1; // } // else if (arr[mid] > num) // { // max = mid - 1; // } // else // { // return mid; // 找到了,返回数组下标 // } // } // return -1; // 没找到 // //} //int main() //{ // int arr[] = { 23,34,45,56,67 }; // int len = sizeof(arr) / sizeof(int); // int num = 34; // int temp = binarySearch(arr, len, num); // printf("%d\n", temp); // return 0; // //}

3️⃣:分块查找:
分块原则 1:前一块中的最大数据小于后一块的所有数据。
原则 2:块的数量一般等于数字个数的开根号。

11.排序算法:

1️⃣冒泡排序:
A. 相邻的数据两两比较,小的放前,大的放后。
B. 第一轮比较完后,最大值已经确定。第二轮可以少循环一次,后面以此类推。

eg:

/将35214进行从小到大的冒泡排序 //#include <stdio.h> //int main() //{ // int arr[] = { 3,5,2,1,4 }; // int len = sizeof(arr) / sizeof(int); // 外层循环控制比较的趟数,len 个数需要 len-1 趟 // for (int i = 0;i < len-1;i++) // { //内层循环控制每趟比较的次数小于 LEN-1-i,是为了防止 arr[j+1] 越界 // for (int j = 0;j < len-1-i;j++)// { // if (arr[j] > arr[j+ 1]) // { // int num = arr[j]; // arr[j] = arr[j + 1]; // arr[j + 1] = num; // } // } // // } // for (int i = 0;i < len;i++) // { // printf("%d\n", arr[i]); // } // return 0; //}

2️⃣选择排序从 0 索引开始,拿着每一个索引上的元素跟后面的元素依次比较,小的放前面,大的放后面,以此类推

eg:

////将35214从小到大选择排序 //#include <stdio.h> //int main() //{ // int arr[] = { 3,5,2,1,4 }; // int len = sizeof(arr) / sizeof(int); // for (int i = 0;i < len - 1;i++) // { // for (int j = i + 1;j < len;j++) // { // if (arr[i] > arr[j]) // { // //位置交换 // int num = arr[i]; // arr[i] = arr[j]; // arr[j] = num; // } // } // // } // //遍历数组 // for (int i = 0;i < len;i++) // { // printf("%d\n", arr[i]); // } // return 0; //}

12.二维数组

.

eg:

/#include <stdio.h> //int main() //{ // int arr[3][5] = { 0}; // /*int arr[3][5] = { { 1,2 },{ 3,4 } { 5,6 } };*/ // int len = sizeof(arr) / sizeof(arr[0]); // int len2 = sizeof(arr[0]) / sizeof(arr[0][0]); // for (int i = 0;i < len;i++) // { // for (int j = 0;j < len2;j++) // { ////为什么每个数字要空一格才能运行,否则不能运行 // scanf("%d", &arr[i][j]);// } // // } // for (int i = 0;i < len;i++) // { // for (int j = 0;j < len2;j++) // { // printf("%d ", arr[i][j]); // } // printf("\n"); // } // return 0; //}