函数的定义和声明
返回类型 函数名(数据类型 形式参数,…)
{
}
1.可以定义在main后面,也可以前面
2.只有main函数调用时,函数才会执行
1.形参和实参的概念
形参(也叫形式参数)
在定义函数名和函数体的时候使用的参数,他没有数据,可以看做一个占位符,只能等到函数被调用时接收传递进来的数据,所以称为形式参数;
实参(也叫实际参数)
在调用时传递给函数的参数,即传递给被调用函数的值,会被被调用函数内部使用,所以称为实际参数;
2.形参和实参的区别与联系
形参和实参的区别:
1):
形参变量在函数未被调用时是不占内存空间的,只有在函数被调用时才会给其分配内存空间,调用结束后内存被回收,所以形参只作用于被调函数内部;
实参是开辟了空间了的,并存储了数据;
2):
形参只能是变量并且必须指定其类型;
实参可以是常量,变量,表达式或者函数等;
3):
形参没有确定的值;
实参在进行函数调用时须具有确定的值,以便把这些值传送给形参;
4):
在一般传值调用的机制中只能把实参传送给形参,而不能把形参的值反向地传送给实参。因此在函数调用过程中,形参值发生改变,而实参中的值不会变化。
在引用调用的机制当中是将实参引用的地址传递给了形参,所以任何发生在形参上的改变实际上也发生在实参变量上。
形参和实参之间的联系:
1):形参和实参在类型上,数量上,循序上必须一致;
RG:F(x)=x*x
#include<stdio.h>
int f(int x){
x=x*x;
return x;
}
int main(void){
int a=5,b;
b=f(a);
printf("a=%d,b=%d",a,b);
return 0;
}
试一试做一下水仙花数
#include<stdio.h>
int judge(int n){
int a,b,c;
a=n/100;
b=(n/10)%10;
c=n%10;
if(a*a*a+b*b*b+c*c*c==n) return 1;
return 0;
}
int main(void){
int i;
for(i=100;i<=999;i++){
if(judge(i)==1)
printf("%d\n",i);
}
return 0;
}
-
形式参数与实际参数之间是单向值传递
-
在函数内对形式参数的修改不会影响main 函数内的实际参数
-
返回类型为void时,没有return语句
-
对函数类型未加说明,函数的隐含类型为int
#include<stdio.h>
int fun3(int x){
static int a=3; // static:保存上一个a的值
a=a+x;
return a;
}
int main (void){
int k=2,m=1,n;
n=fun3(k); // n=3+2=5 a=5
n=fun3(m); //n=5+1=6 a=6
printf("%d\n",n);
return 0;
}
题目:输出100以内的素数
#include<stdio.h>
int prime(int n){
int i;
for(i=2;i<n;i++){
if(n%i==0)
return 0;
}
return 1;
}
int main(void){
int i;
for(i=2;i<100;i++){
if(prime(i)==1)
printf("%d\n",i);
}
return 0;
}
- main函数可以调用其他函数,不能被调用
- 函数定义不允许嵌套,调用允许嵌套
函数的递归(调用它本身)
题目:求斐波那契数列
#include<stdio.h>
long f(int n){
long s;
if(n==1||n==2) return 1;
s=f(n-1)+f(n-2);
return s;
}
int main(void){
int n;
printf("please input n:");
scanf("%d",&n);
if(n<0)
printf("error!\n");
else
printf("第%d项斐波那契数列的值是%ld",n,f(n));
return 0;
}
1、写两个函数,分别求两个整数的最大公约数和最小公倍数,用主函数调用这两个函数,并输出结果。两个整数由键盘输人。
#include<stdio.h>
//最大公约数 最大公约数找出两数中的最小值,然后直接相模,当能够同时被两数整除时,则为最大公约数。
size_t GCD(size_t a, size_t b)
{
size_t gcd;
gcd = a > b ? b : a;
while(gcd > 1)
{
if((a % gcd == 0) && (b % gcd == 0))
return gcd;
gcd--;
}
return gcd;
}
//最小公倍数
size_t LCM(size_t a, size_t b)
{
size_t lcm;
lcm = a > b ? a : b;
while(1)
{
if((lcm % a==0) && (lcm % b==0))
break;
lcm++;
}
return lcm;
}
int main()
{
size_t a, b, result;
printf("请输入两个整数:>");
scanf("%d %d", &a, &b);
result = GCD(a, b);
printf("%d和%d的最大公约数为:%d\n", a, b, result);
result = LCM(a, b);
printf("%d和%d的最小公倍数为:%d\n", a, b, result);
return 0;
}
- 写一个判素数的函数,在主函数输人一个整数,输出是否为素数的信息
#include<stdio.h>
#include<stdbool.h>
bool IsPrime(int value) //使用了<stdbool.h>后,可使用true和false来表示真假。
{
for(int i=2; i<value/2; ++i)
{
if(value % i == 0) //说明除了1和本身之外,还能被其他数整除
return false;
}
return true;
}
int main()
{
int value;
bool flag;
printf("请输入 value :>");
scanf("%d", &value);
flag = IsPrime(value);
if(flag)
printf("%d 是素数.\n", value);
else
printf("%d 不是素数.\n", value);
return 0;
}
- 写一个函数,使给定的一个3X3的二维整型数组转置,即行列互换
关键在于数组互换的表达式 ar[i] [j] = ar[j] [i];其次在循环的时候,内层循环不能到达最大列,需要根据此时是第几行的交换来决定循环的次数,否则有可能数组行列交换之后最后又交换回原来的形状了。
#include<stdio.h>
void PrintArray(int ar[3][3])
{
for(int i=0; i<3; ++i)
{
for(int j=0; j<3; ++j)
{
printf("%d ", ar[i][j]);
}
printf("\n");
}
}
void ReverseArray(int ar[3][3])
{
int tmp;
for(int i=0; i<3; ++i)
{
for(int j=0; j<i; ++j)
{
if(i != j) //中间数不发生变化
{
//交换两个数
tmp = ar[i][j];
ar[i][j] = ar[j][i];
ar[j][i] = tmp;
}
}
}
}
int main()
{
int array[3][3] =
{
{1,2,3},
{4,5,6},
{7,8,9}
};
printf("转置前:\n");
PrintArray(array);
//进行数组转置
ReverseArray(array);
printf("转置后:\n");
PrintArray(array);
return 0;
}
- 写一个函数,使输人的一个字符串按反序存放,在主函数中输入和输出字符串。
要把一个字符串反序存放,其实就是对字符串做一个逆序操作,操作过程为收尾字符交换,直到把所有字符全部交换完毕。
strlen()函数
用法:#include <string.h>
功能:计算字符串s的(unsigned int型)长度
说明:返回s的长度,不包括结束符NULL。
#include<stdio.h>
#include<string.h>
void ReverseString(char str[])
{
int start, end;
char tmp;
start = 0;
end = strlen(str)-1; //字符数组小标从0开始,所以-1
while(start < end)
{
tmp = str[start];
str[start] = str[end];
str[end] = tmp;
start++;
end--;
}
}
int main()
{
char str[100] = {0};
printf("请输入一个字符串:>");
scanf("%s", str);
printf("原始字符串为:> %s\n", str);
ReverseString(str);
printf("反序字符串为:> %s\n", str);
return 0;
}
- 写一个函数,将两个字符串连接
利用一个临时数组,空间要保证能够容纳两个字符串,先把第一个字符串进行拷贝到临时数组,第二个字符串在临时数组的尾部接着链接,最后记得加上字符串的结束标记\0即可
#include<stdio.h>
void ConcatStr(char string1[], char string2[], char string[])
{
int i, j;
for (i = 0; string1[i] != '\0'; i++)
string[i] = string1[i];
//找到字符串末尾,继续往后面链接字符串
for (j = 0; string2[j] != '\0'; j++)
string[i + j] = string2[j];
//字符串末尾加上结束符 \0
string[i + j] = '\0';
}
int main()
{
char s1[200] = {0}, s2[100]= {0}, s[100] = {0};
printf("input string1:");
scanf("%s", s1);
printf("input string2:");
scanf("%s", s2);
ConcatStr(s1, s2, s);
printf("\nThe new string is %s\n", s);
return 0;
}