【C语言督学训练营 第五天】数组字符串相关知识
文章目录
- 前言
- 一、数组的定义
- 1.一维数组
- ①.如何定义
- ②.声明规则
- ③.内存分布
- ④.初始化方法
- 2.二维数组
- 3.高维数组
- 二、访问数组元素相关问题
- 1.访问越界
- 2.数组的传递
- 三、Scanf与字符数组
- 1.字符数组初始化
- 2.scanf读取字符
- 四、字符数组相关函数
前言
今天的C语言训练营没有安排高维数组的讲解,因为考试中常考的是一维数组,老师根据一维数组分析了数组越界、数组在内存中的分布、缓冲区与字符数组等相关问题。
一、数组的定义
先看一个案例:
为了存放鞋子,假设你把衣柜最下面的一层分成了 10 个连续的格子。此时,让他人帮你拿鞋子就会很方便,例如你可直接告诉他拿衣柜最下面一层第三个格子中的鞋子。同样假设现在我们有 10 个整数存储在内存中,为方便存取,我们可以借助 C 语言提供的数组,通过一个符号来访问多个元素。
也就是在我们使用的时候,如果需要用到多个类型相同的变量,我们大可以选数组,来简化我们的操作。
1.一维数组
①.如何定义
一维数组的定义格式为
类型说明符 数组名 [常量表达式]
例如:定义一个整型数组,数组名为 a,它有 10 个元素
int a[10];
②.声明规则
注意:声明数组时要遵循以下规则:
- (1)数组名的命名规则和变量名的相同,即遵循标识符命名规则。
- (2)在定义数组时,需要指定数组中元素的个数,方括号中的常量表达式用来表示元素的个数,即数组长度。
- (3)常量表达式中可以包含常量和符号常量,但不能包含变量。也就是说,C 语言不允许对数组的大小做动态定义,即数组的大小不依赖于程序运行过程中变量的值。
- 能不用高维数组就不用高维数组(多一个维度多一点复杂,除非自己特别了解数组)
以下是错误的声明示例(最新的 C 标准支持,但是最好不要这么写):
int n;
scanf(“%d”, &n); /* 在程序中临时输入数组的大小 */
int a[n];
数组声明的其他常见错误如下:
① float a[0]; /* 数组大小为 0 没有意义 /
② int b(2)(3); / 不能使用圆括号 /
③ int k=3, a[k]; / 不能用变量说明数组大小*/
③.内存分布
数组元素在内存中是连续分布的,并且遵循小下标位于低地址的原则。数组中每一个元素占有的空间跟数组类型有关。
④.初始化方法
(1)在定义数组时对数组元素赋初值。例如,
int a[10]={0,1,2,3,4,5,6,7,8,9};
不能写成
int a[10];a[10]={0,1,2,3,4,5,6,7,8,9}
(2)可以只给一部分元素赋值。例如,
int a[10]={0,1,2,3,4};
定义 a 数组有 10 个元素,但花括号内只提供 5 个初值,这表示只给前 5 个元素赋初值,后 5 个
元素的值为 0。
(3)如果要使一个数组中全部元素的值为 0,那么可以写为
int a[10]={0,0,0,0,0,0,0,0,0,0};
或
int a[10]={0};
(4)在对全部数组元素赋初值时,由于数据的个数已经确定,因此可以不指定数组的长度。
例如,
int a[]={1,2,3,4,5};
2.二维数组
除了使用一维数组,还可以使用二维数组,二维数组定义方法与一维数组大致相同。
类型说明符 数组名 [常量表达式][常量表达式]
例如:定义一个整型数组,数组名为 a,它有 100 个元素
int a[10][10];
3.高维数组
C语言支持3维及以上维度的数组,不过我们一般用不到,所以不必深究,只需了解即可。使用数组的时候一定要避免数组越界这个问题,我会在下面介绍到。
先看看高维数组的使用:
//
// Created by Zhu Shichong on 2023/1/9.
//
#include<stdio.h>
main()
{int a[1][1][1];int b[1][1][1][1];int c[2][2][2][2][2];a[0][0][0]=1;b[0][0][0][0]=2;c[1][1][1][1][1]=3;printf("%d %d %d",a[0][0][0],b[0][0][0][0],c[1][1][1][1][1]);return 0;
}
数组元素的个数=定义时各维度下标大小连乘
二、访问数组元素相关问题
1.访问越界
前面介绍过数组定义之后在内存中是连续分布的,并且100个元素的数组最大数组下标为99,那么我们访问下标为100的元素会有什么问题呢?大致有以下两种情况:
- 数组内存中接下来的空间被其余变量占用:会直接导致程序异常。
- 数组内存中接下来的空间没有被其余变量占用:会读出内存中的脏值(也就是乱码。内存中有什么将会读什么),最终亦会导致程序异常。
由此可见,数组越界对我们的程序影响之大。
可能文字不如图片给的感觉强烈,下面给出一个案例:大家可以自行尝试
//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
//数组越界
int main()
{int a[5]={1,2,3,4,5}; //定义数组时,数组长度必须固定int j=20;int i=10;a[5]=6; //越界访问a[6]=7; //越界访问会造成数据异常printf("i=%d\n",i); //i 发生改变return 0;
}
有这种情况的原因是:
编译器并不检查程序对数组下标的引用是否在数组的合法范围内。这种不加检查的行为有好处也有坏处,好处是不需要浪费时间对有些已知正确的数组下标进行检查,坏处是这样做将无法检测出无效的下标引用。
一个良好的经验法则是:
如果下标值是通过那些已知正确的值计算得来的,那么就无须检查;如果下标值是由用户输入的数据产生的,那么在使用它们之前就必须进行检查,以确保它们位于有效范围内。
2.数组的传递
先看一个案例:
//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
#include<string.h>
//一维数组的传递,数组长度无法传递给子函数
//C 语言的函数调用方式是值传递(将地址的值传递过去)
void print(int b[],int len)
{int i;for(i=0;i<len;i++){printf("%3d",b[i]);}b[4]=20; //在子函数中修改数组元素printf("\n");
}
//数组越界
//一维数组的传递
#define N 5
int main()
{int a[5]={1,2,3,4,5}; //定义数组时,数组长度必须固定print(a,5);printf("a[4]=%d\n",a[4]); //a[4]发生改变return 0;
}
如果在print数组时不传递len过去,将会导致无法获取数组的长度,从而无法访问到数组中所有的元素,想要在函数中访问数组中的所有元素,必要的一点就是将数组的长度通过参数的方式传进去。
原因如下:
这是因为一维数组在传递时,其长度是传递不过去的,所以我们通过 len来传递数组中的元素个数。实际数组名中存储的是数组的首地址,在调用函数传递时,是将数组的首地址给了变量 b(其实变量 b 是指针类型,具体原理会在指针节讲解),在 b[]的方括号中填写任何数字都是没有意义的。这时我们在 print 函数内修改元素 b[4]=20,可以看到数组 b 的起始地址和 main 函数中数组 a 的起始地址相同,即二者在内存中位于同一位置,当函数执行结束时,数组 a 中的元素 a[4]就得到了修改。
三、Scanf与字符数组
1.字符数组初始化
字符数组的定义方法与前面介绍的一维数组类似。例如,
char c[10];
字符数组的初始化可以采用以下方式。
(1)对每个字符单独赋值进行初始化。例如,
c[0]=‘I’;c[1]=’ ‘;c[2]=‘a’;c[3]=‘m’;c[4]=’';c[5]=‘h’;c[6]=‘a’;c[7]=‘p’;c[8]=‘p’;c[9]=‘y’;
(2)对整个数组进行初始化。例如,
char c[10]={‘I’,‘a’,‘m’,‘h’,‘a’,‘p’,‘p’,‘y’}
工作中一般不用以上两种初始化方式,因为字符数组一般用来存取字符串。通常采用的初始化方式是 char c[10]= “hello”。因为 C 语言规定字符串的结束标志为’\0’,而系统会对字符串常量自动加一个’\0’,为了保证处理方法一致,一般会人为地在字符数组中添加’\0’,所以字符数
组存储的字符串长度必须比字符数组少 1 字节。例如,char c[10]最长存储 9 个字符,剩余的 1 个字符用来存储’\0’。如果末尾没有存储\0将会可能导致程序出现以下错误(一直沿着字符数组打印,直到内存中存储\0为止)
。
2.scanf读取字符
最明显的就是scanf碰见空白字符会直接阻断
,导致一句话有空格时没办法直接用scanf把那句话读进字符数组。可以通过对下面一个小程序输入 how are you 体会体会。
//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
//scanf 读取字符串时使用%s
int main()
{char c[10];char d[10];scanf("%s",c);printf("%s\n",c);scanf("%s%s",c,d);printf("c=%s,d=%s\n",c,d);return 0;
}
最好的解决方法就是使用gets,puts函数
gets 函数类似于 scanf 函数,用于读取标准输入。前面我们已经知道 scanf 函数在读取字符串时遇到空格就认为读取结束,所以当输入的字符串存在空格时,我们需要使用 gets 函数进行读取。
gets 函数的格式如下:
char *gets(char *str);
gets 函数从 STDIN(标准输入)读取字符并把它们加载到 str(字符串)中,直到遇到换行符(\n)。如下例所示,执行后,我们输入"how are you",共 11 个字符,可以看到 gets 会读取空格,同时可以看到我们并未给数组进行初始化赋值,但是最后有’\0’,这是因为 gets 遇
到\n 后,不会存储\n,而是将其翻译为空字符’\0’。
puts 函数类似于 printf 函数,用于输出标准输出。puts 函数的格式如下:
int puts(char *str);
函数 puts 把 str(字符串)写入 STDOU(标准输出)。puts 会将数组 c 中存储的"how are you"字符串打印到屏幕上,同时打印换行,相对于 printf 函数,puts 只能用于输出字符串,同时多打印一个换行符,等价于 printf(“%s\n”,c)
四、字符数组相关函数
str 系列字符串操作函数主要包括 strlen、strcpy、strcmp、strcat 等。strlen 函数用于统计字符串长度,strcpy 函数用于将某个字符串复制到字符数组中,strcmp 函数用于比较两个字符串的大小,strcat 函数用于将两个字符串连接到一起。
函数原型如下:
头文件 #include <string.h>
size_t strlen(char *str);
char *strcpy(char *to, const char *from);
int strcmp(const char *str1, const char *str2);
char *strcat(char *str1, const char *str2);
对于传参类型 char*,直接放入字符数组的数组名即可。
注意以下几点:
- strlen 函数的计算原理是通过判断结束符来确定字符串的长度。
- strcpy 函数用来将字符串中的字符逐个地赋值给目标字符数组。例中我们将 c 复制给 d,就是将 c 中的每个字符依次赋值给 d,也会将结束符赋值给 d。注意,
目标数组一定要大于字符串大小,即 sizeof(d)>strlen(c),否则会造成访问越界
- strcmp 函数用来比较两个字符串的大小(
首先比较首字母ASCII值,第一个相同比较第二个依次类推
),由于字符数组 c 中的字符串与 d 相等,所以这里的返回值为 0。如果 c 中的字符串大于 d,那么返回值为c与d中不同位字符相减即 c-d(正值);如果 c 中的字符串小于 d,那么返回值依旧为c-d(负值)。如何比较两个字符串的大小呢?具体操作是从头开始,比较相同位置字符的 ASCII码值,若发现不相等则直接返回,否则接着往后比较。例如,strcmp(“hello”,“how”)的返回值是−1,即"hello"小于"how",因为第一个字符 h 相等,接着比较第二个位置的字符,e 的 ASCII 码值小于 o 的,然后返回e-o。不同的标准中有可能返回值不同
,但一定是两字符串相同返回0,前面小后面大返回负值,否则返回正值。 - strcat 函数用来将一个字符串接到另外一个字符串的末尾。例中字符数组 c 中存储的是"hello",我们将 d 中的"world"与 c 拼接,最终结果为"helloworld"。注意,
目标数组必须大于拼接后的字符串大小,即 sizeof(c)>strlen(“helloworld”)
。
今天的分享到此结束!!!
相关文章:

【C语言督学训练营 第五天】数组字符串相关知识
文章目录前言一、数组的定义1.一维数组①.如何定义②.声明规则③.内存分布④.初始化方法2.二维数组3.高维数组二、访问数组元素相关问题1.访问越界2.数组的传递三、Scanf与字符数组1.字符数组初始化2.scanf读取字符四、字符数组相关函数前言 今天的C语言训练营没有安排高维数组…...

GPT-4 免费体验方法
POE 在Quora上非常受欢迎的手机聊天机器人Poe App已经集成ChatGPT助手!除了最初集成的三个聊天机器人Sage、Claude和Dragonfly外,Poe现在还加入了第四位ChatGPT。由于使用了ChatGPT API,因此Poe拥有真正的ChatGPT。 现在更是第一批集成了GP…...
中断-屏蔽位
1.中断控制器(PIC:适用于单处理器、APIC) 1.定义 中断控制器可以看作是中断服务的代理,外设五花八门,如果没有一个中断的代理,外设想要给cpu发送中断信号来处理中断。那么只能是外设连接在cpu引脚上,由于cpu引脚很宝贵,所以不可能拿出那么多引脚来供外设连接,所以就有…...
【洛谷P1636】 Einstein学画画
题目描述:Einstein 学起了画画。此人比较懒~~,他希望用最少的笔画画出一张画……给定一个无向图,包含 n 个顶点(编号 1∼n),m 条边,求最少用多少笔可以画出图中所有的边。输入格式第一行两个整数…...
户外LED显示屏钢结构制作原则
户外LED显示屏在施工安装时是必须要制作固定钢结构的,因为户外LED显示屏工作环境相对比较恶劣,制作钢结构一是为了安全,二是为了提高防护等级。那么户外LED显示屏钢结构制作原则是什么呢?迈普光彩小编总结了一些分享个大家。 户外…...
【内网穿透】使用Haproxy反向代理搭建企业私有云:神卓互联教程
神卓互联是一款强大的内网穿透工具,可以帮助企业搭建私有云,实现对内部资源的远程访问。在搭建私有云的过程中,使用HAProxy反向代理可以提高系统的性能和可靠性。本文将介绍如何使用神卓互联和HAProxy反向代理搭建私有云。 步骤如下…...
spring boot项目:实现与数据库的连接
步骤【写在前面】定义数据库连接信息:引入数据库驱动:创建数据源:创建JdbcTemplate:编写DAO层:使用Service注解标注Service层:使用RestController注解标注Controller层:示例代码:app…...

【gitlab部署】centos8安装gitlab(搭建属于自己的代码服务器)
这里写目录标题部署篇序言要求检查系统是否安装OpenSSH防火墙问题准备gitlab.rb 配置坑点一忘记root密码重置使用篇gitlab转换成中文git关闭注册入口创建用户部署篇 序言 在团队开发过程中,想要拥有高效的开发效率,选择一个好的代码开发工具是必不可少的…...
2021年全国职业院校技能大赛(中职组)网络安全竞赛第三套试题A模块解析(超级详细)
2021年全国职业院校技能大赛(中职组) 网络安全竞赛试题 (3) (总分100分) 赛题说明 一、竞赛项目简介 “网络安全”竞赛共分A. 基础设施设置与安全加固;B. 网络安全事件响应、数字取证调查和应用安全;C. CTF夺旗-攻击;D. CTF夺旗-防御等四个模块。根据比赛实际情况…...

Hbase异步复制和同步复制解析
背景 Hbase是一个KV数据库,自然和Mysql以及Redis等会涉及到复制的问题,也有主从集群的概念,那么本文就来看下Hbase的复制逻辑 Hbase复制实现 首先我们先在回顾下,在Hbase实现中,每个RegionServer上面会包含多个Regi…...

TIKTOK海外直播公会如何申
在“清朗行动”的规范化整治下,国内秀场直播俨然成为了“夕阳行业”,早已度过了野蛮生长的阶段。随着直播公会内卷竞争加剧,公会的生存也愈发艰难,有的娱乐主播甚至纷纷转行做起了电商,可见国内娱乐直播行业的惨淡。 …...

6.springcloud微服务架构搭建 之 《springboot集成Gateway》
5.springcloud微服务架构搭建 之 《springboot集成Hystrix》 目录 1.gateway介绍 2.项目引入gateway 3.yml配置gateway参数 5.自定义全局Filter 6.测试 1.gateway介绍 服务网关(Spring Cloud Gateway)是Spring Cloud官方推出的 第二代网关框架&#…...

[N1CTF 2018]eating_cms_
目录 信息收集 代码审计 parse_url解析漏洞 信息收集 进入即是登录页面,抓包一看应该是SQL注入,但是空格、%、|等等啥的都被waf了,不太好注入,先信息收集一波 花一分钟扫下目录,发现一个viminfo和register.php Viminfo文件…...

《Spring系列》第13章 Aop切面(二) 代理创建
前言 本篇文章主要介绍AOP的源码,要想看懂AOP,那么就看AOP给容器中注入了什么组件,这个组件什么时候工作,这个组件的功能是什么? EnableAspectJAutoProxy会向IOC容器中注入一个后置处理器,它会在Bean的创…...
算法-贪心
贪心算法1信息学竞赛课堂贪心算法2贪心法实际生活中,经常需要求一些问题的“可行解”和“最优解”,这就是所谓的“最优化”问题。一般来说,每个最优化问题都包含一组“限制条件”和一个“目标函数”,符合限制条件的问题求解方案称…...

【数据结构与算法】树(Tree)【详解】
文章目录前言树一、树的基本概念1、树的定义2、基本术语3、树的性质二、树的存储结构1、双亲表示法2、孩子表示法3、孩子兄弟表示法二叉树一、二叉树的概念1、二叉树的定义2、几个特殊的二叉树3、二叉树的性质4、二叉树的存储结构二、遍历二叉树1、先序遍历2、中序遍历3、后序遍…...

OSPF------LSA 详解
LSA头部 [r1]display ospf lsdb 链路状态老化时间(Link-State Age) 16bits,单位s当该LSA被始发路由器产生时,该值被设置为0,之后随着该LSA在网络中被洪泛,老化时间逐渐累积。(但是不能让它一直增长&#x…...
js加解密入门
首先,让我们简单介绍一下百度公司的文心一言。文心一言是百度公司推出的一项文本生成工具,它可以根据给定的主题或关键词生成一句简短而富有启发性的文字。在我们的加密和解密方法中,我们将利用文心一言的特点来生成随机的字符串,…...

vue+Echarts导入自定义地图
在vue项目先安装echarts //在vue文件中的<script>中引入 import * as echarts from "echarts"; import geoJson from ../assets/map/Fmap.json; //自定义地图的位置 import * as topojson from "topojson-client"; //使用组件topojson-client自定…...
dp-组合总和 Ⅳ
给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。题目数据保证答案符合 32 位整数范围。示例 1:输入:nums [1,2,3], target 4输出:7解释:所…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...

UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...

微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...

自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...

【免费数据】2005-2019年我国272个地级市的旅游竞争力多指标数据(33个指标)
旅游业是一个城市的重要产业构成。旅游竞争力是一个城市竞争力的重要构成部分。一个城市的旅游竞争力反映了其在旅游市场竞争中的比较优势。 今日我们分享的是2005-2019年我国272个地级市的旅游竞争力多指标数据!该数据集源自2025年4月发表于《地理学报》的论文成果…...

数据分析六部曲?
引言 上一章我们说到了数据分析六部曲,何谓六部曲呢? 其实啊,数据分析没那么难,只要掌握了下面这六个步骤,也就是数据分析六部曲,就算你是个啥都不懂的小白,也能慢慢上手做数据分析啦。 第一…...