C 语言-数组

1. 数组

1.1 引入

需求:记录班级10个学员的成绩

需要定义10个变量存在的问题:变量名起名困难变量管理困难

需求:记录班级1000个学员的成绩

1.2 概念

作用:容纳 数据类型相同 的多个数据的容器

特点:

  • 长度不可变
  • 容纳 数据类型相同

名词:

元素:数组中存储的数据
下标:元素在数组中的位置,下标从0开始,长度-1结束
长度:数组中可存储元素个数

注意:

  • 数组中的数据在 内存中是连续存储的。

1.3 分类

  • 安存储的数据类型存储

    字符数组
    整形数组
    浮点型数组
    ...
    
  • 按维度分类

    一维数组
    二维数组
    ...
    

1.4 使用

1.4.1 定义与初始化

① 定义:

语法:

数据类型 数组名[长度] = {值1, 值2, 值3, 值4...};
② 初始化

全部初始化:

此时可省略长度不写

如:

int nums[5] = {1, 3, 5, 7, 9}
//此时可以长度不写
int nums01[] = {1, 3, 5, 7, 9}

部分初始化:

没初始化的部分,值默认为0。

如:

int num02[5] = {1, 3, 5}
③ 字符数组与字符串

比如:

char str01[5] = {'h','e','l','l','o'};char str02[] = "hello";

注意:

  • 字符串 赋值给字符数组 系统将 默认为其在尾部加 \0
  • \0:字符串结束
#include <stdio.h>
int main(int argc, char const *argv[])
{char str01[5] = {'h','e','l','l','o'};char str02[] = "hello";printf("str01大小为:%d\n",sizeof(str01));printf("str02大小为:%d\n",sizeof(str02));return 0;
}// 输出
// str01大小为:5
// str02大小为:6

1.4.2 使用

① 获取指定位置元素

语法:

数组名[下标]

如:

int nums[5] = {1, 3, 5, 7, 9};取出并打印 第4个数printf("%d\n", nums[3]);
取出后赋值给别的变量int x = nums[4];
取出后赋值给数组的其他位置nums[1] = nums[4];
#include <stdio.h>
void fun01()
{int nums[5] = {1,3,5,7,9};printf("nums中下标为4的元素是:%d\n",nums[4]);
}
void fun02()
{int nums[5] = {1,3,5,7,9};int x = nums[4];printf("x=%d\n",x);
}int main(int argc, char const *argv[])
{fun01();fun02();return 0;
}// 输出:
// nums中下标为4的元素是:9
// x=9
② 修改指定位置元素

语法:

数组名[下标] = 值;

如:

int nums[5] = {1,3,5,7,9};
将数组中下标为1的元素修改为33
nums[1] = 33;

例:

#include <stdio.h>void fun03()
{int nums[5] = {1,3,5,7,9};nums[1] = 33;printf("nums修改后下标为1的值是:%d\n",nums[1]);
}int main(int argc, char const *argv[])
{fun03();return 0;
}// 输出:
// nums修改后下标为1的值是:33
③ 计算数组长度

思路:

数组所占字节数大小/单个元素所占大小 = 长度

如:

int nums[] = {1,2,3,4,5,6,7,8,89,9,10,1,21,121,121,21,3,32};
int len = sizeof(nums) / sizeof(nums[0]);
int len = sizeof(nums) / sizeof(int);

例:

#include <stdio.h>void fun04()
{int nums[] = {1,2,3,4,5,6,7,8,89,9,10,1,21,121,121,21,3,32};int len = sizeof(nums) / sizeof(nums[0]);//int len = sizeof(nums) / sizeof(int);printf("数组的长度为:%d\n",len);
}int main(int argc, char const *argv[])
{fun04();return 0;
}// 输出:
// 数组的长度为:18
④ 遍历

含义:将数组中的数据逐个取出

例:

#include <stdio.h>void fun05()
{int nums[] = {1,2,3,4,5,6,7,8,89,9,10,1,21,121,121,21,3,32};//计算数组长度int len = sizeof(nums) / sizeof(nums[0]);//开启循环for(int i = 0; i < len; i++){//取值int x = nums[i];//打印printf("%d,",x);}printf("\n");
}int main(int argc, char const *argv[])
{fun05();return 0;
}// 输出:
// 1,2,3,4,5,6,7,8,89,9,10,1,21,121,121,21,3,32,
⑤ 键盘输入数据存储到数组中

注意:字符串除外

例1:

void fun06()
{char cs[10] = {0};scanf("%c",&cs[0]);printf("%c\n",cs[0]);
}/*
输入: 56
输出: 5
因为%c是char的占位符, 占一个字节
*/

例:

#include <stdio.h>void fun07()
{int nums[5] = {0};for(int i = 0; i < 5; i++){printf("请输入第%d个数",(i+1));scanf("%d",&nums[i]);}for(int i = 0; i < 5; i++){printf("%d,",nums[i]);}printf("\n");
}int main(int argc, char const *argv[])
{fun07();return 0;
}/*
输出:
请输入第1个数12
请输入第2个数23
请输入第3个数12
请输入第4个数23
请输入第5个数25
12,23,12,23,25,
*/
⑥ 字符串录入

scanf

问题:不能录入空格
void fun08()
{char str[50] = {0};//会将空格或回车作为录入结束scanf("%s",str);printf("str=%s\n",str);
}

gets

问题:会出现bug假如没有定义数组长度,会报错
#include <stdio.h>void fun09()
{char str[] = "";gets(str,sizeof(str),stdin);printf("str=%s\n",str);
}int main(int argc, char const *argv[])
{fun09();return 0;
}/*
hello
str=hello
*** stack smashing detected ***: ./a.out terminated
已放弃 (核心已转储)
*/

fgets

最优选择
语法:char *fgets(char *restrict str, int size, FILE *restrict stream))fgets(数组名,sizeof(数组名),stdin);
假如没有定义数组长度,会直接结束。
#include <stdio.h>void fun10()
{char str[50] = "";fgets(str,sizeof(str),stdin);printf("str=%s\n",str);
}int main(int argc, char const *argv[])
{fun10();return 0;
}/*
输出:
hello world
str=hello world*/
⑦ 数组与函数

注意:

  • 数组的本质是一个地址
  • 所以调用函数时传入数组其实传递的是数组名对应的地址
  • 此时当函数中将该数组中的内容修改
  • 那么调用该函数所传递的数组的值也将被修改

如:

#include <stdio.h>
void funA(int a)
{a = 10;
}void funB(int nums[5])
{nums[0] = 10;
}
/*
要求定义一个函数,计算两数之和,要求返回和,加数,被加数*/ 
void add(int a,int b,int nums[3])
{int x = a + b;nums[0] = x;nums[1] = a;nums[2] = b;
}
int main(int argc, char const *argv[])
{int x = 1;funA(x);printf("x= %d\n",x);int xs[5] = {1};funB(xs);printf("xs[0] = %d\n",xs[0]);int adds[3] = {0};add(10,2,adds);for(int i = 0; i < 3; i++){printf("%d\n",adds[i]);}return 0;
}/*
输出:
x= 1
xs[0] = 10
12
10
2
*/

1.5 扩展

因为数组本质是地址,所以 遍历时:nums[i] == *(nums+i)

#include <stdio.h>
int main(int argc, char const *argv[])
{int nums[5] = {2,4,6,8,9};for(int i = 0; i < 5; i++){printf("%d,",nums[i]);// printf("%d,",*(nums+i));}printf("\n");return 0;
}/*
两个打印输出相同,如下:
2,4,6,8,9,
*/

2. 二维数组

2.1 概念

一维数组作为元素存储的数组 。

2.2 使用

2.2.1 定义与初始化

语法:

数据类型 数组名[x][y] = {{值1,值2,值3,...},{值11,值22,值33,...},{值111,值222,值333,...},...
};

x:二维数组中存储的一维数组的个数

y:一维数组中可存储的元素的个数

如:

#include <stdio.h>
int main(int argc, char const *argv[])
{int nums[5][3] = {{1,2,3},{4,5,6},{7,8,9},{10,11,12},{13,14,15}};// 当数组全部初始化时可以省略长度不写// 二维数组的长度是一维数组的个数int nums[][3] = {{1,2,3},{4,5,6},{7,8,9},{10,11,12},{13,14,15}};int nums[3][3] = {{0},{0},{0}};int nums[3][3] = {0};int nums[3][3] = {{1,2,3},{4,5,6},{7,8,9}};int nums01[3][3] = {1,2,3,4,5,6,7,8,9};int nums02[3][3] = {0};return 0;
}

2.2.2 使用

① 取值
获取二维数组中下标为x的一维数组数组名[x]
获取二维数组中下标为x中下标为y的元素数组名[x][y]

例:

#include <stdio.h>
int main(int argc, char const *argv[])
{int nums01[3][3] = {1,2,3,4,5,6,7,8,9};int nums02[3][3] = {0};printf("nums01[0][2] = %d\n",nums01[0][2]);printf("nums02[0][2] = %d\n",nums02[0][2]);char strs[3][50] = {"hello", "world", "boboy"};printf("strs[0] = %s\n",strs[1]);return 0;
}/*
输出:
nums01[0][2] = 3
nums02[0][2] = 0
strs[0] = world
*/
② 赋值
数组名[x][y] = 值;

注意:

因为数组不能修改其指向的地址(因为数组是常指针),所以数组不能重复初始化

所以以下语法是错误的

数组名[x] = 新数组;

常指针:可以修改其指向的内容中的值,但是不能修改其指向的地址

③ 长度
sizeof(数组名) / sizeof(数组中第一个元素) = 长度
④ 遍历

思路:

1,获取二维数组中一维数组的个数,即二维数组的长度,为x
2,获取一维数组中元素的个数,即一维数组的长度,为y
3,开启循环,逐个获取二维数组中的一维数组
4,在循环内遍历获取到的一维数组

例1:

#include <stdio.h>
void fun01()
{int nums[5][3] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};int xlen = sizeof(nums) / sizeof(nums[0]);int ylen = sizeof(nums[0]) / sizeof(nums[0][0]);for(int i = 0; i < xlen; i++){//nums[i]for(int j = 0; j < ylen; j++){int x = nums[i][j];printf("%d,",x);}printf("\n");}
}void fun02()
{char strs[3][5] = {{'a','b','c','d','e'},{'h','e','l','l','o'}};int xlen = sizeof(strs) / sizeof(strs[0]);int ylen = sizeof(strs[0]) / sizeof(strs[0][0]);for(int i = 0; i < xlen; i++){for(int j = 0; j < ylen; j++){printf("%c ",strs[i][j]);            }printf("\n");}
}int main(int argc, char const *argv[])
{fun01();printf("###################\n");fun02();fun03();return 0;
}/*
输出:
1,2,3,
4,5,6,
7,8,9,
10,11,12,
13,14,15,
###################
a b c d e 
h e l l o */

例2:遍历字符串

#include <stdio.h>void fun03()
{char strs[3][6] = {"abcde","hello"};int xlen = sizeof(strs) / sizeof(strs[0]);for(int i = 0; i < xlen; i++){printf("%s",strs[i]);            printf("\n");}
}int main(int argc, char const *argv[])
{fun03();return 0;
}/*
输出:
abcde
hello*/

例3:键盘录入

#include <stdio.h>//键盘录入多个字符串存储到数组中
void fun04()
{char strs[3][128] = {0};for(int i = 0; i < 3; i++){fgets(strs[i],sizeof(strs[i]),stdin);}for(int i = 0; i < 3; i++){printf("%s",strs[i]);}
}
int main(int argc, char const *argv[])
{fun04();return 0;
}/*
输入:
hello
world
tom
输出:
hello
world
tom
*/

3. 算法

软件 = 算法 + 数据结构

算法 = 数学公式使用代码实现

优点:提高代码运行效率

如:

  • 代码
//计算100以内数之和
int sum = 0;
for(int i = 0; i < 100; i++){sum = sum + i;} 
printf("sum=%d\n",sum);分析得知:以上代码共执行了303行
  • 数学
在数学中该问题的公式为: (首项+尾项) * 项数 / 2int sum = (0 + 99) * 100 / 2;
分析得知:以上代码共执行了1行

评判算法是否优良

  • 时间复杂度
  • 空间复杂度

3.1 常用算法

3.1.1 两数交换位置

int a = 1;
int b = 2;
int c = a;
a = b;
b = c;

3.1.2 寻找最值

思路:
1,假设数组中的一个数为最值
2,在使用数组中元素与其一一对比
3,如果取出的元素大于或小于最值,将假设的最值换为改值
4,当对比完成后,假设的最值就是真的最值

代码:

int nums[] = {6,21,33,67,1,29,32,14};
//寻找最小值
int min = nums[0];
for(int i = 0; i < sizeof(nums)/sizeof(nums[0]); i++){if(nums[i] < min){min = nums[i];}
} 
printf("最小值为:%d\n",min);

寻找最值下标

思路:
1,假设数组中的位置上的数为最小值,记录该位置为最值下标
2,在使用数组中元素与下标对应的值一一对比
3,如果取出的元素大于或小于下标对应的值,将假设的下标改为该数的下标
4,当对比完成后,假设的最下标就是最值下标

代码:

int nums[] = {6,21,33,67,1,29,32,14};排序
//寻找最小值下标
int minIndex = 0;
for(int i = 0; i < sizeof(nums)/sizeof(nums[0]); i++){if(nums[i] < nums[minIndex]){minIndex = i;}} 
printf("最小值下标为:%d\n",minIndex);

3.2 排序

目的:将数组中的数据从大到小(降序)或从小到大(升序)排序

3.2.1 冒泡排序

核心思想:相邻比较,交换位置

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
//生成随机数
void setNums(int nums[],int len)
{for(int i = 0; i < len; i++){nums[i] = rand() % 100;}
}
//打印数组中的内容
void printNums(int nums[],int len)
{for(int i = 0; i < len; i++){printf("%d ",nums[i]);}printf("\n");
}void sort01(int nums[],int len)
{//冒泡排序for (int i = 0; i < len - 1; i++){for(int j = 0; j < len-1; j++){if (nums[j] > nums[j+1]){//交换位置int x = nums[j];nums[j] = nums[j+1];nums[j+1] = x;}}}
}
int main(int argc, char const *argv[])
{int nums[10] = {0};srand(time(NULL));int len = sizeof(nums)/ sizeof(nums[0]);setNums(nums,len);printNums(nums,len);sort01(nums,len);printNums(nums,len);return 0;
}
//25 70 74 40 78 42 91 54 50 20 
//20 25 40 42 50 54 70 74 78 91 

3.2.2 选择排序

核心思想:确定位置,与最值,交换位置

在这里插入图片描述

void sort02(int nums[],int len)
{//选择排序,外层循环一次找到一个最值并且放到目标位置for(int j = 0; j < len -1 ; j++){int tagIndex = j;int minIndex = tagIndex;//取值: 目标位置~lenfor(int i = tagIndex; i < len; i++){//寻找最值下标if(nums[minIndex] > nums[i]){minIndex = i;}}//目标位置不等于最值位置,则交换位置if (tagIndex != minIndex){//交换位置,此时最值交换到目标位置int x = nums[tagIndex];nums[tagIndex] = nums[minIndex];nums[minIndex] = x;}}
}
//7 82 4 2 42 19 69 70 19 52 
//2 4 7 19 19 42 52 69 70 82

简化:

void sort02(int nums[],int len)
{for(int j = 0; j < len -1 ; j++){int minIndex = j;for(int i = j; i < len; i++){if(nums[minIndex] > nums[i]){minIndex = i;}}if (j != minIndex){//交换位置int x = nums[j];nums[j] = nums[minIndex];nums[minIndex] = x;}}
}
//7 82 4 2 42 19 69 70 19 52
//2 4 7 19 19 42 52 69 70 82

3.3 查找

目的:查询数组中是否存在指定元素

3.3.1 顺序查找

核心思想:逐个比较

/*定义一个函数查找指定数据是否存在如果存在返回1否则返回0nums:要查找的数组len:数组长度tag:查找的数据
*/
int find01(int nums[],int len,int tag)
{for(int i = 0; i < len; i++){if (nums[i] == tag){return 1;}}return 0;
}/*定义一个函数查找指定数据是否存在如果存在返回下标否则返回-1nums:要查找的数组len:数组长度tag:查找的数据
*/
int find02(int nums[],int len,int tag)
{for(int i = 0; i < len; i++){if (nums[i] == tag){return i;}}return -1;
}

3.3.2 二分查找

要求:查找的数组必须 是有序的

int find03(int nums[],int len,int tag)
{//排序sort01(nums,len);printNums(nums,len);//二分查找法//定义开始和结束下标int start = 0;int end = len - 1;while(start <= end){//中间值下标int center = (start + end) / 2;//等于直接返回if (nums[center] == tag){return center;}else if(nums[center] < tag){start = center + 1;}else{end = center - 1;}}return -1;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/235512.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

finebi 新手入门案例

finebi 新手入门案例 连锁超市销售数据分析 步骤&#xff1a; 准备公共数据新建分析主题处理数据在数据中分析在图形中分析数据大屏 准备公共数据 点击公共数据 点击新建文件夹 修改文件夹名称 上传数据 鼠标悬停在文件夹上&#xff0c;右侧出现 鼠标悬停在文件夹上&#x…

C#图像处理OpenCV开发指南(CVStar,04)——图片像素访问与多种局部放大效果的实现代码

​​​​​​​ 使用本文代码需要预先设置一点开发环境&#xff0c;请阅读另外一篇博文&#xff1a; C#图像处理OpenCV开发指南&#xff08;CVStar&#xff0c;03&#xff09;——基于.NET 6的图像处理桌面程序开发实践第一步https://blog.csdn.net/beijinghorn/article/deta…

CMake 教程:常用命令及其使用方法

CMake是一个跨平台、开源的构建工具&#xff0c;它可以自动生成Makefile或者Visual Studio等IDE的工程文件。它能够帮助开发者更方便地管理项目的构建过程&#xff0c;提高项目构建的效率。在本文中&#xff0c;我们将介绍CMake常用的命令以及对应的用法 add_executable add_e…

sql注入基础篇

sql注入基础 漏洞原理 对用户输入的数据没有做参数校验&#xff0c;sql语句没有做安全处理&#xff0c;导致用户可以通过参数控制sql语句从而查询一些敏感数据&#xff0c;甚至控制对方主机 漏洞利用 前置知识 ​ 1、首先不同的数据库&#xff0c;漏洞注入的方式也不同&#x…

Unity 一些常用注解

在Unity中有一些比较常用的注解&#xff1a; 1、[SerializeField]&#xff1a;将私有字段或属性显示在 Unity 编辑器中&#xff0c;使其可以在 Inspector 窗口中进行编辑。 2、[Range(min, max)]&#xff1a;限制数值字段或属性的范围&#xff0c;在 Inspector 窗口中以滑动条…

Selenium定位元素的方法css和xpath的区别!

selenium是一种自动化测试工具&#xff0c;它可以通过不同的定位方式来识别网页上的元素&#xff0c;如id、name、class、tag、link text、partial link text、css和xpath。 css和xpath是两种常用的定位方式&#xff0c;它们都可以通过元素的属性或者层级关系来定位元素&#…

【CAN通信】CanIf模块详细介绍

目录 1.内容简介 2.CanIf详细设计 2.1 CanIf功能简介 2.2 一些关键概念 2.3依赖的上下层模块 2.4 功能详细设计 2.4.1 Hardware object handles 2.4.2 Static L-PDUs 2.4.3 Dynamic L-PDUs 2.4.4 Dynamic Transmit L-PDUs 2.4.5 Dynamic receive L-PDUs 2.4.6Physi…

第16关 革新云计算:如何利用弹性容器与托管K8S实现极速服务POD扩缩容

------> 课程视频同步分享在今日头条和B站 天下武功&#xff0c;唯快不破&#xff01; 大家好&#xff0c;我是博哥爱运维。这节课给大家讲下云平台的弹性容器实例怎么结合其托管K8S&#xff0c;使用混合服务架构&#xff0c;带来极致扩缩容快感。 下面是全球主流云平台弹…

Hiera实战:使用Hiera实现图像分类任务(一)

文章目录 摘要安装包安装timm 数据增强Cutout和MixupEMA项目结构计算mean和std生成数据集 摘要 现代层次视觉变换器在追求监督分类表现时增加了几个特定于视觉的组件。 这些组件虽然带来了有效的准确性和吸引人的FLOP计数&#xff0c;但增加的复杂性实际上使这些变换器比普通V…

MySQL表的查询、更新、删除

查询 全列查询 指定列查询 查询字段并添加自定义表达式 自定义表达式重命名 查询指定列并去重 select distinct 列名 from 表名 where条件 查询列数据为null的 null与 (空串)是不同的&#xff01; 附&#xff1a;一般null不参与查询。 查询列数据不为null的 查询某列数据指定…

时序预测 | Python实现GA-TCN-LSTM遗传算法-时间卷积神经网络-长短期记忆网络时间序列预测

时序预测 | Python实现GA-TCN-LSTM遗传算法-时间卷积神经网络-长短期记忆网络时间序列预测 目录 时序预测 | Python实现GA-TCN-LSTM遗传算法-时间卷积神经网络-长短期记忆网络时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 使用先进的机器学习技术和优化算法…

【C++】了解模板

这里是目录 前言函数模板函数模板的实例化类模板 前言 如果我们要交换两个数字&#xff0c;那么我们就需要写一个Swap函数来进行交换&#xff0c;那如果我们要交换char类型的数据呢&#xff1f;那又要写一份Swap的函数重载&#xff0c;参数的两个类型是char&#xff0c;那我们…