C语言-数组
一维数组
二维数组
字符串
字符串处理函数
一维数组
我们知道,要想把数据存入内存,必须先要分配内存空间。放入四个整数,就得分配四个int型内存空间;
int a[4];
这样,就在内存中分配了4个int类型的内存空间,并给他们组成的集合给了一个名字a。
我们把这样的一组数据的集合称为“数组(Array)”
,它所包含的每一个数据叫做这个数组的“元素(Element)”
,所包含的数据的个数称为数组的“长度(Length)”
。
数组中每个元素都拥有一个属于自己的一个序号,这个序号从零开始,称为“下标(index)”
arrayName[index]
arrayName代表数组名字,index为下标。
需要注意的是:
- 数组中每个元素的数据类型必须相同
- 访问数组时,下标的取值范围一定是0 <= index < length,过大或者过小都会越界,导致数组溢出,发生不可预测的情况。
- 在数组定义时一定不能将数组的下标弄得含糊不清,更不能为变量会将数组定义时就发生错误。
数组内存是连续的
数组是一个整体,它的内存是连续的;也就是说,数组元素之间是相互挨着的,彼此之间没有一点点缝隙。
数组的初始化
- 可以只给部分元素赋值。当
{}
中的值的个数少于元素个数时,只给前面部分元素赋值。
int a[10]={12,19,22,993,344};
有没有想过你只赋值给了五个元素,那剩下的五个元素会存入什么。
当赋值的元素少于数组总体元素的时候,剩余的元素自动初始化为0;
- 对于short、int、long,就是整数0。
- 对于char,就是字符’\0’。
- 对于float、double,就是小数0.0。 由于剩余元素初始化为0,我们只需要将第0个元素赋值为0即可。
- 只能给元素逐个赋值,不能给数组整体赋值。例如:
int a[10] = {1,1,1,1,1,1,1,1,1,1};
//而不能写成
int a[10] = 1;
- 如果我们要给全部元素赋初值,那么在定义数组长度时可以不定义数组长度:
int a[] = {1,2,3,4,5};
//等价
int a[5] = {1,2,3,4,5};
二维数组
dataType arrayName[length1][length2]
数据类型 数组名 [一维下标长][二维下标长]
我们可以将二维数组看作一个Excel表格,有行有列,length1 表示行数,length2 表示列数,要在二维数组中定位某个元素,必须指定行列。
int a[3][4];
/* 表示这样的一组。
a[0][0], a[0][1], a[0][2], a[0][3]
a[1][0], a[1][1], a[1][2], a[1][3]
a[2][0], a[2][1], a[2][2], a[2][3]
*/
二维数组只是在概念上是二维的,存放在内存中存放时依然是连续的,也就是说二维数组是由多个一维数组组成的。
二维数组赋初值
二维数组的赋值方式和一维相像,就像是将多个一维数组赋值
int a[5][3]={ {80,75,92}, {61,65,71}, {59,63,70}, {85,87,90}, {76,77,85} };
//等价
int a[5][3]={80, 75, 92, 61, 65, 71, 59, 63, 70, 85, 87, 90, 76, 77, 85};
- 可以对部分元素赋值,未赋值的元素自动取“零”值
int a[3][3] = {{1},{2},{3}};
//2
int b[3][3] = {{0,1},{0,0,2},{3}};
然后数组输出后的结果为:
1 0 0
2 0 0
3 0 0
//2
0 1 0
0 0 2
3 0 0
- 如果对全部元素赋值,那么第一维的长度可以不给出。
int a[][3] = {1,2,3,4,5,6,7,8,9};
字符数组
用来存放字符的数组称为“字符数组”,也就是一串字符的集合也称“字符串(string)”
C语言中可以直接将字符串赋给字符数组,而不用一个个赋值。例如:
int a[] = {'t','i','a','g','l','a','n','g','z','.','t','o','p','\0'};
int a[] = {"tianlangz.top"};
int a[] = "tianlangz.top";
这三种方式都会将后面的字符串输入到字符数组中。
还要注意一个问题,字符数组只有在定义时才能将整个字符串一次性的赋给它,一旦定义完成,就只能一个一个的赋值了。
字符串结束标志
想要在内存中定位一个字符串,除了要知道开头,还要知道结尾,找到开头很容易,知道它的名字(字符数组的名字或者字符串名)就可以,而字符串在C语言中,字符串总以’\0’作为结尾。所以’\0’也称字符串的结束标志。
C语言在处理字符串的时候,会从前往后逐个扫描字符,一旦遇到’\0’就认为到达了字符串的末尾,随后结束处理因此\0
异常重要,没有\0
字符串就没有结尾。
由""
包围的字符串会自动在尾部添加一个\0
;但需要注意的是如果字符数组是一个一个字符输入的话,那在输入完成后就不会再字符串尾部添加\0
;
在给字符数组赋初值时一定要格外注意留出\0
的位置不然你的字符数组将没有边界。printf()函数输出字符串的时候是遇到\0
结束输出,如果没有,那将继续输出别的东西,因为你的内存中放的不仅仅只有这个数组还有很多其他的东西这就会导致,我们自己都不知道他会输出什么出来。
字符串处理函数
使用字符串处理函数的前提是添加一个头文件<string.h>
string.h是一个专门用来处理字符串的头文件,它包含了多个字符串处理函数
计算字符串长度函数strlen()
用来计算字符串长度的,所谓字符串长度,就是字符串包含了多少个字符(不包括最后的结束符\0
),我们利用strlen()函数来求出字符串的长度,它的用法为:
length strlen(strname);
示例:
#include <stdio.h>
#include <string.h> //记得引入该头文件
int main(){
char str[] = "tianlangz.top";
long len = strlen(str);
printf("The lenth of the string is %ld.\n", len);
return 0;
}
运行结果:
The lenth of the string is 13.
字符串连接函数 strcat()
strcat 是string catenate 的缩写,意思是把两个字符拼接到一起,格式为:
strcat(arrayName1,arrayName2);
arrayName1、arrayName2为需要拼接的字符串。
strcat()将把arrayName2连接到arrayName1后面,并删除原来arrayName1最后的结束标志\0
。这意味着,arrayName1需要足够长,要能够同时容纳两个字符串的长度,否则会越界(超出范围)。
strcat()的返回值为arrayName1的地址。例如:
#include <stdio.h>
#include <string.h>
int main(){
char str1[100]="The URL is ";
char str2[60];
printf("Input a URL: ");
gets(str2);
strcat(str1, str2);
puts(str1);
return 0;
}
运行结果:
Input a URL: https://www.tianlangz.top
The URL is https://www.tianlangz.top
字符串复制函数 strcpy()
strcpy() 是 string copy 的缩写,意思就是字符串复制,也就是将一个字符串从一个地方复制到另一个地方。
strcpy(arrayName1,arrayName2);
它会把后面的内个字符串复制到前面的内个字符串中,连\0也一起复制:
#include <stdio.h>
#include <string.h>
int main(){
char str1[50] = "《C语言》";
char str2[50] = "https://www.tianlangz.top";
strcpy(str1, str2);
printf("str1: %s\n", str1);
return 0;
}
运行结果:
str1: https://www.tianlangz.top
将字符串二中的内容复制过来,只要字符数组一足够长就能够完美融入其中,而且覆盖原有内容,当然如果原有内容字符串一就比字符串2长,那么虽然不输出,但是没有被覆盖的部分依然存在于原数组中,但是数组一的长度不够数组二的长度,就不能全部装入所拷贝的字符串了。
字符串比较函数strcmp()
strcmp() 是 string compare 的缩写,意思是比较两个字符串。
strcmp(arrayName1, arrayName2);
字符本身没有大小之分,strcmp()使用字符对应的ASCII码值进行比较,从头开始比较,如果他们相等,就比较下一个字符,直到遇见不同的字符,或者到字符末尾。
而它的返回值为若字符串1和字符串2相同则返回0,如果字符串1比字符串2大则返回大于0的值,如果字符串1比字符串2小则返回小于0的值。 我们举例子来说明一下:
#include <stdio.h>
#include <string.h>
int main(){
char a[] = "aBcDeF";
char b[] = "AbCdEf";
char c[] = "aacdef";
char d[] = "aBcDeF";
printf("a VS b: %d\n", strcmp(a, b));
printf("a VS c: %d\n", strcmp(a, c));
printf("a VS d: %d\n", strcmp(a, d));
return 0;
}
结果:
a VS b: 32
a VS c: -31
a VS d: 0
当然理解数组有一个特别实际的例子 将数组中的元素按由小到大的顺序输出出来,用冒泡排序法
所谓冒泡排序法,整个排序的过程就像气泡从水中一个一个冒上来,最先上来的是最大的,然后第二个,以此类推,很经典。
#include <stdio.h>
int main()
{
int nums[10], i, j, temp, s;
for(i=0;i<10;i++)
scanf("%d",&nums[i]);
for(i=0;i<10-1;i++)
{
for(j=0;j<10-1-i;j++)
{
if(nums[j] > nums[j+1])
{
temp=nums[j];
nums[j]=nums[j+1];
nums[j+1]=temp;
}
}
}
for(i=0;i<10;i++)
printf("%d",nums[i]);
printf("\n");
return 0;
}
可以自己尝试理解一下。