4.2 二维字符数组
1:引入目的:对于处理多个一维字符数组不方便时,可以引入二维字符数组
从该角度来看,二维字符数组其实就是一维字符串数组
2:定义格式:char 数组名[常量1][常量2];
常量1:表示的是定义的字符串的个数 参数2:表示的是每个字符串的最大长度+1
3: 初始化方式
1、单字符初始化:该方式跟二维整形数组一致
2、字符串初始化:
全部初始化:char arr[3][8] = {"apple", "banana", "orange"}; arr[0] arr[1] arr[2]
特殊初始化:char arr[][8] = {"apple", "banana", "orange"}; //此时省略的第一维,会根据初始化字符串的个数确定
部分初始化:char arr[5][8] = {"apple", "banana", "orange"}; //没有初始化的字符串 默认为空串
4: 二维数组元素的使用
1、单字符使用:数组名[行标][列表] ---->找到了指定位置上的某个字符
2、字符串使用:数组[行标]; ---->找到了制定行的一个字符串
5: 二维字符数组输入输出、求最值、排序
#include<stdio.h>
#include<string.h>
#define MAX 4
int main(int argc, char const *argv[])
{
char arr[MAX][20]={" "};
for (int i = 0; i < MAX; i++)
{
printf("请输入第%d个字符串:",i+1);
scanf("%s",arr[i]);
}
//输出所有的字符串
printf("目前的字符串分别是:");
for(int i=0; i<MAX;i++)
{
printf("%s\t", arr[i]);
}
puts("");
//
char max[20]=" ";
strcpy(max,arr[0]);
for (int i = 0; i < MAX; i++)
{
if(strcmp(max,arr[i])<0)
{
strcpy(max,arr[i]);
}
}
printf("%s\n",max);
char temp[20]=" ";
for (int i = 1; i < MAX; i++)
{
for (int j = 0; j < MAX-i; j++)
{
if(strcmp(arr[j],arr[j+1])>0)
{
strcpy(temp,arr[j]);
strcpy(arr[j],arr[j+1]);
strcpy(arr[j+1],temp);
}
}
}
printf(" ");
for (int i = 0; i < MAX; i++)
{
printf("%s\t",arr[i]);
}
putchar(10);
return 0;
}
[5]函数
5.1 引入目的
1: 系统会提供一些库函数供大家使用,但是,提供的函数毕竟有限,如果想要使用特别定制的函数,需要自己封装
2: 对于一些重复调用的语句块而言,如果不加封装的话,会使得代码比较冗余
3: 为了提高编程效率,我们引入了函数,能够做到一处修改,处处修改
4: 目前接触的函数:printf、scanf、putchar、getchar、puts、gets、strlen、strcmp、strcat、strcpy
5.2 函数的定义
1: 函数:执行特定功能的一段代码块
2: 定义格式: 返回值类型 函数名(参数列表) { 函数体代码 }
1、返回值类型:函数执行后,向外界返回的一个结果值,可以有结果(非void),也可以没有结果(void) 定义函数时:有返无返看主调,主调函数想要数据,就定义有返回值函数,主调函数要什么类型的结果,就定义什么数据类型 主调函数不要数据,就定义void类型
2、函数名:是一个标识符,要符合命名规则
3、():小括号是函数的标识,即使是没有参数的函数调用时也要将括号加上
4、参数列表:可以有,也可以没有,表示外界向该函数体提供的数据
定义函数是:有参无参看主调,主调函数给数据,就定义有参函数,主调函数给几个数据,就定义几个参数接收,主调函数给什么类型的数据,就定义什么类型的参数接收 主调函数不给数据,就不定义参数
5、{}:要封装的函数体代码,要用花括号包裹起来
6、函数体代码:要被封装的内容
5.3 函数的分类
1: 对于函数定义格式而言,函数名和函数体代码是不可变的,但是,函数的返回值类型和函数的参数是可变的
2: 对于一个函数而言,返回值是可有可无的,参数也是可有可无的,根据此,函数分为四大类
1、无参无返回值函数:该函数,仅仅只是单纯执行特定的代码,没有数据传入,也不需要返回结果,仅仅只是执行一个过程
函数定义格式: void 函数名(void) {} 例如:void print_menu(void);
2、有参无返回值函数:该函数,需要主调函数传入给定的数据后,才能进行执行该功能,但是,执行结束后,没有返回结果
函数定义格式:void 函数名(形参列表) {} 例如:void print_arr(int arr[], int n);
3、无参有返回值函数:该函数无需外界传入数据,直接执行内部语句,并且执行结束后,会向主调函数返回一个确定的数据
函数定义格式:返回值类型 函数名(void){} 例如:int getchar(void);
4、有参有返回值函数:该函数需要外界提供对应的参数,执行函数体代码后,并向主调函数返回一个确定的值
函数定义格式:返回值类型 函数名(参数列表) {} 例如:int strlen(char *src);
3: 关于函数的相关概念
主调函数:调用别的函数的函数叫做主调函数
被调函数:被别的函数调用的那个函数称为被调函数
形式参数:也称形参,定义函数时,括号里面的参数称为形参
实际参数:也称实参,函数调用时,括号里面的参数称为实参
4: 函数调用格式:变量名 = 函数名(实参列表);
#include<stdio.h>
#include<string.h>
int main(int argc, char const *argv[])
{
//菜单
while (1)
{
print_neum();
int menu =0;
scanf("%d",&menu);
switch (menu)
{
case 1:
{
sum_1();
}
break;
case 2:
{
int n=0,m=0;
printf("请输入两个数字");
scanf("%d%d",&n,&m);
sum_2(n,m);
}
break;
case 3:
{
int sum= sum_3();
printf("sum = %d\n", sum);
}
break;
case 4:
{
int num,key; //这两个数据是主调函数中的
printf("请输入两个数:");
scanf("%d%d", &num, &key);
int sum = sum_4(num, key); //调用有参有返回值函数
printf("sum = %d\n", sum);
}
case 0:
return 0;
}
}
return 0;
}
//菜单显示
void print_neum()
{
printf("1.无参无返回值");
printf("2.有参无返回值");
printf("3.无参有返回值");
printf("4.有参有返回值");
}
//无参无返回值
void sum_1()
{
int num,key;
printf(" 请输入数字");
scanf("%d%d",&num,&key);
int sum=num+key;
printf("%d\n",sum);
}
//有参无返回值
void sum_2(int n,int m)
{
int sum=n+m;
printf("%d\n",sum);
}
//无参有返回值
int sum_3()
{
int n=0,m=0;
printf("请输入两个数字");
scanf("%d%d",&n,&m);
int sum=n+m;
return sum;
}
//有参有返回值
int sum_4(int n,int m)
{
int sum=n+m;
return sum;
}
练习:
1: 定义一个有参无返回值函数,主调函数传入两个整数,被调函数中输出两个整数的最大值
2: 定义无参有返回值函数,被调函数中定义并初始化一个长度为5的整形数组,求出该数组的最大值,传递给主调函数输出
3: 定义一个有参有返回值函数,主调函数传入三角形的三条边,被调函数判断为何种三角形,并返回给主调函数
返回值设定:
-1:表示不能构成三角形
0:表示构成普通三角形
1:构成等腰三角形
2:构成等边三角形
//定义一个有参无返回值函数,主调函数传入两个整数,被调函数中输出两个整数的最大值
#include<stdio.h>
#include<string.h>
int main(int argc, char const *argv[])
{
int n=0,m=0;
printf("请输入两个整数:");
scanf("%d%d",&n,&m);
MAX(n,m);
return 0;
}
//输出最大值
void MAX(int n,int m)
{
if (n>=m)
{
printf("%d\n",n);
}else
{
printf("%d\n",m);
}
}
//定义无参有返回值函数,被调函数中定义并初始化一个长度为5的整形数组,求出该数组的最大值,传递给主调函数输出
#include<stdio.h>
#include<string.h>
int main(int argc, char const *argv[])
{
printf("%d",MAX());
return 0;
}
//输出最大值
int MAX()
{
int arr[5]={0};
for (int i = 0; i < 5; i++)
{
scanf("%d",&arr[i]);
}
int max=0;
for (int i = 0; i < 5; i++)
{
if (max<arr[i])
{
max=arr[i];
}
}
return max;
}
//定义一个有参有返回值函数,主调函数传入三角形的三条边,被调函数判断为何种三角形,并返回给主调函数
//返回值设定:
//-1:表示不能构成三角形
//0:表示构成普通三角形
//1:构成等腰三角形
//2:构成等边三角形
#include<stdio.h>
#include<string.h>
int main(int argc, char const *argv[])
{
int x=0,y=0,z=0;
printf("请输入三角形三边长:");
scanf("%d%d%d",&x,&y,&z);
printf("%d",judge(x,y,z));
switch (judge(x,y,z))
{
case 0:
printf("普通三角形\n");
break;
case 1:
printf("等腰三角形\n");
break;
case 2:
printf("等边三角形\n");
break;
case -1:
printf("不能构成三角形\n");
break;
}
return 0;
}
//判断函数
int judge(int x,int y,int z)
{
if ((x+y>z)&&(x+z>y)&&(y+z>x))
{
if(x==y&&y==z)
{
return 2;
}
else if (x==y||y==z||z==x)
{
return 1;
}else
{
return 0;
}
}else
{
return -1;
}
}
5.4 函数与变量的关系
1: 局部变量:定义在函数内部的变量称为局部变量
局部变量的表现形式:定义在函数体内的变量
函数的形式参数
定义在语句块内的变量
局部变量的作用域:从定义开始,到函数结束(语句块内的变量到语句结束)
注意:不同作用域下的局部变量可以同名
2: 全局变量:也称全程变量和外部变量,就是定义在函数体外部的变量
作用域:从定义开始到整个程序结束为止,该变量定义后的任意一个函数都可以使用他
注意:局部变量可以跟全局变量同名,函数体内使用的默认是局部变量(就近访问原则,局部优先原则)
如果非要使用全局变量,也不是不可以,需要使用关键字 extern 来声明
#include<myhead.h>
void fun(); //将函数提前声明
int value = 1314; //该变量是全局变量
//自定义函数
void fun()
{
int argc = 520; //不同作用域下允许定义同名的变量
//函数只能使用提前定义的全局变量,后面的全局变量不能使用
//printf("value = %d, value_1 = %d\n", value, value_1);
}
//定义全局变量
int value_1 = 666;
int main(int argc, const char *argv[])
{
printf("argc = %d\n", argc); //输出传入参数的个数
for(int i=0; i<argc; i++)
{
printf("argv[%d] = %s\n", i, argv[i]); //输出传入的值
}
int num = 520; //定义函数内部的变量,该变量的作用域从定义到程序结束
//定义语句块内的变量
if(1)
{
int key = 1314; //这里也是局部变量,作用域仅仅在if语句块内
}
//此处可以使用局部变量num但是不能使用局部变量key
//printf("argc = %d, num = %d, key = %d\n", argc, num, key);
int value = 999; //定义一个与全局变量同名的局部变量
printf("value = %d\n", value); //999
{
extern int value; //表示要使用全局变量的value
printf("value = %d\n", value); //1314
}
return 0;
}
3: 静态局部变量:在函数体内定义一个功能上类似于全局变量的局部变量
定义格式:static 数据类型 变量名;
作用域:只能在函数体内被使用,但是,生命周期随着整个程序的结束而结束
#include<myhead.h>
void fun()
{
int num = 520; //定义一个普通的局部变量
num ++;
printf("num = %d\n", num);
}
void hun()
{
static int num = 520; //定义一个静态的局部变量,具有保值的功能
//不会随着所在函数结束,而释放空间
num ++;
printf("num = %d\n", num);
}
//主程序
int main(int argc, const char *argv[])
{
for(int i=0; i<3; i++)
{
hun();
}
return 0;
}
[6]、数组作为函数参数传递
1: 数组的要素:起始地址(数组名),数组的容量
2: 数组作为函数参数传递,属于地址传递,形参内容的改变,实参内容也会跟着改变
3: 定义形参接受数组时,接受数组名时,只需要定义一个变量标识数组即可
#include<myhead.h>
//定义输出函数
void print_arr(int brr[], int n)
{
printf("数组元素分别是:");
for(int i=0; i<n; i++)
{
printf("%d\t", brr[i]);
}
puts("");
}
//定义排序函数
void sort_arr(int brr[], int n, int flag)
{
for(int i=1; i<n; i++)
{
for(int j=0; j<n-i; j++)
{
if(flag == 0) //升序
{
if(brr[j]>brr[j+1])
{
int temp = brr[j];
brr[j] = brr[j+1];
brr[j+1] = temp;
}
}else
{
if(brr[j]<brr[j+1])
{
int temp = brr[j];
brr[j] = brr[j+1];
brr[j+1] = temp;
}
}
}
}
}
//定义输出brr的函数
void print_brr(char brr[][20], int n)
{
printf("传入的字符串分别是:");
for(int i=0; i<n; i++)
{
printf("%s\t", brr[i]);
}
puts("");
}
/******************主程序***************************/
int main(int argc, const char *argv[])
{
int arr[8] = {1,3,2,6,7,9,5,10}; //定义一个数组并初始化
//调用函数完成对该数组的输出
print_arr(arr, 8); //传递数组时,只需要传递数组名和数组容量
//调用排序函数
sort_arr(arr, 8, 0); //升序排序
//输出排序后的结果
print_arr(arr, 8);
//定义二维字符数组
char brr[][20] = {"banana", "apple", "zhangsan"};
//调用函数输出数组
print_brr(brr, 3);
return 0;
}
作业:
完成学生管理系统
1> 使用菜单完成
2> 有学生的信息录入功能:输入学生个数,并将学生的姓名、分数录入
3> 查看学生信息:输出所有学生姓名以及对应的分数
4> 求出学习最好的学生信息:求最大值
5> 按姓名将所有学生进行升序排序
6> 按成绩将所有学生进行升序排序
要求每个功能使用函数完成
//完成学生管理系统
//1> 使用菜单完成
//2> 有学生的信息录入功能:输入学生个数,并将学生的姓名、分数录入
//3> 查看学生信息:输出所有学生姓名以及对应的分数
//4> 求出学习最好的学生信息:求最大值
//5> 按姓名将所有学生进行升序排序
//6> 按成绩将所有学生进行升序排序
//要求每个功能使用函数完成
#include<stdio.h>
#include<string.h>
int arr[100]={0};//存储学生成绩
char brr[100][20]={""};//存储学生姓名
int n=0;//学生人数
//菜单显示
void print_menu()
{
printf("学生管理系统\n");
printf("1.录入\n");
printf("2.查看所有学生成绩\n");
printf("3.查看最高分\n");
printf("4.按姓名升序\n");
printf("5.按成绩升序\n");
printf("0.退出\n");
}
//录入
void input()
{
printf ("请输入要录入的人数");
scanf("%d",&n);
printf("%d\n",n);
for (int i = 0; i<n; i++)
{
printf("请输入第%d个学生姓名:",i+1);
scanf("%s",brr[i]);
printf("请输入第%d个学生成绩:",i+1);
scanf("%d",&arr[i]);
}
printf("%d\n",n);
}
//显示所有学生成绩
void print_arr()
{
printf("学生成绩:");
for(int i=0; i<n; i++)
{
printf("%s\t",brr[i]);
printf("%d\n", arr[i]);
}
puts("");
}
//查找最大值并显示
void max()
{
int max;
int maxi;
for (int i = 0; i < n; i++)
{
if (arr[i]>max)
{
max=arr[i];
maxi=i;
}
}
printf("%s\t%d\n",brr[maxi],arr[maxi]);
}
//按姓名字母升序
void name()
{
int x=0;//交换成绩用
char y[20]=" ";//交换姓名用
for (int i = 1; i < n; i++)
{
for (int j = 0; j < n-i; j++)
{
if (strcmp(brr[j],brr[j+1])>0)
{
x=arr[j];
arr[j]=arr[j+1];
arr[j+1]=x;
strcpy(y,brr[j]);
strcpy(brr[j],brr[j+1]);
strcpy(brr[j+1],y);
}
}
}
}
//按成绩升序
void chengji()
{
int x=0;//交换成绩用
char y[20]="";//交换姓名用
for (int i = 1; i < n; i++)
{
for (int j = 0; j < n-i; j++)
{
if (arr[j]>arr[j+1])
{
x=arr[j];
arr[j]=arr[j+1];
arr[j+1]=x;
strcpy(y,brr[j]);
strcpy(brr[j],brr[j+1]);
strcpy(brr[j+1],y);
}
}
}
}
//主函数
int main()
{
char stu[][20]={""};
while(1)
{
int m;
print_menu();
scanf("%d",&m);
switch (m)
{
case 1:
input();
break;
case 2:
print_arr();
break;
case 3:
max();
break;
case 4:
name();
print_arr();
break;
case 5:
chengji();
print_arr();
break;
case 0:
return 0;
}
}
}