数组
这篇文章主要对数组、二维数组和几个字符串处理函数进行简单探究
1.数组的定义
-
类型 数组名[元素个数]
这种写法即为数组的定义方式如:
int a[6]; char b[20]; double c[24]; float d[30];
-
上面定义的的几个类型的数组中:
一般整型数组一个元素占4个字节;字符型数组一个元素占1个字节,单精度浮点型数组占4个字节,双精度浮点型数组占8个字节
注:在以前的标准中是不允许定义动态数组的,也就是说int a[6];
其[]
的值只能是常量和常量表达式
而在C99
新标准的定义下,是允许存放动态数组的,也就是说可以在程序运行的过程中定义数组的长度,其[]
的值也可以是变量。
如:
int n;
printf("请输入需要的数组长度:");
scanf("%d",&n);
int a[n];
2.访问数组中的元素
-
语法:
数组名[小标]
注
:数组中元素的小标是从0
开始的,也就是说数组中第一个元素的小标为0
。(后面的讲解可跳过)那么为什么要这样呢,这就要设计一点后面的知识了,简单来说,某个元素的小标就相当与其相对于第一个元素的偏移量,如第一个元素相对于第一个元素的偏移量为0,所以第一个元素的小标为0 -
所以我们用访问其中元素可以这样写:
int a[6]; //创建一个具有六个元素的整型数组 printf("%d",a[0]); //其中a[0]就相当于访问数组a的第1个元素。 printf("%d",a[4]); //其中a[0]就相当于访问数组a的第5个元素。 printf("%d",a[6]); //此时因为第6个元素的下标为5,所以此操作就相当于越界访问,最好不要这样做
3.遍历打印数组中的元素
如果我们要遍历数字中的所有元素,这时就需要借助循环了,直接引用数组名一般是不能打印出数组元素的。为什么要说一般呢,因为字符数组除外。
- 如:我们要打印下面的一个整型数组:
int a[10] = {1,2,3,4,5,6,7,8,9,10};
for (i = 0; i < 10; i++) //注意小标是从0开始的哦!
{
printf("%d",a[i]);
}
- 但如果要打印字符数组呢:
char a[10] = {"zifushu"};
printf("%s",a);//注意字符串的格式化占位符的转换类型为%s
- 同样我们要接受数据到数组中时,整型数组和其它数组需要一个元素一个元素的接收
int a[10];
int ch;
int i = 0;
while ((ch = getchar()) != '\n')
{
a[i++] = ch;
}
- 面对字符型的数组(如果是
不间断
的字符串,也就是在字符串中没有空格
),我们可以用scanf()
直接将字符串接收到字符数组中
如:(注意这里用scanf()
接收函数的特殊性哦)注:一般接收字符串是不使用scanf(),这里主要举例子
char a[10];
printf("请输入字符串");
scanf("%s",a); //这里用scanf接收字符串到数组a中不需要用取值操作符&,是因为数组名就相当于第一个元素的地址。
而如果该字符串是间断的呢?此时我们就要用到gets()
函数,或者一个个接收了。那么肯定有很多人要问?为什么不能用scanf()
接收间断、不连续的字符串呢?我们马上解释:
因为scanf()
函数有一个特性,当他接收到空白字符时,他会终止接收剩下的字符串,也就是说当他识别到一个空白字符后,这个函数将会终止。
如:我们用以下程序接收:
char a[10];
scanf("%s",a);
如果我们此时输入LL AA DD
那么a中将只会存在LL两个字符
- 那么gets()函数究竟是怎么实现接收的呢
char a[10];
gets(a);
是不是非常简单,以后接收字符串就可以使用gets()函数了
- 当然我们也可以一个字符一个字符的接收
char a[10];
int i;
while ((str[i++] = getchar()) != '\n') //其循环中是一个空语句,本身不执行任何操作,这里我们是在循环条件中赋值给a数组
;
4.数组的初始化
-
如果我们要将数组中所有元素初始化为0,可以用以下写法:
int a[10] = {0};
注:这里实际上只是将数组中第一个元素赋值为0
那么为什么后面所有元素都为0了呢?
我们先来看看遍历以下数组会打印什么结果。
int b[10] = {1};
结果是:a[0] = 1,后面所有元素都为0
那么这究竟是为什么呢?
答:因为当我们为第一个元素初始化后,后面所有元素将自动初始化为0。
-
如果赋值要给不同元素赋值,我们只需要用逗号将值隔开即可
如:
int a[10] = {1,2,3,4,5,6,7,8,9,0};
-
当然我们还可以只给数组中一部分赋值,剩下的当然会自动初始化为0
如:
int a[10] = {1,2,3,4,5,6};
-
有些人可能会问了,那我们能不能不写前面的数组长度呢?
当然可以呐,C语言就给了一种偷懒的方法,我们可以给出各个元素的值,不指定数组的长度,这时数组的长度会根据你写的元素个数自动计算。(
当然,这种方法是有局限性的,你写多少个值,那么数组就有多大的长度
) -
C99
新增了一个新的特性:指定初始化的元素,这样就可以对数组中某些指定元素进行初始化赋值,而未被赋值的元素将自动初始化为0int a[10] = {[3] = 3,[5] = 5,[8] = 8}; //注意这里[]里面的数字是索引哦
5.那么现在我们来做一些小练习吧!
-
用户是否可以自己输入字符串结束标志
‘\0’
呢?答:这当然是不可以的呐,because '\0' 代表ASCII码为0的字符,它不是一个可以显示的字符,而仅仅是一个“空操作符”,表示什么也不做,因此它作为字符串结束标志符。
-
假如有一个数组占用了7个字节的内存空间,你知道它是什么类型的数组吗?
答:它当然是一个字符数组呐,因为只有char类型的数组才可能有存在奇数的空间,其它类型的数组是不可开辟出奇数个字节的空间
-
看下面一串代码,回答 为什么标号(1)那里需要开辟 n + 1 大小的字符数组
为什么标号(2)那里需要一个getchar();
#include <stdio.h> int main(void) { int n,ch,i = 0; printf("请输入要输入字符串的个数:"); scanf("%d",&n); char a[n+1]; printf("请开始输入字符串:"); getchar(); while ((ch = getchar()) != '\n') { a[i++] = ch; } a[n] = '\0'; printf("你输入的字符串是:%s\n",a); return 0; }
答:(1)为什么我们要开辟一个n+1大小的字符数组呢,这是因为在存储字符串是我们还需要一个字符串结束符'\0',这个很重要一定要记住哦,因为当我们直接用scanf("%s",a);来打印数组时,只有当程序读到结束符'\0'时才会结束打印,不然就会一直打印下去,不管你字符数组长度是多少。就像下面这样。
(2为什么需要一个getchar(),因为在我们输入完字符串后,会敲一个换行符'\n',如果不用getchar()接收掉这个空格键,下次再次接收时,就会接收这个'\n'换行符。