2020第二次软件培训——函数、数组、字符串

函数

引例

第一个函数

#include<stdio.h>

void print_c(); //函数声明

void print_c() //函数定义
{
	printf(" ###### \n");
	printf("##    ##\n");
	printf("##      \n");
	printf("##      \n");
	printf("##      \n");
	printf("##    ##\n");
	printf(" ###### \n");
	printf("\n");
}

 int main()
 {
 	print_c(); //函数调用
 	print_c();
 	print_c();
 	
 	return 0;
 }

什么是函数

c语言标准库本身提供了一些基本的函数,称为系统函数,如scanf函数、printf函数、sqrt函数、pow函数等等,除了系统函数外,我们还可以自己定义函数。

函数的作用

①main函数变得冗杂

②程序复杂度不断提高

③代码前后关联度高,改一处就牵一发而动全身

④变量的命名成了问题 简单的名字都用完了

⑤为了在程序中多次实现某功能,不得不多次写重复的代码

函数定义的一般格式

<函数返回值类型>函数名(类型名 形式参数1,类型名 形式参数2)
{

	// 函数体

}

返回类型

函数的返回类型

函数的返回类型就是当系统执行过你的程序之后,应该交还给你什么

返回类型的种类

C语言的返回类型就是int , double , float 等等基本类型

比如经过各种计算,你的函数最后得到一个int整形,

那么在定义函数的时候就规定这是一个int型函数

返回类型的声明

返回类型的声明在两个地方体现:

第一就是函数头,需要告诉系统这是一个什么类型的函数——就像定义一个变量(int a = 0),定义函数的时候同样需要指定类型

第二是在函数结束后,你需要确确实实的返回给他一个你声明的该类型的值,也就是return。

动手写一个函数

输入两个整数,返回它们中较大的一个数

#include <stdio.h>

int max(int a, int b);

int max(int a, int b)
{
 	if(a > b)
 		return a; //函数遇到return语句会立刻返回
 	else
 		return b;
}

int main()
{
	int a, b, c;
	scanf("%d%d", &a, &b);
	c = max(a, b);
	printf("%d", c);
	return 0;
}

不需要返回值的情况-void

若定义函数时指定函数为void,则函数不需要返回任何内容,可以不写return,或者写return(后面不接任何值)

动手写一个函数

输出***

​ ***

​ ***

​ (三行三列)

#include <stdio.h>

int print_();

int print_()
{
	printf("###");
	printf("\n");
}

int main()
{
	print_();
	print_();
	print_();
	
	return 0;
}

函数的参数

不论是否需要参数,在函数的定义是都应该在名字后面加上括号。

参数的定义与主函数中变量定义一样。

参数与主函数中传入的变量并没有直接的关系

令人困扰的问题:形式参数与实际参数

我们先来看一段代码

#include <stdio.h>

void change(int a, int b);

int main() {
	int a = 0, b = 10;
	printf("a = %d, b = %d\n", a, b);
	change(a, b);
	printf("a = %d, b = %d\n", a, b);
	return 0;
}

void change(int a, int b) {
	int temp;
	temp = a;
	a  = b;
	b = temp;
}

试着运行一下上面的代码。看看它的运行结果与你预期的是否一致。

输出结果

a = 0, b = 10
a = 0, b = 10

上面的代码看似完成了交换a, b的值的功能,而程序的运行结果却是两次输出内容保持一致。下面我们就来讲一下这个问题。

我们从函数的值传递讲起。

首先,main函数在调用change函数时,将main函数中a,也就是0传递给了change中的变量a,又将main函数中b,也就是10传递给了change中的变量b。这时,main函数与change函数没有其它任何关联:main中的a只是它的值与change中的a相等,而change函数中的a发生任何改变都不会影响到main中的a变量。这就好比你在主函数中写的代码是

change(0, 10);

主函数只是将其变量的值传给了change函数,它们只是名字相同,而没有任何关系。这好比我有一张表格,然后我去打印店复印了一份给你,你即使把那个表格撕掉,都不会影响我的表格。(其中的就是main函数,就是change函数)
值传递
在以上前提下,change函数中的a变量和b变量再怎么交换都不会影响到main函数中的变量。

那我们该用什么方式去解决“使用函数去交换两个变量的值的问题”呢?
这就是涉及到指针的知识了。等你们对指针有一定的了解后,我们会讲解这方面的知识点的。

注意事项

函数的定义不可以在其他函数中进行。新的函数的定义应当在主函数的外面。

函数定义位置的选择有两个:

1.定义在调用这个函数的函数上面

2.在调用这个函数的下面定义,但要现在上面声明这个函数

注:若使用第二种,声明应包括函数的返回值类型,名称和参数列表

如何使用函数

函数经过定义就可以通过调用他的名字来使用他。

如果函数有参数,则使用时应当填满所有参数,如果函数不含参数,也不可以丢掉空括号

如果函数没有返回值,则直接作为一句话输入在程序中即可

如果函数有返回值,则应该利用一个变量继承这个返回值。

做点题吧

1)设计函数计算1 * 2 * … * 10+11 * … * 20+21 * … * 30的和。

#include <stdio.h>

long long ans(int begin)
{
	int i;
	long long ans;
	ans = 1;
	for (i = begin; i< begin + 10; i++)
	{
		ans = ans * i;
	}
	return ans;
}

int main ()
{
	long long sum;
	sum = ans(1) + ans(11) + ans(21);
    printf("%lld", sum);
}

编写程序,使用自定义函数计算下列分段函数𝑦 = 𝑓(𝑥)的值。
在这里插入图片描述

(保留三位小数)

#include<stdio.h>
#include<math.h>  

float f(float x) {
	if (x >= 0 && x <= 4) {
		return sqrt(64 * x);
	}
	if (x > 4 && x <= 8) {
		return pow(2, x);
	}
}
int main() {
	float x;
	scanf("%f", &x); 
	printf("%.3f", f(x));
	return 0;
}

已知体质指数
B M I = 体 重 ( k g ) 身 高 2 ( m 2 ) BMI=\frac{体重(kg)}{身高^2 (m^2)} BMI=2(m2)(kg)
大多数人的BMI在[18.5 , 24]

现输入一整型数据n 代表身高或体重

求对应的身高或体重范围

#include <stdio.h>
#include <math.h>

float weight_max(float a)
{
	return 24 * pow(a, 2);
}

float weight_min(float a)
{
	return 18.5 * pow(a, 2);
}

float height_max(float a)
{
	return sqrt(a / 18.5);
}

float height_min(float a)
{
	return sqrt(a / 24.0);
}

int main()
{
	float a;
	scanf("%f", &a);
	if (a >= 0.0 && a <= 3.0)
	{
		printf("体重范围为%.3f到%.3f", weight_min(a), weight_max(a));
	}
	else
	{
		printf("身高范围为%.3f到%.3f", height_min(a), height_max(a));
	}
	
	return 0;
}

数组

数组的定义

数组的概念:

简单来说,其实就是存储一批相同类型数据的地方。

数组的定义格式:

类型 数组名[常量表达式]

例如

int a[10];
char b[10];
float c[10];
double d[10];

###循环和数组密不可分

数组的定义是为了规范化、大批量的对数据进行操作,而循环又刚好是对数字进行批量操作的方式。在数组的输入输出等操作中,我们更多的是使用循环。

int a[10];
int i; 
for (i = 0; i < 10; i++)
{
	a[i] = i;
}

例子:存入十个同学的分数(整形),并且计算平均分,最高分和最低分。

数组初始化

int a[3] = {0};//将所有元素初始化为0
int a[3] = {1, 2, 3};//对每个元素分别赋值
int a[] = {1, 2, 3};//偷懒的写法,让编译器自己计算数组的大小

数组不能被动态定义

//以下代码为错误示范
int n, i;
printf("请输入数组的大小:");
scanf("%d", &n);
int a[n];

(ps:以上代码如果按照C99标准并不会报错)

数组的访问

数组名[下标]

例如:

a[0]//访问a数组的第1个元素

b[1]//访问b数组的第2个元素

c[2]//访问c数组的第3个元素

访问数组不要越界

数组越界不报错是因为在C语言中这种行为是没有明确定义的,最后的运行结果取决于编译器自己。但是这样做会导致程序出现难以察觉的bug!

二维数组

二维数组的定义

定义二维数组的方法与一维数组类似。

类型 数组名[常量表达式] [常量表达式]

例如:

int a[4] [4]; // 4行4列

char b[2] [3]; // 2行3列

double c[6] [3]; // 6行3列
二维数组的访问

int a[6] [6];//定义一个6行6列的二维数组

a[5] [5];//访问最后一个元素

与一维数组一样,都需要注意越界的问题!!!

二维数组的初始化

二维数组本质上是以数组作为数组元素的数组,在内存中是线性存放的。

与我们直观理解的矩阵不太一样。

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

2.利用循环的嵌套输入输出

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

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

int a[3] [4] ={0};//元素全部初始化为0

int a[][4] = {1, 2, 3, 4};//二维数组的初始化偷懒的写法,相当于a[1] [4]

字符数组

可以先定义指定长度的字符数组,然后再给每个元素单独赋值:

char str[10];
str[0] = ‘x’;
str[1] = ‘y’;

或者直接在定义的时候对字符数组进行初始化

char str1[5] = {‘e’, ‘s’, ‘t’, ‘a’, ‘\0};//单独初始化元素
char str2[] = {‘e’, ‘s’, ‘t’, ‘a’, ‘\0};//不写数组大小
char str3[] = {“esta”};//使用字符串常量初始化字符数组
char str4[] = “esta”;//使用字符串常量初始化,可以省略大括号

字符串处理函数

注意:使用字符串处理函数时,要导入string.h

strlen

使用方法:strlen(str)

用于返回指定字符串的长度。

strcpy

使用方法strcpy(str1, str2)

strcpy 函数用于拷贝字符串,将str2拷贝到str1中,包含最后的结束符 ‘\0’。

注意:为了避免溢出,必须确保用于存放的数组长度足以容纳待拷贝的字符串(长度需要包含结束符 ‘\0’)。

strcat

使用方法:strcat(str1, str2)

将一个字符连接到目标字符串后边,在此过程将覆盖第一个参数的结束符 ‘\0’。

strcmp

使用方法:strcmp(str1, str2)

用于比较两个字符串。

从第一个字符开始,依次比较每个字符的 ASCII 码大小,直到发现两个字符不相等或结束时(‘\0’)为止

返回值意义
<0字符串1的字符小于字符串2对应位置的字符
=0两个字符串的内容完全一致
>0字符串1的字符大于字符串2对应位置的字符
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值