- 二维字符数组
格式:char 数组名[常量表达式1][常量表达式2]
char str[3][5]
常量表达式1:第一维,可有可无,表示行,表示字符串的个数。
常量表达式2:第二维,必须存在,表示列,表示每个字符串所占的字节大小。
char a;//存储一个字符
char b[10];//存储10个字符,一个字符串
char c[3][5];//存储3个字符串,每个字符串5字节
二维字符数组的定义与初始化
字符串初始化:
*{}不可省略
char a[3][5]={“abcd”,“1234”,“+-*/”};//字符串的全部初始化
char a[3][5]={“abcd”,“1234”};//字符串的部分初始化,剩余元素使用\0填充
char a[][5]={“abcd”,“1234”,“+-*/”};//省略第一维度,默认是实际的行数
单字符的初始化
char str[2][3]={{'a','b','c'},{'1','2','3'}};//单字符的全部初始化
练习
输入五个学生的名字,计算其最大值
函数
函数的分类
库函数:系统自带的函数(scanf/printf/strlen)
自定义函数:程序员手动封装的函数
- 有无参函数
有无参:由参数列表决定,如果参数列表存在,则称为有参函数,否则称为无参函数
- 有无返函数
有无返:由数据类型决定,如果参数类型为void,则称为无返函数,否则称为有返函数
void sum() 无参无返函数
void sum(int a) 有参无返函数
int sum(void) 无参有返函数
int sum(int a) 有参有返函数
无参无返函数
格式:
存储类型 void 函数名(void) //函数头
{
函数体;
}
调用格式:
函数名();
getchar();
存储类型:函数省略存储类型默认是extern
数据类型:基类型,构造类型,空类型void,指针
函数名:满足命名规范(常用下划线/驼峰命名)
():函数的标志,不允许省略
{}:不允许省略
参数列表:可有可无,当存在多个时,需要用逗号隔开
- 自定义函数在主函数上面
- 自定义函数在主函数下面
注意:自定义函数在主函数下面定义时,需要声明函数
建议自定义函数在主函数下面定义,执行速度会相对较快,可读性强
练习
定义四个无参无返函数,实现加减乘除
全局变量和局部变量
- 全局变量
全局变量:定义在函数外的变量
内存:全局变量在静态区
作用域:从定义开始,到本文件结束
- 局部变量
局部变量:定义在函数内的变量,参数列表
内存:在栈区
作用域:从定义开始,到本函数有效
全局变量和局部变量重名
当全局变量和局部变量重名时,优先选用局部变量,就近原则
局部变量和局部变量重名
当局部变量和局部变量重名时,采用就近原则
有参函数
为什么有参函数?被调函数需要使用主调函数的局部变量,解决方式:传参
格式:
存储类型 数据类型 函数名(参数列表) //函数头
{
函数体;
}
使用格式:
函数名(变量名1,变量名2,...);
实参和形参的类型:
实参:常量,变量,表达式
形参:变量
规则:
- 个数一致
- 一 一对应
- 类型建议一致;如果不一致以形参为主,发生类型转换
- 变量名可以不一致
- 实参只写变量名,形参需要写数据类型
练习
在主函数中输入一个表达式,定义4个有参无返函数实现加减乘除
数组做参数:一般只传递数组变量名,表示把整个数组传递过去
形参的数组长度可以省略不写,默认是实际参数的实际元素个数
如果写形参的数组长度,则需要大于等于实际参数的实际元素个数
数组做形参,看似是数组,实则是指针
在主函数中定义一维数组初始化 11 22 33 44 55
在自定义函数中实现数组输出
在主函数中定义3列二维数组初始化 1 2 3 4 5
在自定义函数中实现数组循环输出
二维数组做参数,第一维可以省略不写,但第二维不可以省略
在主函数中定义字符数组并初始化“hello world”
在自定义函数中实现字符串输出
在主函数中,输入两个字符串,自定义函数实现字符串的连接(非函数)
void my_strcat(char dest[],char src[])
有返函数
为什么有返?主调函数需要使用被调函数的局部变量,解决方式返回
格式:
存储类型 数据类型 函数名(参数列表) //函数头
{
函数体;
return 表达式;
}
调用格式://谁调用的函数就返回给谁
- 变量=函数名(变量名1,变量名2,...);
- 直接使用函数名(变量名1,变量名2,...);
数据类型:如果数据类型是空类型void,则默认是无返函数,不是void为有返函数。可以省略,默认是int
return:返回,结束函数
表达式:可以是变量,常量,表达式
一个函数可以有无数个return但只有第一个有效。
一个return只能返回一个值
数据类型建议和return的值的类型保持一致,如果不一致以数据类型为主,发生类型转换
练习:
在主函数中定义数组初始化1 2 3 4 5,定义一个有参有返函数,计算数组的和
在主函数中定义一个字符串,并输入,在自定义函数中计算字符串的长度(非函数实现)
递归
递归:函数的自身调用,把大问题分解为多个独立的子问题解决的办法,递归的本质是循环
直接递归:一个函数的自身调用
间接递归:多个函数之间相互调用
循环的执行速度远大于递归,递归解决问题规模较大的情况,循环解决问题规模较小的情况
递归组成:
递归出口/递归边界:结束条件
递归前进段/递归公式:
练习
在主函数定义两个字符串并输入,在自定义函数中实现字符串的比较(非函数)
gets(str);
gets(arr);
my_strcmp(str,arr);
return 0;
}
int my_strcmp(char str[],char arr[]) //传参
{
int i=0;
while(str[i]==arr[i])
{
if(0==str[i])
break;
i++;
}
int sub=str[i]-arr[i];
if(sub>0)
puts("str>arr");
else if(sub<0)
puts("str<arr");
else if(sub==0)
puts("str=arr");
}
在主函数定义一个字符串,在自定义函数中实现冒泡排序
void Bubble(char str[])
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
void Bubble(char str[]);//声明函数
int main(int argc, const char *argv[])
{
char str[128]="";
gets(str);
Bubble(str);
puts(str);
return 0;
}
void Bubble(char str[]) //传参
{
int i,j,len;
char t;
for(len=0;str[len];len++);
for(i=1;i<len;i++)
{
for(j=0;j<len-i;j++)
{
if (str[j]>str[j+1])
{
t=str[j];
str[j]=str[j+1];
str[j+1]=t;
}
}
}
}
在主函数定义两个字符串,在自定义函数中实现字符拷贝
void my_strcpy(char dest[],charsrc[])
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
void my_strcpy(char str[],char arr[]);//声明函数
int main(int argc, const char *argv[])
{
char str[128]="";
char arr[128]="";
gets(str);
gets(arr);
my_strcpy(str,arr);
return 0;
}
void my_strcpy(char str[],char arr[]) //传参
{
int i;
for(i=0;arr[i]!=0;i++)
{
str[i]=arr[i];
}
str[i]=0;
puts(str);
}