首页 > 其他分享 >【我开了C语言的金手指】二.函数(1)

【我开了C语言的金手指】二.函数(1)

时间:2022-10-07 10:04:20浏览次数:78  
标签:return 函数 int max 金手指 C语言 我开 printf main

(一)函数的定义

  是一个大型程序中的某部分代码,由一个或多个语句块组成。它负责完成某项特定的任务,相较于其它的代码,具备相对独立性。

  一般会有输入参数并有返回值,提供对过程封装和细节的隐藏。这些代码通常被集成为软件库。

#define _CRT_SECURE_NO_WARINGS 1
#include<stdio.h>

int Add(int x, int y)
{
int z;
z = x + y;
return z;
}

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

【我开了C语言的金手指】二.函数(1)_嵌套

(二)C语言中函数的分类:

1.库函数

1.1作用

一些用以描述基础功能,不是业务性的代码;开发的过程中每个程序员都能用上的;可以支持可移植性和提高程序的效率;C语言的基础库为我们提供了一系列类似的库函数。

1.2常用

IO函数(input output)

字符串操作函数

字符操作函数

内存操作函数

时间/日期函数

数学函数

其它库函数

1.3怎么使用函数

参照文档,学习使用库函数 

​www.cplusplus.com​

​cppreference.com​

MSDN

例如strcpy

#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "ak\0";
char arr2[20] = "#########";
strcpy(arr2, arr1);
printf("%s\n", arr2);
return 0;
}

接收后为​​ak\0######​​,打印是时\0为字符串的结束标志

例如memset

#include<stdio.h>
#include<string.h>
int main()
{
char arr[] = "hello world";
memset(arr, '*', 5);
printf("%s\n", arr);
return 0;
}

2.自定义函数

2.1函数的基本组成

ret_type fun_name(para1,*)
{
statement; //语句项
}

//ret_type 返回类型
//fun_name 函数名
//para1 函数参数

2.2例子

取最大值

#include <stdio.h>
//get_max函数的设计
int get_max(int x, int y)
{
return (x > y) ? (x) : (y);
}
int main()
{
int num1 = 10;
int num2 = 20;
int max = get_max(num1, num2);
printf("max = %d\n", max);
return 0;
}

交换

我们可以先不用函数,了解交换的逻辑:

#include<stdio.h>
int main()
{
int a = 20;
int b = 10;
int tmp = 0;
printf("a=%d b=%d\n", a, b);
tmp = a;
a = b;
b = tmp;
printf("a=%d b=%d\n", a, b);
return 0;
}

那接下来我们可以引入函数解决问题:

void Swap(int x, int y)
{
int tmp = 0;
tmp = x;
x = y;
y = tmp;
}
#include<stdio.h>
int main()
{
int a = 20;
int b = 10;
printf("a=%d b=%d\n", a, b);
Swap(a, b);
printf("a=%d b=%d\n", a, b);
return 0;
}

但是,我们发现这样写并没有达到我们设想的效果

【我开了C语言的金手指】二.函数(1)_#include_02

这是因为x,y有自己的坐标空间,除了接收a,b的值以外,与a,b无更多联系。(详见(三)_3)

知识预备

#include<stdio.h>
int main()
{
int a = 10;
int* pa = &a;//pa指针变量
*pa = 20;//解引用操作符
printf("%d\n", a);
return 0;
}

通过将a和b的地址传输给x,y;

void Swap(int *x, int *y)
{
int tmp = 0;
tmp = *x;
*x = *y;
*y = tmp;
}
#include<stdio.h>
int main()
{
int a = 20;
int b = 10;
printf("a=%d b=%d\n", a, b);
Swap(&a, &b);
printf("a=%d b=%d\n", a, b);
return 0;
}

任务完成

(三)函数的参数

1.实际参数:

真实传给函数的参数,叫实参。

可以是:常量,变量,表达式,函数等。

//常量
#include<stdio.h>

int find_max(int x, int y)
{
if (x > y)
return x;
else
return y;
}

int main()
{
int a = 10;
int b = 20;
int max = find_max(200,100); //看这里
printf("the max is %d\n", max);
return 0;
}
//变量
#include<stdio.h>

int find_max(int x, int y)
{
if (x > y)
return x;
else
return y;
}

int main()
{
int a = 10;
int b = 20;
int max = find_max(a,b); //看这里
printf("the max is %d\n", max);
return 0;
}
\\表达式
#include<stdio.h>

int find_max(int x, int y)
{
if (x > y)
return x;
else
return y;
}

int main()
{
int a = 10;
int b = 20;
int max = find_max(a,b+1); //看这里
printf("the max is %d\n", max);
return 0;
}
//函数
int find_max(int x, int y)
{
if (x > y)
return x;
else
return y;
}
int main()
{
int a = 10;
int b = 20;
int max = find_max(a,find_max(100,7)); //看这里
printf("the max is %d\n", max);
return 0;
}

无论是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。

2.形式参数:

函数名后括号中的变量,只有在函数被调用的时候才实例化(分配内存单元)

形参当函数掉用完后就自动销毁。

void Swap(int *x, int *y)  //xy为形式参数
{
int tmp = 0;
tmp = *x;
*x = *y;
*y = tmp;
}
#include<stdio.h>
int main()
{
int a = 20;
int b = 10; //ab为实参
printf("a=%d b=%d\n", a, b);
Swap(&a, &b);
printf("a=%d b=%d\n", a, b);
return 0;
}

3.注意

形参是实参的一份临时拷贝,拥有自己的空间,对形参的修改不会改变实参!

(四)函数调用

1.传值调用​​(a,b)​

函数的形参和实参分别占有不同的内存块,对形参的修改不会影响实参。

使用情况:不改变函数外变量,如比大小。

2.传址调用​​(&a,&b)​

把函数外部创建变量的地址传递给函数参数的一种调用函数的方式。

可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。

使用情况:要改变函数外变量,比如交换。

3.练习

3.1写一个函数可以判断一个数是不是素数。

#include<stdio.h>
#include<math.h>
int is_prime(int a)
{
int j = 0;
for (j = 2; j <=sqrt(a); j++)
{
if (a % j == 0)
return 0;
}
return 1; //当j超出sqrt(a)时都没找到因数,说明此时i为素数,返回1。
}
int main()
{
int i=0;
for (i = 100;i<=200;i++)
{
if (is_prime(i) == 1)
printf(" %d", i);
}
return 0;
}

3.2判断是不是闰年

#include<stdio.h>
int is_leap_year(int y)
{
if ((y % 4 == 0 && y % 100 != 0 )|| (y % 400 == 0))
return 1;
else
return 0;
}


int main()
{
int year = 0;
for (year = 1000; year <= 2000; year++)
{
if (is_leap_year(year) == 1)
printf("%d ",year);
}
return 0;
}

3.3实现一个整形有序数组中实现二分查找

#include<stdio.h>

int binary_search(int arr[], int k) //此时arr本质上是指针
{
int sz = sizeof(arr) / sizeof(arr[0]);
int left = 0;
int right = sz - 1;
while (left <= right)
{
int mid = (left + right) / 2;
if (arr[mid] < k)
{
left = mid + 1;
}
else if (arr[mid] > k)
{
right = mid - 1;
}
else
{
return mid;
}
}
return -1;
}

int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int k = 7;
int ret=binary_search(arr, k); //数组传输时只传输arr首元素的地址,节约空间
if (ret == -1)
{
printf("找不到指定的数字\n");
}
else
{
printf("找到了,下标是: %d\n", ret);
}

return 0;
}

我们发现带码运行错误,

【我开了C语言的金手指】二.函数(1)_库函数_03

这是因为数组传输时为了节约空间只传输arr首元素的地址,此时形参的arr相当于指针。

#include<stdio.h>

int binary_search(int arr[], int k,int sz)
{

int left = 0;
int right = sz - 1;

while (left <= right)
{
int mid = (left + right) / 2;
if (arr[mid] < k)
{
left = mid + 1;
}
else if (arr[mid] > k)
{
right = mid - 1;
}
else
{
return mid;
}
}
return -1;
}

int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int k = 7;
int sz = sizeof(arr) / sizeof(arr[0]);
int ret=binary_search(arr, k,sz);
if (ret == -1)
{
printf("找不到指定的数字\n");
}
else
{
printf("找到了,下标是: %d\n", ret);
}

return 0;
}

注:

11行代码​​ int mid = (left + right) / 2;​​不能移除出循环;

循环的判断条件一定是<=;

找不到时要有对应的输出-1

3.4每调用一次函数,num+1

#include<stdio.h>

void add(int* p)
{
(* p)++;
}

int main()
{
int num = 0;
add(&num);
printf("num=%d\n", num);

add(&num);
printf("num=%d\n", num);

add(&num);
printf("num=%d\n", num);
return 0;
}

(五)函数的嵌套调用和链式访问

1.嵌套调用

函数之间可以相互调用

#include<stdio.h>

void new_line()
{
printf("dd\n");
}

void three_new_line()
{
int i = 1;
for (i = 1; i <=3; i++)
{
new_line();
}
}

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

2.链式访问

把一个函数的返回值作为另一个函数的参数。

#include<stdio.h>
int main()
{
int len = 0;
len = strlen("abc");
printf("%d\n", len);
printf("%d\n", strlen("abc"));
return 0;
}

思考以下函数打印什么

#include<stdio.h>
int main()
{
printf("%d", printf("%d", printf("%d", 43)));
return 0;
}

【我开了C语言的金手指】二.函数(1)_#include_04

先打印43,两个字符,返回2

打印2,一个字符,返回1

打印1,

(六)函数的声明和定义

1.函数的声明

告诉编译器一个函数叫什么,参数是什么,返回类型是什么,但是具体存不存在,函数声明决定不了;

函数的声明一般放在函数前,先声明,后使用;

函数声明一般放在头文件中。


程序需要顺序阅读,当函数放在主体代码后时,需要在前面先声明函数(当然,在一些新的编译器中做出了优化,即使不声明,也可以用函数)。

#include<stdio.h>
//int add(int x, int y);

int main()
{
int a = 10;
int b = 56;
int sum = add(a, b);
printf("%d", sum);
return 0;
}

int add(int x, int y)
{
int z = x + y;
return z;
}

当然,也可以创建一个add.h用来存放声明,创建一个add.c存放函数,以后使用时,在主程序中引用(注意使用双引号)即可。

【我开了C语言的金手指】二.函数(1)_#include_05

【我开了C语言的金手指】二.函数(1)_嵌套_06

       #ifndef:如果没有定义函数,就定义;如果之前定义过,为假结束,防止重复引用。

2.函数的定义

指函数的具体实现,交代函数的功能实现。

test.h放置函数的声明

test.c放置函数的实现










标签:return,函数,int,max,金手指,C语言,我开,printf,main
From: https://blog.51cto.com/u_15796276/5734215

相关文章

  • FC龙珠Z外传赛亚人灭绝计划,可控制贝吉塔和简单金手指
    无意中搜到有似乎有贝吉塔可控的修改ROM还是中文的,但是中文版VirtuaNES加载不上,用其他模拟器如nestopia显示也比日文原版慢很多,所以花点时间直接做成了金手指,也方便用搜索......
  • [C语言]CLion Recommends to use 'strtof' instand of 'scanf'
    #include<stdio.h>intmain(){floatOilConsumption;printf("PleaseentertheFuelConsumption:\n");scanf("%f",&OilConsumption);printf("Fu......
  • C语言学习记录5
    #每日美图分享#huhufor循环的执行顺序为:初始化——>判断——>最后再调整#include<stdio.h>intmain(){inti=0;for(i=0//初始化;i<10//判断;i++//调整){......
  • 开始学c语言的感受
    刚开始写博文,不知道如何下手。身在宿舍,为了提升自己的写作技巧、打字速度,保持自己的热情以及复习自己所学的知识,在大佬的推荐下,我选择了博客。刚开始听起编程语言的时候,觉得......
  • C语言-逻辑运算符
    i++与++i的区别intmain(intargc,char*argv[]){inti=1; ints=++i; intx=i++; printf("%d,%d,%d",i,s,x); return0;} 答案:“3,2,2”。解析:i......
  • 多种PID算法用C语言来实现
    原文链接:https://blog.csdn.net/Nirvana_Tai/article/details/105409311,随后整理验证,再补充(一)前言  PID算法在工业应用中随处可见。大学期间,想做各类科创也少不了PI......
  • C语言操作符
    1.在进行除法运算的时候,如果两个操作数都是整数,那么结果就是整数。要想得到的结果是浮点数,至少有一个操作数是浮点数,最后的结果也是定义为浮点类型。2.在进行取模运算的时候......
  • 【C语言】初始函数
    ......
  • C语言下for循环的一点技巧总结
    for循环是普遍应用与各种计算机语言的一种循环方式。一般情况下,for循环规则:for(条件一;条件二;条件三)条件一为满足条件,也就是条件一为1时,进入这个for循环。条件二为循环......
  • C语言基础笔试题解析
    题目在这里:​​c语言笔试面试大全,C语言基础笔试题_Thomas杨大炮的博客-CSDN博客t​​2.C语言程序的三种基本结构都有哪些呢?3. ​​递归调用​​和间接递归调用​​定义​......