L1D8 C语言函数(一)

函数(一)

函数就是一个能完成特定功能的模块,其程序代码独立,可以给函数传递参数,也可以得到返回值。函数的实现人员把函数设计成一个黑盒子,隐藏了实现细节,并对外部提供尽可能简单的接口。对此对于函数调用方来说,无需知道函数的内部工作原理,仅需知道功能、参数、返回值即可。

一 函数定义和声明

1.1函数定义

函数是一个完成特定功能的代码模块,其程序代码独立,通常要求有返回值,也可以是空值。一般形式如下:

/* <数据类型>  <函数名称>( <形式参数说明> ) 
{
	语句序列;             
	return[(<表达式>)]; 
} 
} 
<数据类型>是整个函数的返回值类型。return[(<表达式>)]语句中表达式的值,
要和函数的<数据类型>保持一致。如无返回值应该写为void型。
*/
/*例如*/
int function(int a , int b)
{
	int c;
	c = a + b;
	return c;
}

1.2函数声明

函数的说明就是指函数原型 其中,<形式参数说明>可以缺省说明的变量名称,但类型不能缺省.
例如, double Power(double x, int n) ; double Power(double, int);

二 函数的调用、参数传递

2.1 函数的调用

函数的使用也叫函数的调用,形式如下: 函数名称(〈实际参数〉)
实参就是在使用函数时,调用函数传递给被调用函数的数据。需要确切的数据
函数调用可以作为一个运算量出现在表达式中,也可以单独形成一个语句。对于无返回值的函数来讲,只能形成一个函数调用语句。

tips:实参和形参的区别?
形参指的是出现在函数定义中的参数列表。实参指的是函数调用时,里面的参数。如下例程所示,函数定义中,a,b为形参,函数在main中调用时,m,n为实参。整个程序运行过程中,是将实参m、n的数据传递到开辟的形参a、b中,实现整个程序的功能。

int function(int a , int b)
{
	return a + b;
}
int main(int argc , char **aggv)
{
	int m = 10 , n = 20;
	int c = 0;
	c = function(m , n);
}

2.2 函数的参数传递(重点)

函数之间的参数传递方式:
全局变量、复制传递方式、地址传递方式
1、全局变量传递
全局变量就是在函数体外说明的变量,它们在程序中的每个函数里都是可见的,全局变量一经定义后就会在程序的任何地方可见。函数调用的位置不同,程序的执行结果可能会受到影响。不建议使用
使用代码示例如下:

#include <stdio.h>

int n;
double factorial();

int main(int argc, char const *argv[])
{
    double s = 0;
    printf("input:");
    scanf("%d", &n);

    s = factorial();
    printf("%e\n", s);

    return 0;
}

double factorial()
{
    double ret = 1;
    int i;
    for (i = 1; i < n; i++)
        ret *= i;
    return ret;
}

在这里插入图片描述

2、复制传递方式(值传递)
调用函数将实参传递给被调用函数,被调用函数将创建同类型的形参并用实参初始化。形参是新开辟的存储空间,因此,在函数中改变形参的值,不会影响到实参。如下程序所示:

#include <stdio.h>
void rev(int a , int b)
{
	int t = 0;
    t = a;
    a = b;
    b = t;
    printf("a= %d , b= %d\n", a, b);
    printf("a addr:%p , b addr:%p\n",&a,&b);
}
int main(int argc , char **aggv)
{
	int m = 10 , n = 20;
	rev(m , n);
    printf("m = %d, n = %d\n", m, n);
    printf("m addr:%p , n addr:%p\n",&m,&n);
}

此代码中,目的是实现数据的交换功能,但是打印结果却不符合需求(俩数交换),就是我们提到的“在函数中改变形参的值,不会影响到实参”;
在这里插入图片描述

形参和实参的特点:
①、形参只有在函数被调用时才会分配内存空间(在栈上),在调用结束后,释放分配的内存空间。因此形参只在函数内部有效。
②、实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,进行函数调用时,必须具有特定的值,以便把这些值传给形参。
③、形参和实参在数量上、类型上、顺序上应该严格一致,否则发送“类型匹配错误”。

3、地址传递方式
按地址传递,实参为变量的地址,而形参为同类型的指针。
被调用函数中对形参的操作,将直接改变实参的值(被调用函数对指针的目标操作,相当于对实参本身的操作)。

#include <stdio.h>
void rev(int *a , int *b)
{
	int t = 0;
    t = *a;
    *a = *b;
    *b = t;
    printf("*a= %d , *b= %d\n", *a, *b);
    printf("a addr:%p , b addr:%p\n",&a,&b);
}
int main(int argc , char **aggv)
{
	int m = 10 , n = 20;
	rev(&m , &n);
    printf("m = %d, n = %d\n", m, n);
    printf("m addr:%p , n addr:%p\n",&m,&n);
}

在这里插入图片描述

如果只是实现功能,不改变目标,可以使用值传递。如果要改变目标(实参),比如实现交换,小写转大写等,让目标值(实参)发生变化,就要用地址传递。

三 函数和数组

3.1 传递数组

当形参是数组形式时,其本质也是一个指针。数组作为实参传递时,形参并没有复制形参所有的内容,而是复制了实参数组的首地址。
由于数组的特殊性,只要知道了数组的首地址,就可以依次访问数组中所有元素。
示例程序如下(计算数组所有元素和及数组中奇数个数):

#include <stdio.h>

int test_array(int a[] , int n , int *p)
{
    int i = 0, sum = 0;
    *p = 0;
    for (i = 0; i < n; i++)
    {
        sum += a[i];
        if(a[i]%2)
            (*p)++;
    }
    return sum;
}

int main(int argc, char **argv)
{
    int a[] = { 9 , 12 , 2 , 3 , 29 , 31 , 40 , 80}, n = 0;
    int sum = 0 , odd = 0;
    n = sizeof(a)/sizeof(int);
    sum = test_array(a,n,&odd);
    printf("sum = %d odd numbers count = %d\n",sum,odd);
    return 0;
}

在这里插入图片描述

3.2 传递指针

#include <stdio.h>

int test_array(int *a , int n , int *p)
{
    int i = 0, sum = 0;
    *p = 0;
    for (i = 0; i < n; i++)
    {
        sum += *(a+i);
        if(*(a+i)%2)
            (*p)++;
    }
    return sum;
}

int main(int argc, char **argv)
{
    int a[] = { 9 , 12 , 2 , 3 , 29 , 31 , 40 , 80}, n = 0;
    int sum = 0 , odd = 0;
    n = sizeof(a)/sizeof(int);
    sum = test_array(a,n,&odd);
    printf("sum = %d odd numbers count = %d\n",sum,odd);
    return 0;
}

在这里插入图片描述

3.3 main函数参数

形式:int main(int argc, char **argv)
参数说明:argc是给main传递的参数个数 , argv是具体的参数集合。
示例如下:

#include <stdio.h>

int main(int argc, char const *argv[])
{
    int i = 0;
    printf("argc = %d\n" , argc);
    for (i = 0; i < argc ; i ++)
        printf("argv[%d] = %s\n", i, argv[i]);
    return 0;
}

在这里插入图片描述

四 综合练习

1、实现求x的n次方的函数
答:

#include <stdio.h>

float my_pow(float a,int n);

int main(int argc,char *argv[])
{
	float a = 2;
	float sum = 0;
	int n = 10;
	puts("please input a:");
	scanf("%f",&a);
	puts("please input n:");
	scanf("%d",&n);
	sum = my_pow(a,n);
	printf("%f\r\n",sum);
	return 0;
}

float my_pow(float a,int n)
{
	int i = 0;
	float sum = 1;
	for(i = 0;i<n;i++)
	{
		sum = sum*a;
	}
	return sum;
}

2、编写一个函数,统计字符串中小写字母的个数,并把字符串中的小写字母转化成大写字母,并输出转换后的字符串及小写字母个数。

#include <stdio.h>
#include <ctype.h>

int my_str1tostr2(char *str);

int main(int argc,char *argv[])
{
	char str[100] = {0};
	char *p = str;
	int num = 0;
	puts("please input a str:");
	gets(p);
	num = my_str1tostr2(p);
	printf("%s  %d\r\n",p,num);
	return 0;
}
int my_str1tostr2(char *str)
{
	int num = 0;
	while(*str != '\0')
	{
		if(islower(*str))
		{
			num++;
			*str = toupper(*str);
		}
		str++;
	}
	return num;
}

3、编写函数,计算一个一维整型数组的所有元素之和。
答:

/*
 * @Description: 
 * @Author: 余红祥
 * @Date: 2022-03-26 19:32:56
 * @LastEditTime: 2022-07-04 22:23:30
 * @LastEditors:  
 */
#include <stdio.h>
int sum_array(int *str,int n);

int main(int argc,char *argv[])
{
	int a[10] = {0};
	int sum = 0,i = 0;
	int *p = a;
	for(i = 0;i < 10;i++)
	{
		scanf("%d",p+i);
	}
	p = a;
	sum = sum_array(p,10);
	printf("%d\r\n",sum);
	return 0;
}

int sum_array(int *str,int n)
{
	int sum = 0;
	int i = 0;
	while(i<n)
	{
		sum += *(str+i);
		//str++;
		i++;
	}
	return sum;
}

4、 编程实例:编写函数,删除字符串中的空格。
答:

#include <stdio.h>
void del_sapce(char *s1);

int main(int argc,char *argv[])
{
	char s[] = "   a   b   s   h";
	puts(s);
	del_space(s);
	
	puts(s);
	return 0;
}

void del_space(char *s1)
{
	char *s2 = s1;
	while(*s1 != '\0')
	{
		if(*s1 == ' ')
		{
			s1++;
		}
		else
		{
			*s2 = *s1;
			s1++;
			s2++;
		}
	}
	*s2 = '\0';
}

5、利用函数,实现strlen函数的功能。
答:

#include <stdio.h>

int my_strlen(const char *str);

int main(int argc ,char *arrgv[])
{
	char str[100] = {0};
	char *p = str;
	int length = 0;
	puts("please input a str :");
	gets(p);
	length = my_strlen(p);
	printf("the str length is: %d\n",length);
	return 0;
}

//确定指针目标的值在这里不需要修改,尝试使用const修饰符
/*function:求字符串长度
*argument:str:需要获取长度的字符串
*return:n:返回值为长度*/
int my_strlen(const char *str)
{
	int n = 0;
	while(*str++ != '\0')
		n++;
	return n;
}

ps:欢迎大佬指正,共同学习进步。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 下面是一个用 C 语言编写的快速傅立叶变换(FFT)函数:void fft(int dir,long m,double *x,double *y) { long n,i,i1,j,k,i2,l,l1,l2; double c1,c2,tx,ty,t1,t2,u1,u2,z; /* Calculate the number of points */ n = 1; for (i=0;i<m;i++) n *= 2; /* Do the bit reversal */ i2 = n >> 1; j = 0; for (i=0;i<n-1;i++) { if (i < j) { tx = x[i]; ty = y[i]; x[i] = x[j]; y[i] = y[j]; x[j] = tx; y[j] = ty; } k = i2; while (k <= j) { j -= k; k >>= 1; } j += k; } /* Compute the FFT */ c1 = -1.0; c2 = 0.0; l2 = 1; for (l=0;l<m;l++) { l1 = l2; l2 <<= 1; u1 = 1.0; u2 = 0.0; for (j=0;j<l1;j++) { for (i=j;i<n;i+=l2) { i1 = i + l1; t1 = u1 * x[i1] - u2 * y[i1]; t2 = u1 * y[i1] + u2 * x[i1]; x[i1] = x[i] - t1; y[i1] = y[i] - t2; x[i] += t1; y[i] += t2; } z = u1 * c1 - u2 * c2; u2 = u1 * c2 + u2 * c1; u1 = z; } c2 = sqrt((1.0 - c1) / 2.0); if (dir == 1) c2 = -c2; c1 = sqrt((1.0 + c1) / 2.0); } /* Scaling for forward transform */ if (dir == 1) { for (i=0;i<n;i++) { x[i] /= n; y[i] /= n; } } } ### 回答2: 以下是一个用C语言编写的FFT(快速傅里叶变换)函数的示例: ```c #include <stdio.h> #include <complex.h> #include <math.h> #define PI 3.14159265 void fft(complex double x[], int size) { if (size <= 1) { return; } complex double even[size / 2]; complex double odd[size / 2]; for (int i = 0; i < size / 2; i++) { even[i] = x[2 * i]; odd[i] = x[2 * i + 1]; } fft(even, size / 2); fft(odd, size / 2); for (int k = 0; k < size / 2; k++) { complex double t = cexp(-I * 2 * PI * k / size) * odd[k]; x[k] = even[k] + t; x[k + size / 2] = even[k] - t; } } int main() { // 示例使用的输入数据 int size = 8; complex double x[] = {1, 2, 3, 4, 5, 6, 7, 8}; // 对输入数据进行快速傅里叶变换 fft(x, size); // 输出结果 printf("FFT结果:"); for (int i = 0; i < size; i++) { printf("%.2f + %.2fi, ", creal(x[i]), cimag(x[i])); } return 0; } ``` 这个FFT函数使用递归的方式实现傅里叶变换,并且根据蝶形算法的原理进行计算。函数的输入参数为一个复数数组x和数组的大小size。函数将输入数组进行原地傅里叶变换,并将结果保存在同一数组x中。在示例代码中,输入的大小为8,并且输入数据为{1, 2, 3, 4, 5, 6, 7, 8}。最后,通过打印结果,可以看到变换后的结果。请注意,这个示例代码只是FFT的一个简单实现,实际的FFT算法可能会有更多的优化和复杂性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值