C语言——函数

C语言目录:

1. 概述

2. 数据类型

3. 量

4. 运算符

5. 流程控制

6. 函数

7. C程序编译过程

8. 文件

9. 内存管理


将一个常用的功能封装起来,方便以后调用

6.1 分类及定义

同一源文件函数名称不能相同

返回值类型 函数名(参数类型 形式参数1,参数类型 形式参数2,…){
    函数体;
    返回值;
}
分类
函数定义
库函数
用户定义函数
函数执行结果
有返回值函数
无返回值函数
数据传送
无参函数
有参函数

6.1.1 库函数与用户定义函数

a. 库函数

由C语言系统提供,用户无需定义,也不必在程序中做类型说明,引入头文件后即可在程序中直接调用

b. 用户定义的函数

由用户按需编写的函数。对于用户自定义的函数,不仅要在程序中定义函数本身,而且在主调函数中必须对该被调函数进行声明,才能调用

6.1.2 有返回值与无返回值函数

a. 有返回值函数

必须指定返回值类型和使用return关键字返回对应数据

返回值类型 函数名(参数列表){
    函数体;
    返回值;
}
b. 无返回值函数
void 函数名(参数列表) {
    函数体;
}

6.1.3 有参函数和无参函数

a. 无参函数
返回值类型 函数名() {
    函数体;
    return;
}
b. 有参函数
返回值类型 函数名(参数类型 形式参数1,参数类型 形式参数2,…) {
    函数体;
    return 0;
}

6.2 参数与返回值

6.2.1 形参与实参

形参 :定义函数时,函数名后面的 () 称为形参

形参变量只有在函数被调用时分配内存。在函数调用结束,释放内存单元

实参 :函数调用时,传入的值称为实参

实参可以是常量、变量、表达式、函数等

在进行函数调用时,都必须具有确定的值,以便把这些值传递给形参

a. 注意

个数:调用函数时,传递的实参个数和函数的形参个数必须保持一致

类型:形参与实参类型不一致,会自动转换为形参类型

void change(double number1, double number2) {//  形参
}

int main() {
    change(10, 20);
    // 传入实参  10.000000, 20.000000
   // 自动将实参转换为double类型后保存
    
    return 0;
}

值传递:当使用基本数据类型(char、int、float)作为实参时,实参和形参之间只是值传递,修改形参的值并不影响实参

void change(int number1, int number2) { //  形式参数
    number1 = 250; // 不会影响实参
    number2 = 222;
}

int main() {
    int a = 88;
    int b = 99;
    change(a, b);
    printf("a  = %d, b = %d", a, b); // 输出结果: 88, 99
    return 0;
}

6.2.2 返回值

如果没有写返回值类型,默认是 int

return 实际返回的值类型应与函数返回值类型一致,否则以返回值类型为准,自动进行类型转换

int height() {
    return 3.14; 
}

int main() {
  double temp = height();
  printf("%lf", temp);// 输出结果: 3.000000
}

一个函数内部可以多次使用 return ,但 return 之后的代码不再执行

6.3 函数的声明

默认情况下,只有后面定义的函数才可以调用前面定义过的函数

函数声明:在函数调用之前告诉系统,函数名称、参数列表、返回值类型

函数实现:定义具体的业务逻辑是怎么运作的

函数声明格式:返回值类型 函数名(参数列表);

// 函数声明
void getMax(int v1, int v2);
int main(int argc, const char * argv[]) {
    getMax(10, 20); // 调用函数
    return 0;
}
// 函数实现
void getMax(int v1, int v2) {
    int max = v1 > v2 ? v1 : v2;
    printf("max = %i\n", max);
}
  • 函数的实现不能重复, 而函数的声明可以重复

  • 函数声明可以写在函数外面,也可以写在函数里面,,只要在调用之前被声明即可

int main(int argc, const char * argv[]) {
    void getMax(int v1, int v2); // 函数声明, 不会报错
    getMax(10, 20); // 调用函数
    return 0;
}
// 函数实现
void getMax(int v1, int v2) {
    int max = v1 > v2 ? v1 : v2;
    printf("max = %i\n", max);
}

如果被调函数的返回值是整型,可以不对被调函数做声明,可以直接调用

int main(int argc, const char * argv[]) {
    int res = getMin(5, 3); // 不会报错
    printf("result = %d\n", res );
    return 0;
}

int getMin(int num1, int num2) {// 返回int, 不用声明
    return num1 < num2 ? num1 : num2;
}

6.4 输入输出

6.4.1 putchar()和getchar()

putchar():向屏幕输出一个字符

#include <stdio.h>
int main(){
    char ch = 'a';
    putchar(ch); // 输出a
}

getchar():从键盘获取一个字符

#include <stdio.h>
int main(){
    char ch;
    ch = getchar();// 获取一个字符
    printf("ch = %c\n", ch);
}

6.4.2 scanf函数

系统会先将用户输入放入输入缓冲区,从缓冲区中逐个取数据赋值给变量,如果输入缓冲区不为空,scanf 会一直从缓冲区中获取

#include <stdio.h>

int main(){
    int num1;
    int num2;
    char ch1;
    scanf("%d%c%d", &num1, &ch1, &num2);
    printf("num1 = %d, ch1 = %c, num2 = %d\n", num1, ch1, num2);
    
    char ch2;
    int num3;
    scanf("%c%d",&ch2, &num3);

    printf("ch2 = %c, num3 = %d\n", ch2, num3);
}

在这里插入图片描述

a. fflush

利用 fflush(stdin); 清空缓冲区

C和C++标准从未定义过,是C标准的扩充函数,不是所有平台都支持

b. setbuf

setbuf(stdin,NULL) 设置缓冲区为空

所有平台有效

6.4.3 printf()函数格式

a. 数据类型符
类型含义
%d / %i有符号十进制整型
%u无符号十进制整型
%o无符号八进制整型
%x / %X无符号十六进制整型
%f单、双精度浮点数
%e / %E以指数形式输出单、双精度浮点数
%c字符
%s字符串
%p地址
%%表示%本身
#include <stdio.h>

int main(){
    int a = 10;    
    int b = -10;
    
    // 有符号整数(可以输出负数)
    printf("a = %d\n", a); // 10
    printf("a = %i\n", a); // 10

    // 无符号整数(不可以输出负数)
    // 输出存储单元内二进制数对应的十进制整数
    printf("a = %u\n", a); // 10
    printf("b = %u\n", b); // 429496786

    // 无符号八进制整数(不可以输出负数)
    //输出存储单元内二进制数对应的十进制整数对应的八进制数
    printf("a = %o\n", a); // 12
    printf("b = %o\n", b); // 37777777766

    // 无符号十六进制整数(不可以输出负数)
    printf("a = %x\n", a); // a
    printf("b = %x\n", b); // fffffff6

    // 无符号十六进制整数(不可以输出负数)
    printf("a = %X\n", a); // A
    printf("b = %X\n", b); // FFFFFFF6

    float c = 6.6f;
    double d = 3.1415926;
    
    // 单、双精度浮点数(默认保留6位小数)
    printf("c = %f\n", c); // 6.600000
    printf("d = %lf\n", d); // 3.141593

    double e = 10.10;
    // 以指数形式输出单、双精度浮点数
    printf("e = %e\n", e); // 1.010000e+001
    printf("e = %E\n", e); // 1.010000E+001
    
    // 以最短输出宽度,输出单、双精度浮点数
    printf("e = %g\n", e); // 10.1
    printf("e = %G\n", e); // 10.1
    
    char f = 'a';
    // 输出字符
    printf("f = %c\n", f); // a
}
实型有效位问题
  • 单精度 %f 输出时,仅前6-7位是有效数字;双精度 %lf 输出时,仅前15-16位是有效数字
  • 有效位数包含小数点前的非零数位

精度与有效位

有效位:指从第一个非零数字开始,误差不超过本数位半个单位的、正确的数位

原因:计算机存储浮点数时,采用IEEE754,存的是IEEE754可表示的最相近浮点数

#include <stdio.h>
int main(){
    //        1234.567871093750000
    float a = 1234.567890123456789;
    //         1234.567890123456900
    double b = 1234.567890123456789;
    printf("a = %.15f\n", a); // 前8位数字是准确的, 后面的都不准确
    printf("b = %.15f\n", b); // 前16位数字是准确的, 后面的都不准确
}
b. 精度格式符

精度:小数点后位数

%.n数据类型符 ,n为十进制整数

  • 如果输出数字,则表示小数的位数;
  • 如果输出的是字符,则表示输出字符的个数;
  • 若实际位数大于所定义的精度数,则截去超过的部分
#include <stdio.h>
int main(){
    double a = 3.1415926;
    printf("a = %.2f\n", a); // 3.14
}
动态指定保留小数位数

格式:printf("%.*f",[],a);

#include <stdio.h>
int main(){
    double a = 3.1415926;
    printf("a = %.*f", 2, a); // 3.14
}
c. 格式控制符
符号含义
%m…m指定输出字段的宽度,如果位数小于m,则左端以空格补全;若位数大于,则按实际位数输出
-结果左对齐,右边补空格
#对于c,s,d,u类影响
八进制,加前缀o
十六进制,加前缀0x
对于浮点数,只有当结果有小数才给出小数点
空格输出值为整数,在输出值前面加上空格,为负数加上负号
+当输出值为正数时,在输出值前面加上一个+号, 默认不显示
0右对齐时,用0填充
#include <stdio.h>
int main(){
    int a = 1;
    int b = -1;
    // -号标志
    printf("a =|%d|\n", a); // |1|
    printf("a =|%5d|\n", a); // |    1|
    printf("a =|%-5d|\n", a);// |1    |
    // +号标志
    printf("a =|%d|\n", a); // |1|
    printf("a =|%+d|\n", a);// |+1|
    printf("b =|%d|\n", b); // |-1|
    printf("b =|%+d|\n", b);// |-1|
    // 0标志
    printf("a =|%5d|\n", a); // |    1|
    printf("a =|%05d|\n", a); // |00001|
    // 空格标志
    printf("a =|% d|\n", a); // | 1|
    printf("b =|% d|\n", b); // |-1|
    // #号
    int c = 10;
    printf("c = %o\n", c); // 12
    printf("c = %#o\n", c); // 012
    printf("c = %x\n", c); // a
    printf("c = %#x\n", c); // 0xa
}

6.7 递归函数

一个函数在它的函数体内调用它自身称为递归调用

  • 递归常用于"回溯", “树的遍历”,"图的搜索"等问题
void function(int x){
    function(x);
}
  • 存在一个条件能够让递归结束

  • 问题的规模能够缩小

  • 能用循环实现的功能,用递归都可以实现

代码理解难度大内存消耗大(易导致栈溢出), 所以考虑到代码理解难度和内存消耗问题, 在企业开发中一般能用循环都不会使用递归

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

AmosTian

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

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

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

打赏作者

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

抵扣说明:

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

余额充值