目录
一、数组的定义
- 定义:数组是一组有序数据的集合。数组中个数据的排列是有一定规律的,下标(或索引)代表数据在数组中的的序号(从0开始),且数组中的每一个元素都属于同一个数据类型
二、一维数组
- 创建格式为:数据类型 数组名[常量表达式]
- 其中这个常量表达式也就是数组的长度,也可以不写
- 以下关于char类型数组上面的注释要仔细理解和看
#include <stdio.h>
main(){
//创建一个数组名为name的数组里面存放10个char类型的数据
//注意字符串类型中哪怕"abcdefghij"满足十个字符但后面还是有个默认的'\0'字符
//但在某些依赖于正确的字符串结束标志的操作中可能会导致问题。所以尽量留一位给'\0'
//只有字符型数组存在'\0'结束符
char name[10]="。。。";//这种形式初始化才会自动添加'\0',等下举个不自动添加的
int age[10]; //创建一个数组名为age的数组,里面存放10个int类型数据
double test[10] //创建一个数组名为test数组,里面存放10个double类型的数据
}
#include <stdio.h>
main() {
char name[7] = "promise"; //定义一个字符型的数据,其中一种方式;
//这是特殊的初始化方式[]中没有给定范围
//但系统就默认我们初始化的元素个数就为数组的大小,系统会自动帮我们计算数组的大小,
//并且按照顺序一一对数组中的元素进行赋值
//{}包含每个字符,故此数组长度为9,在这种初始化方式中,没有明确指定字符串的结束,所以不会自动添加 '\0'
char name2[] = {'Z','h','a','n','g','\t','s','a','n'};
int age[2] = {18,21}; //初始化一个age数组,为int类型
double result[3]; //定义一个double类型数组
result[0] = 88.8; //给索引0赋值
result[1] = 99.9; //给索引1赋值
printf("%0.2f",result[0]);
printf("%zu\n",sizeof(name2));
for (int i = 0;i <= sizeof(name);i++) {
printf("%c", name[i]);
}
}
关于为什么是问号解答:在进行循环时,循环超出数组的有效范围了。当访问到数组末尾之后的内存时,其值是未定义的,所以输出的最后一个字符可能是问号或者其他不可预期的字符。
好!我现在再来写一个,你们自己运行以下就会发现,当循环没有超过范围且后面的范围没有字符串时及时运行到也会发现是空的,因为这是隐藏的'\0'
#include <stdio.h>
main{
char name[8]="promise";
for(int i=0;i<sizeof(name);i++){
printf("%d",name[i])
}
}
三、二维数组
- 定义:数组的元素都是内置类型的,如果我们把一维数组作为数组的元素,这就是二维数组,二维数组作为数组元素的数组被称为三维数组,把二维数组以上的数组统称为多维数组
//创建格式
类型符 数组名[常量表达式1][常量表达式2]
//常量表达式1为行
//常量表达式2为列
int num[2][3] = {{1,2,3},{4,5,6}};//定义一个行为2,列为3的数组
//查看数组
for (int i = 0;i < 2;i++) { //遍历行
for (int j = 0;j < 3;j++) { //遍历列
printf("%d\t",num[i][j]); //输出对应行和列的元素
}
printf("\n");
}
四、sizeof()计算数组取值范围
4.1一维数组取值范围计算
计算公式:数据类型长度x数组长度
int ints[10] = { 1,2,3,4,5,6,7 };
short shorts[10] = { 1,2,3,4,5,6,7 };
double doubles[10] = { 1,2,3,4,5,6,7 };
char chars[10] = {'1','2','3'};
printf("一维数组ints的取值范围为:%zu\n",sizeof(ints));
printf("一维数组lons的取值范围为:%zu\n", sizeof(shorts));
printf("一维数组floats的取值范围为:%zu\n", sizeof(doubles));
printf("一维数组chars的取值范围为:%zu\n", sizeof(chars));
4.2 二维数组取值范围计算
计算公式:行x列x数据类型=二维数组长度
五、字符数组中常用的函数
-
在 C 语言中,严格来说没有像其他一些高级语言那样内置的真正意义上的 “字符串类型”。它的字符串是以字符数组的形式存在的,以
'\0'
作为字符串结束标志。(首尾呼应上了哈) -
所以我们要对字符串进行操作,即字符数组操作就需要调用string.h文件!!!那么我们现在来看看此文件中有哪些常用的函数。
5.1 strlen()函数
- 作用:用于计算字符串的长度,它通过查找字符串中的
'\0'
字符来确定长度 - 返回类型:unsigned int
#include <stdio.h>
#include <string.h>
main(){
char str1[]="My name is Promise";
printf("str的字符串长度为:%d",strlen(str1))
}
5.2 strcpy()函数
- 格式:strcpy(字符数组1,字符数组2);
- 作用:将字符数组2复制到字符数组1中去
#include <stdio.h>
#include <string.h> //调用string源文件
main() {
Common_Keywords(); //调用常见关键字函数
}
Common_Keywords() {
char str2[] = "I'am from Anhui";
char str3[20]="Copy test";
strcpy(str3, str2);
printf("复制完str2后str3的值为:%s",str3);
}
str3可以没有赋值,也可为赋值状态。如果str里面有初始化的值,strcpy
会覆盖str3
原有内容,从str3
的起始地址开始将str2
的内容复制进去,直到遇到str3
中的字符串结束符'\0'
。
注:如果str2
字符串长度大于str3
的可用空间(不包括结束符'\0'
),会导致缓冲区溢出,可能引发程序错误甚至安全问题。如下图所示
5.3 strncpy()函数
功能:strncpy
是一个字符串复制函数,相比strcpy
,它多了一个指定复制长度的参数,可以更好地控制复制的字符数量,从而降低缓冲区溢出的风险。- 格式为:trcpy(字符数组1,字符数组2,字符个数);
#include <stdio.h>
#include <string.h> //调用string源文件
main() {
Common_Keywords(); //调用常见关键字函数
}
Common_Keywords() {
char str1[] = "My name is Promise";//默认后面有一个'\0'结尾
char str2[] = "I'am from Anhui";
char str3[20]="Copy test";
//调用strcpy函数
strcpy(str3, str2);
printf("复制完str2后str3的值为:%s\n",str3);
//调用strncpy函数
strncpy(str3,str1,2);
printf("复制完str1两个字符长度后str3的值为:%s\n", str3);
}
有此运行结果可以推断出:strcpy它源字符串str1中的字符个数哪怕小于目标字符串str2个数时str1会直接覆盖掉str2中所有的字符只保留str1的,但是strncpy在str1小于str2时只会覆盖掉对应位置的字符
5.4 strcat()函数
- 格式:strcat(目的字符串,源字符串);
- 作用:把源字符串追加到目标字符串后面,构成一个新的字符串;
#include <stdio.h>
#include <string.h> //调用string源文件
main() {
Common_Keywords(); //调用常见关键字函数
}
Common_Keywords() {
char str1[] = "My name is Promise";//默认后面有一个'\0'结尾
char str4[50]="hello world!";
strcat(str4,str1); //str4的长度要大于str1加str4本身已存储的字符个数
printf("将str1追加到str4后面的结果为:%s",str4);
}
5.5 strncap()函数
- 格式:str(目标字符串,源字符串,位数);
- 作用:源字符串的最多
n
个字符连接到目标字符串的末尾,覆盖目标字符串末尾的'\0'
,并在连接后的字符串末尾自动添加一个'\0'
。如果源字符串的长度小于n
,则将整个源字符串连接到目标字符串末尾;如果源字符串的长度大于或等于n
,则只连接源字符串的前n
个字符。
#include <stdio.h>
#include <string.h> //调用string源文件
main() {
Common_Keywords(); //调用常见关键字函数
}
Common_Keywords() {
char str1[] = "My name is Promise";//默认后面有一个'\0'结尾
char str2[] = "I'am from Anhui";
char str4[50]="hello world!";
strcat(str4,str1);
printf("将str1追加到str4后面的结果为:%s\n",str4);
//调用strncat函数
strncat(str4,str2,4);
printf("将str2中的四个字符追加到str4后面结果为:%s\n",str4);
}
5.6 strcmp()函数
- 格式:strcmp(表达式1,表达式2);
- 作用:用于比较两个字符串的大小
- 返回值:表达式1=表达式2返回0;表达式1<表达式2返回-1;表达式1>表达式2返回1
-
#include <stdio.h> #include <string.h> main(){ char str1[] = "My name is Promise";//默认后面有一个'\0'结尾 char str2[] = "I'am from Anhui"; printf("zzw与zzz的的比较结果为:%d\n",strcmp("zzw","zzz")); printf("str1与str2的的比较结果为:%d\n",strcmp(str1,str2)) //字符串中从第一个字母开始比较其ascall码值 }
执行过程:
- 逐个比较对应位置的字符的 ASCII 码值,直到找到不同的字符或者到达其中一个字符串的结束符(
'\0'
)。 - 如果在某个位置上,
str1
的字符 ASCII 码值小于str2
的对应字符 ASCII 码值,那么strcmp
返回一个负数。 - 如果在某个位置上,
str1
的字符 ASCII 码值大于str2
的对应字符 ASCII 码值,那么strcmp
返回一个正数。 - 如果两个字符串完全相同,即对应位置的字符都相同且同时到达结束符,那么
strcmp
返回 0。
5.7 strncmp()函数
- 格式:strcmp(表达式1,表达式2,长度);
- 作用:用于比较两个字符串的特定长度部分
- 返回值:表达式1=表达式2返回0;表达式1<表达式2返回-1;表达式1>表达式2返回1
#include <stdio.h>
#include <string.h> //调用string源文件
main() {
Common_Keywords(); //调用常见关键字函数
}
Common_Keywords() {
char str5[] = "abcdefg";
char str6[] = "abcdefh";
printf("str5与str6前6个字符的比较:%d\n",strncmp(str5,str6,6)); //哪怕长度超出字符串的长度,它也是在检测到字符串的'\0'后自动结束
}
5.8 puts()函数
- 格式:puts(const char *str);
- 作用:将字符串
str
输出到标准输出设备(通常是屏幕),然后自动输出一个换行符'\n'
要求:
使用时通常直接传入一个以空字符'\0'
结尾的字符串常量或字符数组作为参数
#include <stdio.h>
#include <string.h> //调用string源文件
main() {
Common_Keywords(); //调用常见关键字函数
}
Common_Keywords() {
char str5[] = "abcdefg";
puts("以下是str5数组值:");
puts(str5);
}
5.9 gets()函数
- 格式:gets(str);
- 作用:读取用户输入的一行字符,直到遇到换行符
'\n'
或文件结束符,然后将读取到的字符(不包括换行符)存储到字符数组s
中,并在字符串末尾自动添加一个空字符'\0'
。
#include <stdio.h>
#include <string.h> //调用string源文件
main() {
Common_Keywords(); //调用常见关键字函数
}
Common_Keywords() {
char getTest[30];
printf("请输入字符串长度需小于30:");
gets(getTest);
printf("你输入的字符串为:%s",getTest);
}
下面的了解即可,因为考纲不考,后面的就不知道考不考fgets函数了
注:gets
函数存在严重的安全风险,因为它不检查输入缓冲区的大小,可能导致缓冲区溢出。如果用户输入的字符串长度超过了接收它的数组的大小,就会发生缓冲区溢出,可能导致程序崩溃或被恶意利用。正因为如此,在现代 C 编程中,不推荐使用gets
函数。可以使用更安全的函数如fgets
来读取输入。
5.10 strlwr()与strupw()函数
- 作用:strlwr()将字母小写 strupw()将字母大写
- 注:现在2202版(以前的不知道)VS不支持这种写法了会报错,需要加上_。如下所示
#include <stdio.h>
#include <string.h> //调用string源文件
main() {
Common_Keywords(); //调用常见关键字函数
}
Common_Keywords() {
char str7[] = "abcdefg";
char str8[] = "HIJKLMN";
printf("将str7转大写为:%s\n",_strupr(str7));
printf("将str8转小写为:%s\n",_strlwr(str8));
}
5.11 strstr()函数
- 格式:strstr(目标字符串,子字符串);
- 作用:如果在被查找的字符串(目标字符串)中找到了要查找的子字符串,则返回指向子字符串在被查找字符串中首次出现位置的指针。如果没有找到子字符串,则返回
NULL
#include <stdio.h>
#include <string.h> //调用string源文件
main() {
Common_Keywords(); //调用常见关键字函数
}
Common_Keywords() {
//调用strncmp函数
char str5[] = "abcdefg";
//调用strstr()函数
char wordTest[] = "de";
char* result = strstr(str5, wordTest);//表示定义一个指向字符的指针wordTest,并让它指向一个字符串常量 "de" 的首地址
printf("在str5中查找字符ab的位置:%s\n",result);
char test24 = str5-result;
printf("str5原本长度与被查找出的长度相差:%d\n",result-str5);
printf("test24结果为:%d\n", test24);
}