C语言笔记(二)

复习

1、随机数

int rand(void);
生成一个 >= 0 的整型数据
int a = rand() % 51; //a的取值范围为0~50
头文件:stdlib.h
生成的随机数是伪随机数

void srand(unsigned int seed);
seed:随机数种子	
      time(NULL) --- 将随机数种子随着系统时间改变
   	  #inlclude <time.h>
播下一个随机数种子
头文件:stdlib.h

2、循环语句

while
while(表达式)
{
    代码块;
}
step:
	先判断表达式是否为真(非0为真,0为假), 如果为真则进入循环体执行一次代码块,执行完后再次判断表达式;
        							   如果为假,则直接跳过该循环体。

do...while
do
{
    代码块;
}while(表达式);
step:
	先执行代码块,再判断表达式是否问真...

for
for(表达式1; 表达式2; 表达式3)
{
    代码块;
}
表达式1: 循环控制变量的初始化
表达式2: 循环退出的条件
表达式3: 循环控制变量的自增或自减
step:
    先执行表达式1,再判断表达式2是否为真,如果为真则进入循环体,再执行表达式3...
    								如果为假,则直接跳过循环
    
goto
    goto 一般和 if 连用

break
    退出该层循环
continue
    结束本次循环,并判断下一次是否进入循环

数组

  • 变量定义很多,数据多
  • 定义多个变量,这些变量存储在内存空间中是随机的
  • 班级成绩

1、含义

  • 存储大量同类型数据的有序(内存上连续)集合

2、一般形式

<存储类型> <数据类型> 数组名[元素个数];
存储类型: auto register extern static
数据类型: char short int long float double 
数组名:
	标识符 				 //满足命名规则
    数组名代表整个数组空间 	//sizeof(数组名) 计算整个数组空间的大小
    数组名代表数组首元素地址    //数组名是一个地址常量
元素个数:
    代表该数组最大能存储的元素个数
[]: 偏移并引用

定义一个数组:
    char a[5];		//定义了一个char型数组,该数组最多能存储5个char型元素
	int b[5];
数组元素的访问:
    数组名[下标];
	下标从0开始,最大为数组元素个数-1
  	对于数组元素的访问,一般用循环
eg:
#include <stdio.h>
int main(int argc, char *argv[])
{ 
    int a[5];
    /*
    a[0] = 1;
    a[1] = 2;
    a[2] = 3;

    printf("a[0] = %d\n", a[0]);
    printf("a[1] = %d\n", a[1]);
    printf("a[2] = %d\n", a[2]);
    */
    int n = 0;
    for(int i = 0; i < 5; i++)
    {
        a[i] = n;
        n++;
        printf("%d ", a[i]);
    }
    puts(" "); 
    printf("ip(a) = %p\n", a); 				//数组名是地址常量,地址常量不能赋值
    printf("ip(a[0]) = %p\n", &a[0]); 		//数组首元素地址
    printf("sizeof(a) = %ld\n", sizeof(a));  //结果为20,数组名代表整个数组空间的大小
    return 0;
} 

3、数组的初始化

1、完全初始化
    int a[5] = {1,2,3,4,5};
    char str[5] = {'h','e','l','l','o'};
                = {"hello"};
                = "hello";
    eg:
    char buf1[5] = "hello";
    char buf2[5] = "world";
    printf("%s\n", buf1);		//打印结果为helloworld

    char buf1[6] = "hello";		//字符串后有'\0', 字符数组保存字符串时,有多余的空间保存'\0'
    char buf2[5] = "world";
    printf("%s\n", buf1);
    printf("ip(buf1) = %p\n", buf1);
    printf("ip(buf2) = %p\n", buf2);
2、非完全初始化
    int a[5] = {1}; //给第一个元素初始化为1,其余未初始化的元素默认值为0
    int b[5] = {0}; //数组每一个元素的值都为0
3、缺省初始化
    int a[] = {1,2,3,4};	//表示数组最大元素个数为4

eg1:
int a[5] = {0};
for(int i = 0; ; i++)
{
    printf("%d ", a[i]);
}
//数组越界访问,可以读取未开辟空间的值,但是,访问到一定程度之后,就不允许被访问了(报段错误)

eg2:
int a[5] = {0};
for(int i = 0; i < 10; i++)
{
    a[i] = i;
    printf("%d ", a[i]);
}
//报段错误,不能修改未开辟空间中的数据

易错点:
int a[5] = {0};
int b[5];
b = a;		//错误,不能通过一个已定义数组赋值给新的数组,数组名是地址常量

a[5] = {1,2,3}; //error a[5]在定义之后单独使用,代表某一个元素

int i;
int a[i];		//变量不能作为数组初始化的元素个数

练习:从键盘上输入十个分数(是个评委), 去掉最高分、最低分,输出分数的平均值。
#include <stdio.h>
int main(int argc, char *argv[])
{ 
    int a[10] = {0};
    for(int i = 0; i < 10; i++)
    {
        scanf("%d", &a[i]);
    }
    int max = a[0];
    int min = a[0];
    int sum = 0;
    for(int i = 0; i < 10; i++)
    {
        sum += a[i];
        if(max < a[i])
            max = a[i];
        if(min > a[i])
            min = a[i];
    }
    printf("max = %d min = %d ave = %d\n", max,min,(sum - max - min)/8);
    return 0;
}

冒泡排序

从键盘输入一组数据,保存在数组中,使用冒泡排序对该数组中的元素排序(从小到大)
eg:
#include <stdio.h>
int main(int argc, char *argv[])
{ 
    int a[5] = {0};
    for(int i = 0; i < 5; i++)
    {
        scanf("%d", &a[i]);
    }
    for(int i = 0; i < 4; i++)
    {
        for(int j = 0; j < 4 - i; j++)
        {
            if(a[j] > a[j + 1])
            {
                int temp = a[j];
                a[j] = a[j + 1];
                a[j + 1] = temp;
            }
        }
    }
    for(int i = 0; i < 5; i++)
    {
        printf("%d ", a[i]);
    }
    puts(" ");
    return 0;
} 

字符串操作函数

1、strlen

函数原型
	size_t strlen(const char *s);
功能:
    计算s所指向的字符串的长度
参数:
    const char *s;
	待计算的字符串的地址
返回值:
    返回该字符串的有效长度,不包括'\0';
头文件:
    #include <string.h>

eg:
char str[10] = "hello";
printf("sizeof(str) = %ld\n", sizeof(str));		// 10 sizeof计算整个数组空间的大小
printf("strlen(str) = %ld\n", strlen(str));		// 5  strlen计算有效字符的个数

注意:strlen函数,遇见'\0'就会结束
    
练习:输入一个字符串,将其逆序输出

2、strcpy

函数原型
	char *strcpy(char *dest, const char *src);
功能:
    将src所指向的字符串(包括'\0'),拷贝到缓冲区dest中
参数:
    char *dest : 缓冲区
	const char *src : 待拷贝的字符串地址
返回值:
    返回dest缓冲区的地址
头文件:
    #include <string.h>
        
eg:
char dest[20] = {0};
strcpy(dest, "hello");
puts(dest);

3、strcat

函数原型
    char *strcat(char *dest, const char *src);
	char *strncat(char *dest, const char *src, size_t n);
功能:
    把src所指向字符串连接在dest缓冲区中的字符串后面,src要覆盖掉dest缓冲区中的'\0',并在新的字符串后面加上'\0'
参数:
    char *dest : 缓冲区
	const char *src : 待连接的字符串地址
返回值:
    返回dest缓冲区的地址
头文件:
    #include <string.h>
eg:
char dest[20] = "hello";
char src[20] = "world";
strcat(dest, src);
puts(dest);

4、strcmp

函数原型
    int strcmp(const char *s1, const char *s2);
    int strncmp(const char *s1, const char *s2, size_t n);
功能:
    比较s1与s2两个字符串的大小,从左至右依次判断
参数:
    const char *s1: 字符串首地址
	const char *s2: 字符串首地址
返回值:
    > 0 : s1 > s2
    < 0 : s1 < s2
    = 0 : s1 = s2
头文件:
    #include <string.h>
eg:
int cmp = strcmp("abc", "abb");
if(cmp > 0)
    printf("abc > abb\n");
else if(cmp < 0)
    printf("abc < abb\n");
else
    printf("abc = abb\n");

Day7

复习

数组

1、存储大量同类型数据,并且数据在内存空间中是连续存储的
2、数组的定义
    <存储类型> <数据类型> 数组名[元素个数];
存储类型:默认为auto
数据类型: char short int long float double 
数组名:
    标识符 //满足命令规则
    代表整个数组空间 //sizeof(数组名) 求整个数组空间的大小 = 元素个数 * sizeof(数据类型)
    代表数组首元素的地址	//数组名是一个地址常量
元素个数:
	决定数组最大能存放的元素个数
[]: 偏移并引用
3、数组的使用
   数组名[下标];
下标:从0开始,最大为数组元素-1
   int a[4];
   a[0] = {1};
一般使用循环语句便利数组
4、数组的初始化
   完全初始化:
   int a[3] = {1,2,3};
   非完全初始化:
   int b[4] = {1};	//未被初始化的元素值为0
   int c[4] = {0};	//将该数组元素全部赋值为0
   缺省初始化:
   int d[] = {1,2,3,4};

冒泡排序

字符串数组

char str[10] = {"hello"};
			= "hello";
			= {'h','e','l','l','o'};
字符串末尾有'\0'

字符串操作函数

1、strlen
函数原型:
	size_t strlen(const char *s);
函数功能:
	计算字符串的有效长度,不包括'\0'
返回值:
	字符串的有效长度
参数:
	字符串首地址
头文件:
	#inlcude <string.h>
2、strcpy
函数原型:
	 char *strcpy(char *dest, const char *src);
     char *strncpy(char *dest, const char *src, size_t n);
函数功能:
	把字符串src复制到缓冲区dest中,包括'\0';
返回值:
	dest缓冲区的首地址
参数:
	字符串src首地址
     dest缓冲区首地址
头文件:
	#inlcude <string.h>
3、strcmp
函数原型:
    int strcmp(const char *s1, const char *s2);	
    int strncmp(const char *s1, const char *s2, size_t n);
函数功能:
	从左至右依次比较s1和s2的元素
返回值:
	> 0 : s1 > s2
    < 0 : s1 < s2
    = 0 : s1 = s2
参数:
	字符串s1 s2首地址
头文件:
	#inlcude <string.h>
4、strcat
函数原型:
    char *strcat(char *dest, const char *src);
    char *strncat(char *dest, const char *src, size_t n);
函数功能:
	将src字符串拼接在dest缓冲区后,要覆盖dest末尾的'\0'
返回值:
	dest缓冲区首地址
参数:
	字符串dest src首地址
头文件:
	#inlcude <string.h>

多维数组 – 二维数组

多个一维数组
1、二维数组的定义
   <存储类型> <数据类型> 数组名[][];
存储类型:默认为auto
数据类型:char short int long float double
数组名:
	标识符
     二维数组首行地址
     代表二维数组整个数组空间 // sizeof(二维数组名)
行数: 
列数:
二维数组元素个数:* 列
整个二位数组空间大小:** sizeof(二维数组数据类型)

eg:
int arr[2][3];

2、二维数组的存储方式
    在内存中线性存储,抽象化出行列
3、二维数组的访问
    数组名[行下标][列下标];
	    行下标和列下标都是从0开始,最大为行数-1 列数-1	
        int a[2][3];
        a[0][1] = 1;
	使用嵌套循环对二维数组进行遍历
eg:
int main()
{
    int a[2][3];
    srand(time(NULL));
    //循环遍历赋值
    for(int i = 0; i < 2; i++)
    {
        for(int j = 0; j < 3; j++)
        {
            a[i][j] = rand() % 51; //生成0~50的随机整数
        }
    }
    //循环遍历打印
    for(int i = 0; i < 2; i++)
    {
        for(int j = 0; j < 3; j++)
        {
            printf("%d  ", a[i][j]);
        }
        puts(" ");
    } 
    return 0;
}

4、二维数组的初始化
   完全初始化
   int a[2][3] = {1,2,3,4,5,6};
   int a[2][3] = {{1,2,3}, {4,5,6}};
   非完全初始化
   int a[2][3] = {1,2,3};	//未初始化的元素默认为0
   int a[2][3] = {{1,2}, {4,5}};
   缺省初始化
   int a[][] = {1,2,3,4,5,6,7,8}; //error
   int a[2][] = {1,2,3,4,5,6,7,8}; //error
   int a[][3] = {1,2,3,4,5,6,7,8}; //right 3*3的二维数组
练习:实现一个二维数组的转置
     找出一个34列二维数组中的最大的元素,并打印该元素的行和列
     打印杨辉三角形的前10

指针

1、什么是指针

  • 指针就是地址的别名
  • 什么是地址
    • 内存由多个内存单元构成,每个内存单元由一个或者多个字节组成,每一个字节都有一个编号,这个编号就是地址
  • 指针变量,用来保存一个地址常量
  • 指针、地址、指针变量,为了方便理解,把指针、地址、指针变量都叫做指针

2、指针变量的定义

<存储类型> <数据类型> *指针变量名; 
存储类型
数据类型: char int ....
* : 表示该变量是一个指针变量
指针变量名: 标识符
eg:
int *p; //定义一个指针变量p

指针变量的赋值:
eg1:
int a = 10;
int *p;
p = &a;		//将变量a的地址值赋值给指针变量p

eg2:
int arr[5] = {1,2,3,4,5};
int *q;
q = arr;

指针的初始化:
int a = 10;
int *p = &a; //指针的初始化
int *q = NULL;
NULL //代表零地址空间,不可读也不可写,NULL是零地址空间的宏定义

3、指针变量的大小

指针变量占一定的空间大小
    int *q;
	sizeof(q);	//8
	char *p;
	sizeof(p);  //832位机中,指针变量的大小为4字节
在64位机中,指针变量的大小为8字节

4、直接访问与间接访问

  • 直接访问:通过变量的地址直接访问该变量
  • 间接访问:通过保存该变量地址的变量(指针变量)去访问该变量

4、&与*

* :在定义变量时,代表定义的是一个指针变量
   表示乘法符号
   在对一个指针变量使用时,表示取该指针所指向的地址空间的内容(取内容)
   *p :取p指针所指向空间的内容
&:取地址符号
  获取变量的地址
eg:
int a = 10;
int *p = &a;
printf("a = %d\n", a);
printf("a = %d\n", *p);		//*p取p指针所指向地址空间的内容,现目前p所指向的空间为变量a的地址空间,所有可以打印变量a的值

int arr[4] = {1,2,3,4};
int *q = arr;
printf("arr[0] = %d\n", arr[0]);
printf("arr[0] = %d\n", *q);

5、指针的运算

指针的算术运算
    指针的偏移是以数据类型为单位进行偏移
    指针的数据类型由该指针所指向空间的数据类型决定
    int a = 10;
	int *p = &a;
	p + 1;	//以int数据类型的大小为单位移动  -- 四个字节
	p + n: 指针向地址高的方向移动n个数据
           数据: 不同的数据类型,指针移动的字节数不一样
    p + 1: 指针向地址高的方向移动 1 个数据
    p - 1: 指针向地址低的方向移动 1 个数据
    
p + 1 与 p++++p 的区别
p + 1 : 如果没有重新对指针赋值,则指针的地址值不会改变(指针的指向)
p++   : p = p+1  //对指针变量重新赋值

++p 和 p++ 的区别
如果单独使用,是对指针本身进行自增
    p++++p;

int a[4] = {1,2,3,4};
int *p = a;

printf("ip(p) = %p\n", p);     
printf("ip(++p) = %p\n", ++p); //打印的地址值偏移4字节
printf("ip(p) = %p\n", p);

printf("ip(p) = %p\n", p);     
printf("ip(p++) = %p\n", p++); //打印的地址值未偏移
printf("ip(p) = %p\n", p);

*p++*(p++)
int a[4] = {1,3,5,7};
int *p = a;
//printf("*p++ = %d\n", *p++); 		//打印第一个元素的值 1
printf("*(p++) = %d\n", *(p++));	//打印第一个元素的值 1

*p++ *(p++) 本质上没有区别

使用指针实现字符串逆序输出

day8

复习

二维数组

1、二维数组的定义
    <存储类型> <数据类型> 二维数组名[][];
	存储类型: 默认auto
     数据类型: char int short....
    二维数组名:
		标识符
         代表整个二维数组空间 //sizeof(二维数组名)
         代表二维数组首行的地址
    二维数组最大存储元素个数:行 *int arr[2][3];
2、二维数组的使用
    数组名 [行下标][列下标];
	行下标和列下标都从0开始,最大为行数和列数-1
    int arr[2][3];
	arr[0][0] = 1; //将二维数组的第一个元素赋值为1
	一般用嵌套for循环遍历二维数组
    
    srand(time(NULL));
	//循环给二维数组每一个元素赋值
    for(int i = 0; i < 2; i++)
    {
        for(int j = 0; j < 3; j++)
        {
            arr[i][j] = rand() % 51;
        }
    }
 3、二维数组在内存中是连续存储的(线性)   
 4、二维数组初始化
     完全初始化
     int arr[2][3] = {1,2,3,4,5,6};
	 int arr[2][3] = {{1,2,3},{4,5,6}};
     非完全初始化
     int arr[2][3] = {1,2,3};
	 int arr[2][3] = {{1,2},{4,5,6}};
     缺省初始化
     int arr[][3] = {1,2,3,4,5}; //必须确定列数

指针

  • 什么是指针

    • 指针就是地址,地址的别名
  • 什么是地址

    • 内存是由多个内存单元组成的,内存单元是由一个或多个字节构成,每个字节都有一个编号,这个编号就叫做地址

    指针变量:用来保存地址值

1、指针变量的定义
   <存储类型> <数据类型> *指针变量名;
   *: 表示定义时,该变量是一个指针变量
   int a = 10;
   int *p = &a;
   int arr[3] = {0};
   int *q = arr;
   int *m;	//m是一个野指针
   数据类型: 指针的数据类型,根据指针所指向地址空间的数据类型定义
2、指针的初始化
   int arr[3] = {0};
   int *q = arr; 	//定义时就指明指针的指向
3、指针的大小
   sizeof(指针变量名) --> 8字节
   64位机中,指针的大小为 8 字节
   32位机中,指针的大小位 4 字节
4&*
   &: 取地址
   *: 取内容,取该指针所指向地址空间的内容
      乘法符号
5、指针的运算
   p + 1 : 地址向高位增加1个数据(以该数据的数据类型大小为单位+1)
   p + N : 地址向高位增加N个数据(以该数据的数据类型大小为单位+N)
   p - 1 : 地址向高位减少1个数据(以该数据的数据类型大小为单位-1)
   p - N : 地址向高位减少N个数据(以该数据的数据类型大小为单位-N)
       
   p++++p
   单独使用: 该指针p偏移一个数据类型的大小,指针指向改变
   复杂运算:++ 在一句代码结束后,再改变指针的指向
   
   *p++ *(p++)
   先取该指针所指向地址空间的内容,再进行指针的偏移
   *++p *(++p)
   p先偏移,再取该指针所指向地址空间的内容

1、空指针

char *p = NULL; //空指针
NULL是一个宏定义,代表零地址空间,零地址空间,不可读不可写
为了防止指针成为野指针

2、void指针

void指针也叫做万能指针
int a = 10;
void *p = &a;
void指针可以用来保存任何数据类型的地址
void指针在使用时,要强转为相应的数据类型
int a = 10;
void *p = &a;
printf("%d\n", *(int *)p);

3、指针指向字符串

char *p = "hello";//p指向的是一个字符串常量的首地址
*p = 'a'; //error不能改变常量区的内容

char str[] = "hello";
char *p = str;
*p = 'a';
可以通过指针修改字符串数组中的内容

4、const修饰指针

int a = 10;
const int *p = &a;
const修饰*p:
	该指针指向地址空间的内容不能被修改,但是可以改变指针的指向

int a = 10;
int * const p = &a;
const修饰p:
	该指针的指向不能修改,但是可以修改指针所指向地址空间中的内容
        
int a = 10;
const int * const p = &a;

练习:

  • 用一级指针遍历二维数组,并打印

  • 用指针实现字符串的压缩

    • AAAbbbcccderr —> Abcder
  • 输入一个"12345",转换成整型数据12345输出

  • 用一级指针实现二维数组的冒泡排序

Day 9

1、多级指针

  • 指向一个指针变量的地址的指针,叫多级指针

2、二级指针

  • 指向一个一级指针地址
1、二级指针的定义
    <存储类型> <数据类型> ** 指针变量名;
	int **pp;	//pp是一个二级指针
eg:
	int a = 10;
    int *p = &a;
    int **pp = &p;

    printf("%ld\n",sizeof(pp));
    printf("%ld\n",sizeof(int **));

    printf("&a = %p\n", &a);
    printf("p = %p\n", p);

    printf("*pp = %p\n", *pp);
    printf("**pp = %d\n", **pp);
    printf("pp = %p\n", pp);
    printf("pp + 1 = %p\n", pp + 1);

3、数组指针

​ 是一个指针,指向数组一行的指针,也可以叫行指针

1、数组指针的定义
    <存储类型> <数据类型> (*指针变量名)[一行元素个数];
int a[5] = {1,2,3,4};
int *p = a;
int (*q)[4] = &a;
for(int i = 0; i < 4; i++)
{
    printf("%d ", *(*q + i));
}
puts(" ");
printf("*q = %p\n", *q);
printf("*q + 1 = %p\n", *q + 1);
printf("*(*q) = %d\n", *(*q));
printf("a = %p\n", a);
printf("a + 1 = %p\n", a + 1);
printf("&a = %p\n", &a);
printf("&a + 1 = %p\n", &a + 1);

2、数组指针指向二维数组
int a[2][3] = {1,2,3,4,5,6};
int (*p)[3] = a;
for(int i = 0; i < 2; i++)
{
    for(int j = 0; j < 3; j++)
    {
        printf("%d ", *(*(p + i) + j));
    }
    puts(" ");
}

3、二维数组元素、地址表示
int a[2][3] = {1,2,3,4,5,6};
int (*p)[3] = a;
printf("a[0][0] = %d\n", a[0][0]);
printf("p[0][0] = %d\n", p[0][0]);
printf("*(*(p + 0) + 0) = %d\n", *(*(p + 0) + 0));
printf("*(*(a + 0) + 0) = %d\n", *(*(a + 0) + 0));

printf("a[1][1] = %d\n", a[1][1]);
printf("p[1][1] = %d\n", p[1][1]);
printf("*(*(p + 1) + 1) = %d\n", *(*(p + 1) + 1));
printf("*(*(a + 1) + 1) = %d\n", *(*(a + 1) + 1));
printf("*(p[1] + 1) = %d\n", *(p[1] + 1));
printf("*(p[1] + 1) = %d\n", (*(p + 1))[1]);

*(*(p + 1) + 1) <==> a[1][1] <==> p[1][1] <==> *(*(a + 1) + 1)
*(p[1] + 1) <==> *(a[1] + 1) <==> (*(p + 1))[1] <==> (*(a + 1))[1]
 

4、指针数组

本质就是一个数组,存放大量相同类型的指针变量
1、指针数组的定义
    <存储类型> <数据类型> *变量名[元素个数];
int *pArr[3];
2、指针数组元素访问
    指针数组名[下标];
int a = 10;
int b = 20;
int c = 30;
char d = 's';
//定义一个指针数组,分别保存变量a b c的地址
int *pArr[3] = {&a, &b, &c};
3、指针数组的使用
int *parr[3] = {NULL};
char *pArr[3] = {"hello","world","!"};
int n = 0;
while(n < 3)
{
    puts(pArr[n]);
    printf("%p\n",pArr[n]);
    n++;
}
printf("%c\n", *(pArr[0] + 1));

*pArr[0] = 'l';
printf("%c\n", *pArr[0]);
//用二级指针保存指针数组的
char **p = pArr;

练习:

利用指向行的指针变量求5×3数组各行元素之和。

编写一个程序,输入星期,输出该星期的英文名。用指针数组处理

Monday Tuesday Wednesday Thursday Friday Saturday Sunday

Day10

1、main函数参数

#include <stdio.h>
int main(int argc, char *argv[])
{ 
    //argc 和 argv都是命令行参数
    //argc 表示命令行参数的个数
    //argv 是一个指针数组,用来保存命令参数的地址
    printf("argc = %d\n",argc);
    for(int i = 0; i < argc; i++)
    {
        puts(argv[i]);
    }
    return 0;
} 

2、函数

  • 实现某个特定功能的代码模块
  • 使得代码简洁,清晰
1、函数的定义
<返回类型> 函数名(形参列表)
{
	函数体;
    return 返回值;
}

返回类型: 
		一般数据类型: char short int float double long
         指针类型: char *, short *, int *, float *....
         空类型: void 代表这个函数没有返回值
         void func()
         {
			return;             
         }
		函数的返回类型,必须和函数返回值的类型相同
函数名:
		标识符
         函数的入口地址
形参列表:
		可以没有,也可以定义不同数据类型的参数(不能初始化), 多个参数用 , 隔开
函数体:
		实现功能的代码块;
return:
		return 代表一个函数的结束
返回值: 
		函数调用的时候,返回值的数据类型要与函数 <返回类型> 相同
            
函数三要素:函数的返回的类型、形参列表、函数的返回值

[1] 定义一个函数,实现打印n行hello world
  	void my_print(int n)
    {
		for(int i = 0; i < n; i++)
            printf("hello world\n");
    }
[2] 判断两个整型数据中最大的值,并返回最大数值
    int max(int a, int b)
	{
    	if(a > b)
            return a;
    	else
            return b;
	}
[3] 封装一个函数,求n的阶乘
int mul(int n)
{
    int sum = 1;
  	if(n == 0 || n == 1)
        return 1;
    if(n > 1)
    {
         while(n)
         {
             sum *= n;
         	 n--;
         }
    }
    return sum;
}
2、函数的声明
   告知编译器在别处定义的函数要在后续程序使用
   <返回类型> 函数名(形参列表);
   形参列表也可以只写参数的数据类型
   函数的声明放在函数调用之前都可以,一般放在头文件和主函数的中间,也可以放在头文件中
3、函数的调用
   函数名(实参列表);  
4、函数参数传递
   值传递
   将实参的值拷贝一份给形参,形参的改变不会影响实参的值
   地址传递
   将实参的地址传递给形参,所以可以通过该地址改变实参的值
   
练习:封装一个函数,打印一维数组
//函数声明
void print_arr(int len, int *s);
int main(int argc, char *argv[])
{ 
    int a[5] = {1,2,3,4,5};
    //函数调用
    //print_arr(5, a);
    print_arr(sizeof(a)/sizeof(a[0]), a);
    //sizeof(a)/sizeof(int)  计算数组大小
    return 0;
} 
//定义一个函数,打印一维数组元素,参数传入数组大小 len 数组首地址 s
//void print_arr(int len, int s[])
void print_arr(int len, int *s)
{
    for(int i = 0; i < len; i++)
        printf("%d ", s[i]);
    puts(" ");
}

作业:封装函数,实现strcmp功能

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式石油工程师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值