程序设计入门-C语言基础知识-翁恺-第五周:函数-详细笔记(五)
第五周:函数
5.1 函数
什么是函数?
- 函数是一块代码,接受零个或多个参数,做一件事情,并返回零个或一个值。
- 函数声明语法
返回值 函数名(参数列表){
函数体
} - 我们前面列子中经常使用的printf和scanf都是函数
调用函数
- 函数(参数值);
- ()小括号起到了表示函数调用的重要作用,及时没有参数也需要()
- 如果有参数,则需要给出正确的数量和顺序
- 这些值会被按照顺序依次来初始化函数中的参数
- 调用函数时给的参数叫做实际参数,在函数体内接受到的参数叫形式参数
- 函数知道每一次是哪里调用它,会返回到正确的地方
- 可以传递给函数的值是表达式的结果,这包括:
- 字面量
- 变量
- 函数的返回值
- 计算的结果
- 调用函数时给的值与参数的类型不匹配是C语言传统上最大的漏洞
- 编译器总是悄悄替你把类型转换好,但是这很可能不是你所期望的
- 后续的语言,C++/Java在这方面很严格
从函数中返回值
- return停止函数的执行,并返回一个值
- return;
- return 表达式;
- 一个函数中可以有多个return语句
- 不推荐给一个函数多个return不符合单一出口原则,多个return我们再做修改时需要去找所有的出口
没有返回值的函数
- void 函数名(参数表)
- 不能使用呆值的return,也可以没有return
- 调用的时候不能做返回值的赋值
- tips:如果是有返回值的函数,则必须使用带值的return
5-2 使用函数
- 把函数的原型声明写在main函数前是因为c的编译器自上而下顺序分析你的代码
- 函数可以先做原型声明,再定义;
- 函数的声明和定义必须一致
函数原型
- 函数头,以分号";"结束,就构成了函数原型
- 函数原型的目的是告诉编译器这个函数长什么样子
- 名称
- 参数(数量及类型)
- 返回类型
- 旧的标准习惯把函数原型写在调用它的函数里面,现在一般写在调用它函数的前面。
- 原型里可以不写参数的名字,但是一般仍然要写上,便于阅读。
参数的传递
- c语言的函数的参数的传递是对值的传递
- 每个函数有自己的变了空间,参数也位于这个独立的空间中,和其他函数没有关系
- 过去,对于函数参数表中的参数,叫做“形式参数”,调用函数时给的值,叫做“实际参数”
- 由于容易让初学者误会实际参数就是实际在函数中进行计算的参数,误会调用函数的时候把变量而不是值传进去了,所以我们不建议继续用这种种古老的方式称呼它们。
- 调用参数的时候,我们就叫把值传递进去了,而在函数内部我们就称为参数。
本地变量
- 函数的每次运行,就产生了衣蛾独立的变量空间,在这个空间中的变量,是函数这次运行所独有的,称为本地变量。
- 作用域:在(代码的)什么范围内可以访问这个变量(这个变量可以)起作用
- 对于本地变量,这两个问题的答案是统一的——大括号内(块)
本地变量的规则
- 本地变量时定义在块内的
- 块可以是函数的块内
- 也可以是语句的块内
- 甚至可以随便拉一大括号定义变量
- 程序运行进入这个快之前,这个变量不存在,离开这个快,这个变量也消失了
- 在块外定义的变量在块内仍然有效
- 在块里面定义了和外面同名的变量则掩盖了外面的
- 不能在同一块内定义同名的变量
- 本地变量不会被默认初始化
- 参数在进入函数的时候就被初始化了
没有参数时
- 在函数没有参数时一定要使用void填充参数,比如: void f(void);
- 因为如果不写void就等于告诉编译器,不确定需要什么参数,当调用函数时如果有参数,编译器会默认以为函数的参数的类型都是int ,而且在定义时如果参数不一致编译器也不会报错,因此当定义时变量为double而声明为int调用的结果就不是我们预期的了。
- 同样如果函数没有声明,编译器会默认认为这个函数是一个 int类型返回值并且有两个int类型参数的函数,为了程序便于阅读,所有的函数在使用前都需要原型声明,再定义。
逗号运算符
- 调用函数时的逗号和逗号运算符怎么区分?
- 调用函数时的圆括号里的逗号是标点分隔符,不是运算符
- f(a,b) 标点分割符,分割多个参数
- f((a,b)) 算术运算符
- (a,b) 逗号运算符自左向右运算,先计算左边表达式的值,再计算右边表达式的值,最后的结果返回右边表达式的值。比如 (a=3+2,a-5)的结果是 0
函数里面的函数
- c语言不允许函数的嵌套定义
奇怪的写法
- int i,j,sum(int a,int b); 虽然c语言允许这么做,但是不推荐这种写法,不易于阅读。
- return (i); 返回一个i的值,同样不推荐,理由同上。
关于main
- int mian()也是一个函数
- 要不要写成int main(void)? 可以写成void,并且在main函数执行前程序还有些准备的工作,当执行好这些准备工作后才会调用main函数
- return的0有人看吗?
- Windows: if errorlevel 1...
- Unix Bash: echo $?
- Csh: echo $status
- return的值在各个系统都是可以得到的,有人会根据返回值来判断程序是否出错等,因此return 0 是有意义的。
5.3 课后习题
1 .题目内容: 题目内容:
每个非素数(合数)都可以写成几个素数(也可称为质数)相乘的形式,这几个素数就都叫
做这个合数的质因数。比如,6 可以被分解为 2x3,而 24 可以被分解为 2x2x2x3。
现在,你的程序要读入一个[2,100000]范围内的整数,然后输出它的质因数分解式;当
读到的就是素数时,输出它本身。
输入格式:
一个整数,范围在[2,100000]内。
输出格式:
形如:
n=axbxcxd
或
n=n
所有的符号之间都没有空格,x 是小写字母 x。
输入样例:
18
输出样例:
18=2x3x3
题目分析:
- 我们前面写过判断素数的功能,可以把他封装成一个函数。
- 这里用用户输入的有两种情况,输入的是一个素数或者合数。
- 素数十分好处理,我们直接输出这个数本身即可。
- 如果是合数怎么算出这个合数的质因数呢?我们有三个未知的问题,一是不知道这个合数有多少个质因数,并且也不知道这些质因数的值和组合方式。
- 我们可以采取笨一点的办法,
- 用这个合数num和最小素数2做取余,如果结果不为0,则表示除不尽继续用下一个素数3做整除,一直到能整除为止,算出一个结果。
- 将结果赋值给num,如果num还是合数回到第1步,否则我们就已经把最初的素数num拆分成n个相乘的素数了,也就是这个合数的质因数。
- 因此我们还需要一个取第x个素数的值一个函数,x>0
程序实现:
#ifndef getPrimeFactor_h
#define getPrimeFactor_h
#include <stdio.h>
int isPrime(int number);
void getPrimeFactor(void);
int getPrimeNumber(int index);
#endif
#include "getPrimeFactor.h"
int isPrime(int number)
{
int isPrimeNumber = 1;
int middle = 0;
if (number == 1)
{
isPrimeNumber = 0;
}
else
{
int i = 2;
middle = number / 2;
for (; i <= middle; i++)
{
if (number % i == 0)
{
isPrimeNumber = 0;
break;
}
}
}
return isPrimeNumber;
}
int getPrimeNumber(int index)
{
int isPrimeNumber = 1;
int middle = 0;
int primeNumber = 2;
int i, j;
int currentIndex = 0;
for (j = 2; j < 100000; j++)
{
//重置素数状态
isPrimeNumber=1;
middle = j / 2;
for (i = 2; i <= middle; i++)
{
if (j % i == 0)
{
isPrimeNumber = 0;
break;
}
}
if (isPrimeNumber)
{
primeNumber = j;
currentIndex++;
}
if (index == currentIndex)
{
break;
}
}
return primeNumber;
}
void getPrimeFactor(void)
{
int number = 0;
int currentPrimeNum = 2; //当前素数
int primeIndex = 1; //当前素数的序号,从1开始1,2,3...
printf("请输入一个范围在[2,100000]的整数");
scanf("%d", &number);
if (isPrime(number))
{
printf("%d=%d", number, number);
}
else
{
printf("%d=", number);
do
{
while (number % currentPrimeNum != 0 && currentPrimeNum < number)
{
primeIndex++;
currentPrimeNum = getPrimeNumber(primeIndex);
}
number /= currentPrimeNum;
printf("%dx", currentPrimeNum);
//当number值改变重置状态
currentPrimeNum = 2;
primeIndex = 1;
} while (!isPrime(number));
printf("%d", number);
}
}
#include <stdio.h>
#include "getPrimeFactor.h"
int main(int argc, char *argv[])
{
getPrimeFactor();
return 0;
}
测试样例:
请输入一个范围在[2,100000]的整数18
18=2x3x3
--------------------------------
Process exited after 1.221 seconds with return value 0
请输入一个范围在[2,100000]的整数100
100=2x2x5x5
--------------------------------
Process exited after 1.691 seconds with return value 0
请输入一个范围在[2,100000]的整数108
108=2x2x3x3x3
--------------------------------
Process exited after 2.766 seconds with return value 0
2.题目内容:
一个正整数的因子是所有可以整除它的正整数。而一个数如果恰好等于除它本身外的因子之
和,这个数就称为完数。例如 6=1+2+3(6 的因子是 1,2,3)。
现在,你要写一个程序,读入两个正整数 n 和 m(1<=n<m<1000),输出[n,m]范围内
所有的完数。
提示:可以写一个函数来判断某个数是否是完数。
输入格式:
两个正整数,以空格分隔。
输出格式:
其间所有的完数,以空格分隔,最后一个数字后面没有空格。如果没有,则输出一个空行。
输入样例:
1 10
输出样例:
6
题目分析:
- 我们需要输出n到m范围内所有的完数。
- 如何判断一个数n是否是完数呢?我们用n做取余运算,从1开始取余n/2,这期间所有取余为0的数就是这个数的因子,然后我们再对他们对累加,如果累加的和恰好等于n本身那么这个数就是一个完数。
程序实现:
#ifndef getPerfectNumberRange_h
#define getPerfectNumberRange_h
#include <stdio.h>
void getPerfectNumberRange(void);
int getIsPerfectNumber(int number);
#endif
#include "getPerfectNumberRange.h"
int getIsPerfectNumber(int number)
{
int sum = 0;
int isPerfectNumber = 0;
for (int i = 1; i <= number / 2; i++)
{
if (number % i == 0)
{
sum += i;
}
}
if (sum == number)
{
isPerfectNumber = 1;
}
return isPerfectNumber;
}
void getPerfectNumberRange(void)
{
int n, m;
int isHaveAnyPerfectNumber = 0;
printf("请输入两个正整数n和m,(1<=n<m<1000)");
scanf("%d %d", &n, &m);
for (int i = n; i <= m; i++)
{
if (getIsPerfectNumber(i))
{
printf("%d", i);
if (isHaveAnyPerfectNumber == 0)
{
isHaveAnyPerfectNumber = 1;
}
if (i < m)
{
printf(" ");
}
}
}
if (isHaveAnyPerfectNumber == 0)
{
printf("\n");
}
}
#include <stdio.h>
#include "getPerfectNumberRange.h"
int main(int argc, char *argv[])
{
getPerfectNumberRange();
return 0;
}
测试样例:
请输入两个正整数n和m,(1<=n<m<1000)1 100
6 28
--------------------------------
Process exited after 1.984 seconds with return value 0
请输入两个正整数n和m,(1<=n<m<1000)1 5
--------------------------------
Process exited after 4.39 seconds with return value 0
本文来自博客园,作者:AfreadHuang,转载请注明原文链接:https://www.cnblogs.com/simple-blog/p/9508712.html