C语言-函数、递归、数组上的一些细节

函数链式访问:

一.strlen()

int main() {
	int len = strlen("anocineoc");
	printf("%d\n", len);

	//链式访问
	printf("%d\n", strlen("anocineoc"));
    
    return 0;
}

image-20230319113555744


二.printf()

printf("%d", printf("%d", printf("%d", 43)));

image-20230319113850120

image-20230319114128827
printf返回值是int类型

image-20230319114356570

返回的值是里面元素的个数


函数先声明再调用

//先声明函数
int Add(int x, int y);
//
int main()
{
	int a = 10;
	int b = 20;
	int sum = Add(a, b);
	printf("sum = %d\n", sum);
	return 0;
}

//函数的定义
int Add(int x, int y)
{
	return x + y;
}
注意:
int Add(int x, int y);

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

ctrl+F7(编译)不会出错,因为没有链接过程

image-20230319121007591

ctrl+F5(编译+链接)会报错,因为链接会去找这个函数存在不存在,不存在所以报错

image-20230319121359952

在项目里写函数应该写到头文件中

image-20230319120416340

引头文件,相当于把头文件中的函数声明全部拷贝过来

add.h
int Add(int x, int y);
add.c
#include "add.h"

int Add(int x, int y) {
	return x + y;

}
test.c
#include "add.h"
int main()
{
	int a = 10;
	int b = 20;
	int sum = Add(a, b);
	printf("sum = %d\n", sum);
	return 0;
}

四.开源项目但不想让别人知道函数细节

把自己写的函数的.c和.h文件单独存放在一个项目中,然后如下图生成.lib文件,ctrl+F5生成.lb文件。就可以把.lib文件和.h文件(函数声明)开源给别人。

image-20230319144313633

把.lib和.h文件放在和源文件(即.c文件的目录)的目录下

image-20230319145402173

image-20230319145702243

#include "add.h"
//导入静态库
#pragma comment(lib, "add.lib")
int main()
{
	int a = 10;
	int b = 20;
	int sum = Add(a, b);
	printf("sum = %d\n", sum);
	return 0;
}

即可正常运行

递归

一.最简单的递归

int main() {
	printf("hehe\n");
	main();
	return 0;
}

每一次函数调用都要在栈区上开辟一块空间。

二.输入一个整数,按顺序打印它的每一位。输入1234,输出1 2 3 4.

void print(int n)//
{
	if (n > 9)
	{
		print(n / 10);//
	}
	printf("%d ", n % 10);
}

int main()
{
	int num = 0;
	scanf("%d", &num);//1234
	//打印num的每一位
	//1 2 3 4
	print(num);//print函数就可以把num的每一位打印在屏幕上
	//
	//要想打印print(1234)
	//先打印print(123) 再打印4
	//先打印print(12) 再打印3 4
	//先打印print(1) 再打印2 3 4
	//1 2 3 4
	//
	return 0;
}

三.编写函数不允许创建临时变量,求字符串长度

//计数器的方式1
int my_strlen1(char* str)
{
	int count = 0;
	while (*str != '\0')
	{
		count++;
		str++;
	}
	return count;
}

//my_strlen("abcdef")
//1+my_strlen("bcdef")
//1+1+my_strlen("cdef")
//1+1+1+my_strlen("def")
//1+1+1+1+my_strlen("ef")
//1+1+1+1+1+my_strlen("f")
//1+1+1+1+1+1+my_strlen("")
//1+1+1+1+1+1+0
//6


 //递归的方式
int my_strlen2(char* str)
{
	if (*str != '\0')
		return 1 + my_strlen2(str + 1);
	else
		return 0;
}

int main()
{
	char arr[] = "abc";
	//数组名是首元素的地址 - char*
	int len = my_strlen2(arr);
	printf("%d\n", len);

	return 0;
}


四.求n的阶乘

int Fac(int n)
{
	if (n <= 1)
		return 1;
	else
		return n*Fac(n - 1);
}

int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = Fac(n);

	printf("%d\n", ret);
	return 0;
}

五.求第n个斐波那契数

1 1 2 3 5 8 13 21 34 55

int Fib(int n)
{
	
	if (n <= 2)
		return 1;
	else
		return Fib(n - 1) + Fib(n - 2);
}

int main()
{
	int n = 0;
	
	scanf("%d", &n);
	int ret = Fib(n);
	printf("%d\n", ret);

	return 0;
}

效率非常低,当输入为50时,就已经比较难计算了

计算一下n==3出现的次数

int count = 0;

int Fib(int n)
{
	if (n == 3) {
		count++;
	}
	if (n <= 2)
		return 1;
	else
		return Fib(n - 1) + Fib(n - 2);
}

int main()
{
	int n = 0;
	
	scanf("%d", &n);
	int ret = Fib(n);
	printf("%d\n", count);

	return 0;
}

image-20230319161109213

可见递归效率非常低

计算第n个斐波那契的另一种方法:

int Fib(int n)
{
	int a = 1;
	int b = 1;
	int c = 1;

	while (n>2)
	{
		c = a + b;
		a = b;
		b = c;
		n--;
	}
	return c;
}

int main()
{
	int n = 0;
	
	scanf("%d", &n);
	int ret = Fib(n);
	printf("%d\n", ret);

	return 0;
}

数组

int main()
{
	int n = 10;
	int arr[n];//变长数组-C99标准中引入的。VS2013对C99的支持不好。

	return 0;
}

会报错
请添加图片描述

一.初始化

未初始化:
int main() {
	int arr[10];

	return 0;
}

image-20230319162903049

所以创建数组后一定要初始化。

初始化的各种情况:
int main()
{
	//初始化
	int arr[10] = {1};//不完全初始化
	int arr2[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int arr3[10] = {0};
	int arr4[] = { 0 };//
	char ch[10] = { 0 };
	char ch2[10] = {'1', 'b', 'c'};
	char ch3[] = "abc";

	return 0;
}

image-20230319163440809

image-20230319163502464

image-20230319163525886

image-20230319163554109

因为没说是几个元素,所以自动根据{ }里来创建几个元素

image-20230319163655090

image-20230319163714465

image-20230319163730399

image-20230319163949974

这个没有’\0’

int main()
{
	char arr1[] = "abc";
	char arr2[] = { 'a', 'b', 'c'};
    //因为后面没有'\0'所以会一直打印
	char arr3[] = { 'a', 'b', 'c', 0 };

	printf("%s\n", arr1);
	printf("%s\n", arr2);
	printf("%s\n", arr3);
	printf("%d\n", strlen(arr1));
	printf("%d\n", strlen(arr2));
	printf("%d\n", strlen(arr3));
	return 0;
}

image-20230319164556678

字符数组及其定义和初始化,C语言字符数组详解 (biancheng.net)

C语言中 在什么情况下声明数组时可以不指出数组长度?

带有初始化器的定义,此时数组大小可由初始化器长度推出:int a[] = {1};char a[] = "a";

二.数组在内存中的情况

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("&arr[%d] = %p\n", i, &arr[i]);
	}

	return 0;
}

image-20230319165824820


int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	int* p = arr;//数组名-数组首元素的地址

	for (i = 0; i < sz; i++)
	{
		printf("&arr[%d] = %p <=======> %p\n", i, &arr[i], p+i);
		//p+i -- 是数组arr中下标为i的元素的地址
	}
	return 0;
}

image-20230319170203991

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	int* p = arr;//数组名-数组首元素的地址
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	for ( i = 0; i < sz; i++)
	{
		printf("%d ", *(p + i));//使用指针p,来访问了数组
	}
	return 0;
}

image-20230319170514985

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值