1、函数
1.1 函数是什么
数学中就见过函数,例,f(x)=2*x+1,如果给一个不同的数x,就能得到一个不同的f(x),这就是数学中的函数,其实在C语言中跟这非常相似。
维基百科中对函数的定义:子程序
- 在计算机科学中,子程序,是一个大型程序中的某部分代码,由一个或多个语句块组成。它负责完成某项特定任务,而且相较于其他代码,具备相对的独立性。
- 一般会有输入参数并有返回值,提供对过程的封装和细节的隐藏。这些代码通常被集成为软件库。
2 C语言中函数的分类:
2.1、库函数
C语言本质上是没有库函数的,那后来有人在使用C语言的时候,就发现,有一些功能我们经常使用,比如说:求字符串长度,比较两个字符串的大小,打印数据。这么多函数的功能我们经常会用到,频繁被用到,那我们呢就实现一个库函数strlen,我们提供一个这样的函数,我们再提供一个strcmp这样的函数,有了这样的函数,每个程序员就不需要自己去实践了,而是用库里的这一个,我只要把库的函数实现了,没有bug,所有人用起来也就没有bug了......后来就慢慢引入了库函数这样一个概念,有了库函数,代码的书写效率提升了,大家就不需要再重复的写这种基础的代码了,代码效率就提升了。所以这个时候就有了库函数这个概念。
那到底都有哪些库函数呢,那在https://cplusplus.com/reference/
这样一个网站里,就提供一个叫 c library这样的一个库 。
这个库里面介绍了C语言里所对应的一些列头文件。随便点一个头文件(假设stdio.h)进去看,
在这里面就能看到一些库函数的介绍,这个头文件打开的时候往下拉就能找到我们熟悉的函数,printf,scanf......
题外话:
虚拟机,就是虚拟出来一台电脑。
安装一个虚拟机软件,比如,wmare workstation,这个软件装好以后就可以在里面虚拟一个电脑,那这个时候你的电脑里面又有一台电脑,那这个虚拟机里面又可以再装一个电脑,只要你的电脑性能足够好。
一个虚拟机的电脑其实就是虚拟出来的,不是一台真实的电脑,其实就是一个文件,是叫一个后缀为 .vmdk 的这样一个文件,这个文件其实就是一台电脑。
简单的总结,C语言常用的库函数都有:
- IO函数 (输入输出相关函数,它的头文件stdio.h)
- 字符串操作函数 (string.h)
- 字符操作函数
- 内存操作函数
- 时间/日期函数
- 数字函数
- 其他库函数
参照文档,学习几个库函数:
strcpy https://cplusplus.com/reference/cstring/strcpy/
char * strcpy ( char * destination, const char * source );
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[20] = { 0 };//这个空间我给20个字符,里面现在什么都没有 目的地
char arr2[] = "hello world"; //源头
strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
结果:
文档的基本组成
memset https://cplusplus.com/reference/cstring/memset/
#include<stdio.h>
#include<string.h>
int main()
{
char arr[20] = "hello world"; //把这个hell改成5个x
//设置内存里这5个字节(hello)为x
memset(arr, 'x', 5);
printf("%s\n", arr);
return 0;
}
结果:
把wor改成3个y
#include<stdio.h>
#include<string.h>
int main()
{
char arr[20] = "hello world";
memset(arr+6, 'y', 3);
printf("%s\n", arr);
return 0;
}
结果:
注:
使用库函数,必须包含#include对应的头文件
需要学会查询工具的使用:
MSDN(Microsoft Developer Network) 微软开发者的网站
https://cplusplus.com/reference/
en.cppreference.com(英文版)这个是C++官网提供的
zh.cppreference.com(中文版)
2.2、自定义函数
自定义函数,就是由程序员自己来创造的一个函数。
自定义函数和库函数一样,有函数名,返回值类型和函数参数
但是不一样的是这些都是我们自己来设计的。
2.2.1 函数的组成:
ret_type fun_name(para1,*)
{
statement;//语句项
} //这个大括号括起来的是函数体,也就是函数的实现
ret_type 返回类型
fun_name 函数名
para1 函数参数(可以没有,有一个,有多个)
大括号括起来的是函数体,也就是函数的实现
其实我们说函数就相当于一个工厂。
举个例子:
写一个函数,可以找出两个整数中的较大值
//写一个函数,可以找出两个整数中的较大值
#include<stdio.h>
int get_max(int x, int y)//因为传过来一个a一个b是两个整型,那这个时候你把a传过来,这边得有整型来接收吧,写个int x,
//那这个时候你把b传过来,得有整型来接收,写个int y,这个地方x和y就接收了a和b的两个值
//那这个时候要去求a和b的较大值,其实就是求x和y的较大值
{
return (x > y ? x : y);//之前讲的三步操作符,这个结果算出来后return返回就好了
//当这个 x > y ? x : y返回这个值的时候,返回的是个整型值,那这个函数get_max返回值的类型就应该写成int
//这个int要跟他返回的这个值呼应起来
}
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
//求较大值
int m=get_max(a,b);//这个函数来帮我做一件事,求出a和b的较大值,
//那我是不是要把a和b传给他,那我把a和b以参数的形式传给了get_max函数,这个函数得到这个较大值之后就会返回来,返回来之后放到我的m里面去
//m里面接受了我get_max函数计算返回的结果
printf("%d\n", m);
return 0;
}
结果:
这个时候注意,如果这个输入时实现的方法不一样,(就是这条语句 scanf("%d %d", &a, &b); ),
那这个输入方式也不一样,比如写成这样scanf("%d,%d", &a, &b); ,中间加了个逗号,那这个地方要注意,如果这个地方输入10空格20,这种输入方式是错误的,求出的较大值是错误的
打开监视界面可以清楚看到b的值不是20
因为这个时候其实压根没把20读进来,必须要在输入的时候用逗号隔开
设计的时候以什么样的形式实现,键盘上就以什么样的形式输入
这个是函数的调用:
这个是函数的定义(就是没有这个函数,我得去定义他)
int get_max(int x, int y)里面这个哇,
什么时候用int,什么时候不用int,什么时候返回,什么时候不返回,这完全取决于你写的函数的功能,像get_max这个函数是想带回来一个值,那这里就要用return返回,那这个哇这里就得写个int,因为返回的值是int类型,所以哇就写int,返回的是字符,哇就写char,返回的是指针,这个哇就写指针类型,根据实际情况来看,如果写的函数是不需要返回的,那这哇就写个void就行了。
void test()
{
printf("hehe\n");
}//这个代码只需要打印hehe就行,不需要返回,所以就不用写return
写一个函数可以交换两个整型变量的内容
#include<stdio.h>
void Swap(int x, int y)
{
int z = 0;
z = x;
x = y;
y = z;
}
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
printf("交换前:a=%d,b=%d\n", a, b);
//交换
Swap(a,b);//注意,这个函数只需要吧a和b的内容交换了就可以,
//不需要返回什么东西,所以这个时候这个函数的返回类型可以不写
printf("交换后:a=%d,b=%d\n", a, b);
return 0;
}
结果:
通过调试打开监视界面,会发现Swap这里出了问题
这里会发现,a和b的值是正确传进去了的。说明到这一步前都是正确的,
说明一定是
这里除了问题,没有完成任务。之后
这时发现,两个绿框里圈出来的,x和y的地址跟a和b的地址完全不一样,说明这里的a和b是两个独立的变量,上面的x、y是两个独立的变量,说明这里x和y有单独自己的空间,如果又有个z的话,借助于z,确实把这里的x、y进行了交换,但交换x和y又不影响a和b
这就是为什么没有交换的原因。
实参a和b传给x、y的时候,形参是实参的一份临时拷贝(我确实把你的数据拷贝了一份,但是我有自己独立的空间),因为有独立的空间,所以修改形参不会影响到实参。
这里最好让x和y这里的参数和a和b沾上边,沾一点边。(下面是方法)
#include<stdio.h>
int main()
{
int a = 10;
int* p = &a;//&a将a的地址取出来之后,我可以交给p,p的类型就应该写成int*,p是一个指针
//那这里改变a就有两种方法
a = 20;//直接改
*p = 30;//间接改 通过指针变量p里面存的地址,也能找到a来改他
return 0;
}
正确方法:
#include<stdio.h>
void Swap(int* px , int* py )//传了a和b的地址,就应该有个指针来接收
//这个px里面存了a的地址,py里面存了b的地址,
// 这个函数内部想要找到这个函数外部的地址,找到外部的a和b,就很容易了
{
//*px就是a
//*py就是b
//注意这个时候不是交换地址,是把地址所指向内容的值给交换了
int z = *px;//这个时候*px就是a,就相当于把a里面的值放到z里面
//px里面本来存的是a的地址,*px就是a
*px = *py;//就相当于a=b
*py = z;//b=z
//px和py通过远程的方法找到了下面的a和b,把他们的内容进行了交换
}
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
printf("交换前:a=%d,b=%d\n", a, b);
//交换
//Swap(a, b);
Swap(&a, &b);//把a和b的地址传过去
printf("交换后:a=%d,b=%d\n", a, b);
return 0;
}
结果:
虽然这里也是产生了这样两个空间,但这两个空间里面村的是地址,通过地址可以找回来,找回来之后,就是把他里面的内容给修改掉了。
一个工程中,可以有多个 .c 文件,但是只能由一个main函数。
那如果这里是让a和b相加呢
#include<stdio.h>
void Swap(int* px, int* py)
{
int z = *px;
*px = *py;
*py = z;
}
int Add(int x, int y)
{
int z = 0;
z = x + y;
return z;
}
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
int c=Add(a, b);
printf("%d\n",c);
printf("交换前:a=%d,b=%d\n", a, b);
Swap(&a, &b);
printf("交换后:a=%d,b=%d\n", a, b);
return 0;
}
结果:
那为什么刚刚在像Add这种函数没有传地址呢,而像Swap这里就必须要传地址呢,那什么情况下,在实参的部分要传地址,什么情况下不用传地址。
不是返回值的问题,这个Add函数对a和b不用做任何的事情,a、b的值我不改他也无所谓,所以这个时候会发现,只要把a和b的值传过去就行,再看Swap函数这个地方,Swap这个地方,这个函数要把a和b的值交换,如果是把a和b的值直接传进去,传给x和y,这个x和y的交换是不会影响a和b的,所以这个时候没办法了,我们把这个a和b的地址传过去,这个是时候实际上是通过这两个地址,把这个a和b进行了修改,那这个地方好像不是把值传过去就可以了,我把我a和b这两个变量传过去是解决不了问题的。
那这个Swap其实不仅仅是想得到值,而且是想这个Swap函数内部呢,要改变这个Swap函数外面的a和b,要把a和b的值改掉,那这个时候仅仅传a和b是搞不定的,所以我才传了a和b的地址,让这个函数Swap和Swap外面的这个a和b之间建立了一定的联系,这个时候我们才能在Swap内部通过这两个指针来改变我的a和b。
小总结:
如果这个Swap内部想改变我外部的这些变量,那我就需要把a和b的地址传进去,但如果他不想改,就比如说这个Add函数,他只是想得到这个a和b的值,那就把a和b的值传过去就可以了,不需要传地址。
注意,如果把之前这部分改成上面这个图片这个,把Swap函数函数体里面的*去掉,是不行的,这就只是把px和py里面存放的地址交换了,px和py所指向的a和b的值还是没有变。
3、函数的参数
3.1 实际参数(实参):
真实传给函数的参数,叫实参。
实参可以是:常量,变量,表达式,函数等。
无论实参是何种类型的量,在进行函数调用时,他们都必须由确认的值,以便把这些值传给形参。
常量:比如 int c=Add(a, b);,也可以写 int c=Add(10, b);传常量也是可以的。
表达式,比如 int c=Add(a, b);,也可以写 int c=Add(a+3, b);也是可以的。
函数,比如 int c=Add(Add(a, 3), b); (Add(a, 3)这个函数返回值必须是明确的值)
3.2 形式参数(形参):
形式参数是指函数名括号中的变量,因为形式参数只有在函数调用的过程中才实例化(分配内存单元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效。 (Add函数这个x和y在没有调用的时候没有分配空间,只是一串代码,只是形式上的存在)
当实参传递给形参的时候,形参是实参的一份临时拷贝
对形参的修改不能改变实参
4、函数的调用
4.1 传值调用
函数的形参和实参分别占用不同内存块,对形参的修改不会影响实参。
4.2 传址调用
- 传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
- 这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。
那这个传值调用有什么用呢
#include<stdio.h>
void Swap1(int x, int y)
{
int z = 0;
z = x;
x = y;
y = z;
}
void Swap2(int* px, int* py)//形参的指针变量里边儿存的是来自于实参这个地方的一个地址
//这边就要拿指针来接收,
//这个时候会发现Swap2函数内部和我们这个main函数之间的一些数据,就会建立联系
//这个px就能找到这个main函数里面的a
//这个py就能找到这个main函数里面的b
{
int z = *px;
*px = *py;
*py = z;
}
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
printf("交换前:a=%d,b=%d\n", a, b);
//传值调用,就是我们在调用这个函数的时候,传的是这个a和b变量的值本身
Swap1(a, b);
//a和b传给上面的x和y,x和y会是a和b的一份临时拷贝,对x和y的修改是不会影响a和b的
//传址调用,
Swap2(&a, &b);
//是把a和b的地址传过去了,
//让形参和实参之间建立了某种联系
printf("交换后:a=%d,b=%d\n", a, b);
return 0;
}
4.3 练习
1、写一个函数可以判断一个数是不是素数。
2、写一个函数判断一年是不是闰年。
3、写一个函数,实现一个整形有序数组的二分查找。
4、写一个函数,每调用一次这个函数,就会将num的值加1。
4、
int main()
{
int num=0;
//调用函数,使得num每次增加1
return 0;
}
5、答案
1、 写一个函数可以判断一个数是不是素数。
打印100~200之间的素数
素数是只能被1和他本身整除的数
比如7
只能被1和7整除,2、3、4、5、6都不行
那我要判断7是不是素数,我只要拿2到6的数字去试就可以了
第一个版本
#include<stdio.h>
int main()
{
int i = 0;
int count = 0;//看100到200之间一共有多少个素数
for (i = 100; i <= 200; i++)
{
//判断i是否为素数
//是素数就打印
// 拿2~i-1之间的数字去试除i
int flag = 1;//flag是1,表示是素数
//那假设我就默认i是素数
int j = 0;
for (j = 2; j <= i - 1; j++)//产生一个2~i-1之间的数字
{
if (i % j == 0)//如果为真,说明i不是素数,就把flag改成0
{
flag = 0;
break;
}
}
if (flag == 1)//到了这里flag还等于1,说明i不能被2~i-1之间的数字整除
{
count++;
printf("%d ", i);
}
}
printf("\n一共有%d个素数\n", count);
return 0;
}
结果:
第二个版本 优化版
这是不是太多了,不一定就要试到 i-1 ,假设有一个数字叫 m ,如果m不是素数,m一定可以写成m=a*b的方式,就是如果m可以写成m=a*b的方式的时候,我们就说a和b中一定有一个数字是小于等于 sqrt(m) 的,(sqtr是开平方的意思)
如果说 m能写成m=a*b的方式的时候,你只要找到,因子2,还有必要找这个8去吗,没必要。
所以这个地方没有必要硬生生的把 2 到 i-1 之间的所有数字都试出来,只要试出 sqrt(m) 之前的数字就可以了。如果我判断的是 i ,我只要找到 sqrt(i) 之前的数字就可以了。
使用这个 sqrt 函数要包含头文件 math.h
这个 sqrt 是数学库函数,叫开平方
#include<stdio.h>
#include<math.h>
int main()
{
int i = 0;
int count = 0;
for (i = 100; i <= 200; i++)
{
int flag = 1;
int j = 0;
for (j = 2; j <= sqrt(i); j++)
{
if (i % j == 0)
{
flag = 0;
break;
}
}
if (flag == 1)
{
count++;
printf("%d ", i);
}
}
printf("\n一共有%d个素数\n", count);
return 0;
}
这个时候就把试除的范围缩小了很多,但结果还是正确的。
注意,偶数除了2没有可能是素数,素数只能从奇数里面找,我们干脆改成这样
那我们产生的数字就都是奇数,然后在奇数里面判断,从源头上就少了一般
#include<stdio.h>
#include<math.h>
int main()
{
int i = 0;
int count = 0;
for (i = 101; i <= 200; i+=2)
{
int flag = 1;
int j = 0;
for (j = 2; j <= sqrt(i); j++)
{
if (i % j == 0)
{
flag = 0;
break;
}
}
if (flag == 1)
{
count++;
printf("%d ", i);
}
}
printf("\n一共有%d个素数\n", count);
return 0;
}
在文档里面查找,发现这个 sqrt 是对double类型的值开平方,返回的也是double。(当然整型也是没有问题的,整型传给他的时候,无非就是把整型转换成double型,没什么太大的问题)
第三个版本(使用函数) :
#include<stdio.h>
#include<math.h>
//是素数返回1,不是素数返回0
int is_prime(int n)
{
int j = 0;
for (j = 2; j <= sqrt(n); j++)
{
if (n % j == 0)//如果n % j等于0,说明n不是素数
{
return 0;
}
}//这个地方不需要break,因为return的功能是远远强大于break的,
//break是只是跳出了这个循环,但return只要被执行了,这个函数就此打住了,
//这个函数就返回了,结论就出来了
return 1;
}
int main()
{
int i = 0;
int count = 0;
for (i = 101; i <= 200; i+=2)
{
if (is_prime(i))//is_prime这个函数就是用来判断i是不是素数,返回的是1,为真,是素数,打印
//返回的是0,为假,不是素数,不打印
{
printf("%d ", i);
count++;
}
}
printf("\n一共有%d个素数\n", count);
return 0;
}
2、写一个函数判断一年是不是闰年。
写一个函数判断一年是不是闰年。
打印1000到2000年之间的闰年
闰年的判断规则有两个
1、能被4整除,并且不能被100整除是闰年
2、能被400整除是闰年
错误写法:
#include<stdio.h>
int main()
{
int year = 0;
for (year = 1000; year <= 2000; year++)
{
//判断year是不是闰年
if (year % 4 == 0)
{
if (year % 100 != 0)
{
printf("%d ", year);
}
}//这是一个闰年判断的规则
else if (year % 400 == 0)
{
printf("%d ", year);
}
}
return 0;
}
结果:
但是2000和1600也是闰年啊,但是这里没有打印出来,
把下面的else去掉才可以
正确代码:
#include<stdio.h>
int main()
{
int year = 0;
for (year = 1000; year <= 2000; year++)
{
//判断year是不是闰年
if (year % 4 == 0)
{
if (year % 100 != 0)
{
printf("%d ", year);
}
}//这是一个闰年判断的规则
if (year % 400 == 0)
{
printf("%d ", year);
}
}
return 0;
}
正确结果:
简化版:
#include<stdio.h>
int main()
{
int year = 0;
for (year = 1000; year <= 2000; year++)
{
if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0))
{
printf("%d ", year);
}
}
return 0;
}
函数版:
#include<stdio.h>
//是闰年,返回1
//非闰年,返回0
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,为真,是闰年,打印;返回0,为假,不是闰年,不打印
{
printf("%d ", year);
}
}
return 0;
}
为什么不在is_leap_year()函数中直接打印出素数呢?
因为函数的功能一定要实现的足够单一,足够简单。
3、写一个函数,实现一个整形有序数组的二分查找。
#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-left) / 2;//为什么不写mid=(left+right)/2,是为了防止溢出
if (arr[mid] < k)
{
left = mid + 1;
}
else if (arr[mid] > k)
{
right = mid - 1;
}
else
{
return mid;//找到了,返回下标
}
}
return -1; //找不到,返回 - 1
}
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int k = 17;//要查找的值
int sz = sizeof(arr) / sizeof(arr[0]);//求元素个数
//找到了,返回下标
//找不到,返回-1 (找到的数的下标有可能是0,但不可能是-1)
int ret=binary_search(arr,k,sz);//二分查找
//我要知道两个东西
//1、去哪里查 ,去arr这个数组里查,查谁呢,查k
//2、查到之后找到了还是没找到,就拿一个ret来接收是否找到的讯息
//查的时候需要知道这个数组有几个元素,因为我需要左下标和右下标,右下标跟数组元素有关系
if (ret == -1)
{
printf("找不到\n");
}
else
{
printf("找到了,下标是:%d\n", ret);
}
return 0;
}
结果:
形式参数和实际参数的名字可以相同,也可以不同。
传数组的数据的时候直接写个数组名就可以了,不需要加 [ ] 。
这个时候不考虑EOF,虽然EOF本质上是-1,但是我们不要返回EOF,EOF是在万不得已的情况下,我们才讨论EOF的问题。
如果将代码改成这样呢?
//这是一个错误的示范
#include<stdio.h>
int binary_search(int arr[], int k)
{
int sz = sizeof(arr) / sizeof(arr[0]);
int left = 0;
int right = sz - 1;
while (left <= right)
{
int mid = left + (right - left) / 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);
if (ret == -1)
{
printf("找不到\n");
}
else
{
printf("找到了,下标是:%d\n", ret);
}
return 0;
}
结果:
分析:
形参arr看上去是数组,本质上是指针变量。
在这个地方永远都不要奢望在这个binary_search函数内部来计算参数部分一个数组的元素个数,做不到。
小总结:
数组传参,实际上传递的是数组首元素的地址,而不是整个数组,
所以在函数内部计算一个函数参数部分的数组的元素个数是不靠谱的。
4、写一个函数,每调用一次这个函数,就会将num的值加1。
第一种写法:
#include<stdio.h>
void Add(int* p)
{
(*p)++;//这样操作之后已经让num的值变化了,所以不需要返回,写void就可以了
}
int main()
{
int num = 0;
Add(&num);//这个Add函数会改变num,那这个时候就要把num的地址传进来
printf("%d\n", num); //1
Add(&num);
printf("%d\n", num); //2
Add(&num);
printf("%d\n", num); //3
Add(&num);
printf("%d\n", num); //4
return 0;
}
结果:
第二种写法 :
#include<stdio.h>
int Add(int n)
{
return n+1;//注意这里不能写成n++,因为他是后置++,所以先返回n再加加,就没有意义了。
//但是写成++n就可以,先加再返回。
}
int main()
{
int num = 0;
num = Add(num);
printf("%d\n", num); //1
num = Add(num);
printf("%d\n", num); //2
num = Add(num);
printf("%d\n", num); //3
num = Add(num);
printf("%d\n", num); //4
return 0;
}
这样也可以。一个代码他的实现方法可能是非常多的。
6、布尔类型:
在C99中,引入了布尔类型,bool :用来表示真假的变量。1个字节
比如:bool flag=true; bool flag=false; 就是要么是真,要么是假,只有这两种值。
//把判断一个数是不是素数搬过来做实例
#include<stdio.h>
#include<stdbool.h>
#include<math.h>
bool is_prime(int n)//要使用bool类型,要引用stdbool.h这个头文件
{
int j = 0;
for (j = 2; j <= sqrt(n); j++)
{
if (n % j == 0)//如果n % j等于0,说明n不是素数
{
return false;
}
}
return true;
}
int main()
{
int i = 0;
for (i = 100; i <= 200; i++)
{
if (is_prime(i))
{
printf("%d ", i);
}
}
return 0;
}
结果:
这时转到定义就会发现: