IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> C语言核心点(1) -> 正文阅读

[数据结构与算法]C语言核心点(1)

1 函数

1.1 定义函数

每个 C 程序都至少有一个函数,即主函数 main() ,所有简单的程序都可以定义其他额外的函数。

1.2 函数声明

函数声明会告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。

```c
//以下两种都可以,参数名称不重要,参数类型很重要
int max(int num1, int num2);
int max(int, int);
```

1.3 函数参数

如果函数要使用参数,则必须声明接受参数值的变量。这些变量称为函数的形式参数
当调用函数时,有两种向函数传递参数的方式:
在这里插入图片描述

1.4 案例

#include<stdio.h>
 
 /* 函数在使用前必须进行函数声明(只定义不使用可以不用声明) */
double getAverage(int arr[], int size);

int main()
{
	int arr[5] ={233,500,5,56,34};
	double avg = getAverage(arr,5); 
	//整数输出为%d 浮点数输出为%f 
	printf("平均数为%f",avg);
}

double getAverage(int arr[],int size){
	int i;
	double avg = 0;
	double sum =0;
	for(i=0;i<size;i++){
		sum += arr[i];
	}
	printf("和为%f",sum);
	avg = sum/size;
	
	return avg;
}

或者
#include<stdio.h>

double getAvg(int arr[],int size);

int main(){
	
	int arr[] = {7,7,7,7,7,7};
	printf("数组的平均值为%f \n",getAvg(arr,sizeof(arr)/sizeof(arr[0])));
	
}
 
 double getAvg(int arr[4],int size){
 	int sum =0;
 	int i=0;
 	for(i=0;i<size;i++){
	 	sum+=arr[i];
	 }
	 printf("数组总和为sum=%d \n",sum);
	 return sum/size;
 }


2. 循环和数组

2.1 数组的定义

double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};
double balance[] = {1000.0, 2.0, 3.4, 7.0, 50.0};
上述都是正确的。

案例

#include<stdio.h>
 int main()
{
    int n[10];
    int i;
    int j;
    for(i=0;i<10;i++){
    	n[i]=i+100;
    }
    //获取数组长度  sizeof(n)/sizeof(n[0]) 数组字节总长度/一个字节长度
    //循环变量定义在外面定义 
    for(j=0;j<sizeof(n)/sizeof(n[0]);j++){
    	
    	printf("打印数组为%d",n[j]);
    	printf("\n");
    }
    return 0;
}

注意输出:
在这里插入图片描述

注意点:

  • 数组长度获取: sizeof(n)/sizeof(n[0]),含义是数组字节总长度/一个字节长度,该方式不能用于函数形参数组。
  • 数组的循环变量定义要在外面进行定义。

2.2 传递数组给函数

方式 1
形式参数是一个指针。


void myFunction(int *param)
{
.
.
.
}

方式 2
形式参数是一个已定义大小的数组。

void myFunction(int param[10])
{
.
.
.
}

方式 3
形式参数是一个未定义大小的数组。

void myFunction(int param[])
{
.
.
.
}

2.3 从函数返回数组

C 语言不允许返回一个完整的数组作为函数的参数。但是,您可以通过指定不带索引的数组名来返回一个指向数组的指针。
如果您想要从函数返回一个一维数组,您必须声明一个返回指针的函数,如下:

int * myFunction()
{
.
.
.
}

另外,C 不支持在函数外返回局部变量的地址,除非定义局部变量为 static 变量。

#include<stdio.h>
#include<stdlib.h> 
#include<time.h>

int * getRandom(){
	
	static int r[10];
	int i;
 /* 设置种子 */
  srand( (unsigned)time( NULL ) );
	for(i=0;i<10;i++){
		
		r[i] = rand();
		printf("r[%d] = %d \n",i,r[i]);
	}
	return r;
}

//生成 10 个随机数,并使用数组来返回它们
int main(){
	
	int *p;
	int i;
	p = getRandom();
	
	for(i=0;i<10;i++){
		printf("*(p+%d) = %d \n",i,*(p+i));	
	}
	
	return 0;	
}

2.4 指向数组的指针

double *p;
double balance[10];
//指针指向数组第一个元素的地址
p = balance;

#include<stdio.h>

int main()
{
	double arr[5] ={1,2,3,4,5};
	double *p;
	int i;
	
	//让指针p指向数组的第一个元素 
	p = arr;
	
	//指针的值是数组一个元素的地址, 
	printf("打印出指针p的值= %p,指针p所指向数组元素的值=%f\n",p,*p); 
	printf("使用指针打印出数组值\n"); 
	
	for(i=0;i<5;i++){
		
		//因为数组是连续的 所以刚开始指针指向数组第一个元素,当给指针加1,指针就会后移 
		// 要注意的是这里的加1,并不是真正意义上的数字1 而是一个字符,具体长度由元素类型决定
		printf("*(p+%d): %f\n",i,*(p+i));
	}
	
	printf("使用arr作为地址打印出数组值\n"); 
	for(i=0;i<5;i++){
		
		printf("*(arr+%d): %f\n",i,*(arr+i));
	} 
}

输出结果

打印出指针p的值= 0060FEF0,指针p所指向数组元素的值=1.000000
使用指针打印出数组值
*(p+0): 1.000000
*(p+1): 2.000000
*(p+2): 3.000000
*(p+3): 4.000000
*(p+4): 5.000000
使用arr作为地址打印出数组值
*(arr+0): 1.000000
*(arr+1): 2.000000
*(arr+2): 3.000000
*(arr+3): 4.000000
*(arr+4): 5.000000
请按任意键继续. . .

3. 枚举的使用

3.1 枚举的定义

语法:

enum 枚举名 {枚举元素1,枚举元素2,……};

方式1:
先定义枚举类型,再定义枚举变量

enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
};
enum DAY day;

方式2:
定义枚举类型的同时定义枚举变量

enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;

方式3:
省略枚举名称,直接定义枚举变量

enum
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;

案例

#include<stdio.h>
 enum DAY {
 	MON=1, TUE, WED, THU, FRI, SAT, SUN
 };
 
int main()
{
	enum DAY day =WED;
	printf("输出星期%d",day);
}

#include <stdio.h> 
enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;
int main()
{
    // 遍历枚举元素
    for (day = MON; day <= SUN; day++) {
        printf("枚举元素:%d \n", day);
    }
}

枚举在 switch 中的使用:

#include <stdio.h>
#include <stdlib.h>
int main()
{
 
    enum color { red=1, green, blue };
 
    enum  color favorite_color;
 
    /* 用户输入数字来选择颜色 */
    printf("请输入你喜欢的颜色: (1. red, 2. green, 3. blue): ");
    scanf("%u", &favorite_color);
 
    /* 输出结果 */
    switch (favorite_color)
    {
    case red:
        printf("你喜欢的颜色是红色");
        break;
    case green:
        printf("你喜欢的颜色是绿色");
        break;
    case blue:
        printf("你喜欢的颜色是蓝色");
        break;
    default:
        printf("你没有选择你喜欢的颜色");
    }
 
    return 0;
}

4. 指针

4.1 指针的定义


#include <stdio.h>
 
int main ()
{
    int var_runoob = 10;
    int *p;              // 定义指针变量
    p = &var_runoob;
 
   printf("var_runoob 变量的地址: %p\n", p);
   return 0;
}

表示定义一个P指针,指向变量var_runoob,它的值是var_runoob的地址。
在这里插入图片描述

4.2 指针的使用

使用指针时会频繁进行以下几个操作:定义一个指针变量、把变量地址赋值给指针、访问指针变量中可用地址的值。这些是通过使用一元运算符 * 来返回位于操作数所指定地址的变量的值
下面的实例涉及到了这些操作:


#include <stdio.h>
 
int main ()
{
   int  var = 20;   /* 实际变量的声明 */
   int  *ip;        /* 指针变量的声明 */
 
   ip = &var;  /* 在指针变量中存储 var 的地址 */
 
   printf("var 变量的地址: %p\n", &var  );
 
   /* 在指针变量中存储的地址 */
   printf("ip 变量存储的地址: %p\n", ip );
 
   /* 使用指针访问值 */
   printf("*ip 变量的值: %d\n", *ip );
 
   return 0;
}

打印:

var 变量的地址: 0x7ffeeef168d8
ip 变量存储的地址: 0x7ffeeef168d8
*ip 变量的值: 20

5. 指针的算术运算

  1. 指针的每一次递增,它其实会指向下一个元素的存储单元。
  2. 指针的每一次递减,它都会指向前一个元素的存储单元。
  3. 指针在递增和递减时跳跃的字节数取决于指针所指向变量数据类型长度,比如 int 就是 4 个字节。

5.1 递增一个指针

#include<stdio.h>
const int MAX = 3;
int main()
{
	int var[] = {110,122,300};
	int i, *pr;
		
	pr = var;//等价于pr = &var 只有当指向数组的时候才这样写,指向数组也就是指向数组第一个元素
	
	for(i =0;i<MAX;i++){
		printf(" var[%d]的存储地址=%p",i,pr+i);
		printf(" var[%d]的存储值=%d\n",i,*(pr+i));	
//		或者如下写法
		/* 指向下一个位置 */
//     	ptr++;
	}
}

输出结果:

 var[0]的存储地址=0060FF00 var[0]的存储值=110
 var[1]的存储地址=0060FF04 var[1]的存储值=122
 var[2]的存储地址=0060FF08 var[2]的存储值=300
请按任意键继续. . .

5.2 递减一个指针

#include <stdio.h>
 
const int MAX = 3;
 
int main ()
{
   int  var[] = {10, 100, 200};
   int  i, *ptr;
 
   /* 指针中最后一个元素的地址 */
   ptr = &var[MAX-1];
   for ( i = MAX-1; i >= 0; i--)
   {
 
      printf(" 存储地址:var[%d] = %p", i, ptr );
      printf(" 存储值:var[%d] = %d\n", i, *ptr );
 
      /* 指向下一个位置 */
      ptr--;
   }
   return 0;
}

5.3 指针的比较

指针可以用关系运算符进行比较,如 ==、< 和 >。如果 p1 和 p2 指向两个相关的变量,比如同一个数组中的不同元素,则可对 p1 和 p2 进行大小比较。

#include <stdio.h>
 
const int MAX = 3;
 
int main ()
{
   int  var[] = {10, 100, 200};
   int  i, *ptr;
 
   /* 指针中第一个元素的地址 */
   ptr = var;
   i = 0;
   while ( ptr <= &var[MAX - 1] )
   {
      printf("存储地址:var[%d] = %p\n", i, ptr );
      printf("存储值:var[%d] = %d\n", i, *ptr );
 
      /* 指向上一个位置 */
      ptr++;
      i++;
   }
   return 0;
}

5.4 指针数组

#include <stdio.h>
 
const int MAX = 3;
 
int main ()
{
   int  var[] = {10, 100, 200};
   int  i, *ptr[MAX];
 
  for(i=0;i<MAX;i++){
  	
 	ptr[i] = &var[i];
  }
 for(i=0;i<MAX;i++){
 	
 	printf(" 存储地址:var[%d] = %p", i, ptr[i] );
    printf(" 存储值:var[%d] = %d\n", i, *ptr[i] );
 }

   return 0;
}

输出结果:

 存储地址:var[0] = 0060FF00 存储值:var[0] = 10
 存储地址:var[1] = 0060FF04 存储值:var[1] = 100
 存储地址:var[2] = 0060FF08 存储值:var[2] = 200
请按任意键继续. . .

也可以用一个指向字符的指针数组来存储一个字符串列表:

#include <stdio.h>
 
const int MAX = 4;
 
int main ()
{
	//注意:严格上来说C语言没有字符串变量,只有字符数组 
   const char *names[] = {
                   "Zara Ali",
                   "Hina Ali",
                   "Nuha Ali",
                   "Sara Ali",
   };
   int i = 0;
 
   for ( i = 0; i < MAX; i++)
   {
   		//names[i]前面没有*
      printf("Value of names[%d] = %s\n", i, names[i] );
   }
   return 0;
}

输出结果:

Value of names[0] = Zara Ali
Value of names[1] = Hina Ali
Value of names[2] = Nuha Ali
Value of names[3] = Sara Ali
请按任意键继续. . .

5.5 指向指针的指针

指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链。通常,一个指针包含一个变量的地址。当我们定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置。

int **var;

也就是说 指针的指针存放的时候上一个指针的地址。

#include <stdio.h>
 
int main ()
{
   int  V;
   int  *Pt1;
   int  **Pt2;
 
   V = 100;
 
   /* 获取 V 的地址 */
   Pt1 = &V;
 
   /* 使用运算符 & 获取 Pt1 的地址 */
   Pt2 = &Pt1;
 
   /* 使用 pptr 获取值 */
   printf("var = %d\n", V );
   printf("Pt1 = %p\n", Pt1 );
   printf("*Pt1指针所指向的值 = %d\n", *Pt1 );
    printf("Pt2的值 = %p\n", Pt2 );
   printf("**Pt2指针所指向的指针所指向的值 = %d\n", **Pt2);
 
   return 0;
}

输出结果:

var = 100
Pt1 = 0060FF24
*Pt1指针所指向的值 = 100
Pt2的值 = 0060FF20
**Pt2指针所指向的指针所指向的值 = 100
请按任意键继续. . .

5.6 传递指针给函数

#include <stdio.h>
 
void getSecond(long *par); 
int main ()
{
   long sec = 0;
   
   getSecond(&sec);
   
   printf("实际输出值%ld\n",sec);
}

// 在定义指针的时候带的星号表示该变量是指针变量 long *par 给 
//在访问该指针指向的值得时候用 *par
//给指针变量赋值的时候用&sec 表示把sec变量的地址赋给指针变量*sec 
void getSecond(long *par){
	
	*par = time(NULL);
}

输出结果:

实际输出值1632731782
请按任意键继续. . .

这是因为传过去的是地址,在方法中修改是同一份变量。

5.7 数组参数

#include <stdio.h>
 
/* 函数声明 */
double getAverage(int *arr, int size);

int main ()
{
   int balance[5] = {100,200,300,400,500};
   double avg;
   avg = getAverage(balance,5); 
   printf("平均数为%f\n",avg);
}

double getAverage(int *arr, int size){
	
	int total = 0;
	int i;
	for(i=0;i<size;i++){
		
		total+=*(arr+i);
	}
	return total/size;
}

输出结果为:

平均数为300.000000
请按任意键继续. . .

5.8 从函数返回指针

#include <stdio.h>
#include <time.h>
#include <stdlib.h> 

int * getRandom(){
	static int r[10];
	int i;
   /* 设置种子 */
   srand( (unsigned)time( NULL ) );
	for(i=0;i<10;i++){
		r[i] = rand();
		printf("随机生成的数[%d]=%d\n",i,r[i]);
	}
	return r;	
}

int main ()
{
	int *r;
	int i;
	r = getRandom();
	printf("==================================\n");
	for(i=0;i<10;i++){
		printf("数组元素值[%d] = %d\n",i,*(r+i));
	}
}

输出结果:

随机生成的数[0]=14920
随机生成的数[1]=19019
随机生成的数[2]=8311
随机生成的数[3]=18053
随机生成的数[4]=26906
随机生成的数[5]=22482
随机生成的数[6]=2612
随机生成的数[7]=12707
随机生成的数[8]=4356
随机生成的数[9]=32132
==================================
数组元素值[0] = 14920
数组元素值[1] = 19019
数组元素值[2] = 8311
数组元素值[3] = 18053
数组元素值[4] = 26906
数组元素值[5] = 22482
数组元素值[6] = 2612
数组元素值[7] = 12707
数组元素值[8] = 4356
数组元素值[9] = 32132
请按任意键继续. . .
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-03-08 22:48:16  更:2022-03-08 22:51:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 13:55:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码