06 数组程序设计
1.一维数组
1.1 一维数组的定义
定义:<类型>变量名称[元素数量] 。例如,
int a[100];
double b[200];
数组是一个容器,特点是
- 所有元素具有相同的数据类型
- 一旦创建,不能改变大小
- 数组中的元素在内存中连续依次排列
举例:
int a[10];
10个单元 a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9],每个单元是一个int类型的变量,可以出现在赋值的左边或右边 a[2] = a[1] +1,在赋值左边的叫做左值。
放在方括号[]
中的数字叫做下标或者索引,从0开始计数。有效的下标范围[0,数组的大小-1]
。
1.2 一维数组的初始化
- 对全部元素赋值
int a[10]={0,1,2,3,4,5,6,7,8,9};
这时[ ]中的10可以不写 - 对部分元素赋值
int a[10]={0,1,2,3,4};
系统自动给后5个元素赋初值为0 - 若想将数组元素全部赋值为0,可以对全部元素赋值,也可
int a[10]={0};
还可直接写空的大括号,如:int a[10]={};
- 在指定数组长度并初始化时,未被初始化的元素,如果是字符型数组,初始化为 ’\0’,如果是指针型数组,初始化为NULL,即空指针
int b, a[b];
是错误的,不能用变量说明数组大小
int a[10]; a[10]={0,1,2,3,4,5,6,7,8,9};
会导致编译错误。所以要么在定义时直接赋值,或者定义后用 for循环 读入数组。如:for(int i=0;i<10;i++)
{
a[i]=i;
printf("%d\t",a[i]);
}
1.3 一维数组的引用
格式:数组名[下标]。下标可以是整型常量或整型表达式。如:
a[0] = a[5]+a[7]-a[2*3]
a[i+j]
a[i++]
在C语言中只能逐个的使用下标变量,而不能一次引用整个数组。
#include<stdio.h>
int main()
{
int i,a[10]={1,2,3,4};
for(i=0;i<10;i++)
{
printf("%d\n",a[i]);
}
}
如果没有初始化,会导致输出不可知数。如:
//错误示范
#include<stdio.h>
int main()
{
int i,a[10];
for(i=0;i<10;i++)
{
printf("%d\n",a[i]);
}
}
2.二维数组
2.1 二维数组的定义
定义:<类型>变量名称[元素数量] [元素数量]。例如,
int a[3][5];
通常认为a是一个三行五列的矩阵。
a[0][0] | a[0][1] | a[0][2] | a[0][3] | a[0][4] |
a[1][0] | a[1][1] | a[1][2] | a[1][3] | a[1][4] |
a[2][0] | a[2][1] | a[2][2] | a[2][3] | a[2][4] |
2.2 二维数组的初始化
int a[][5] = {
{0,1,2,3,4},
{2,3,4,5,6}.
};
- 列数必须给出,行数可以由编译器来数出
- 每行一个 {} ,用逗号分离
- 最后的逗号可以存在
- 如果省略,表示补零
- 可以用定位
2.3 二维数组的引用
3.字符数组与字符串
3.1 字符串的输入输出
char string[8];
scanf("%s",string);
printf("%s",string);
scanf 读入一个单词(到空格、tap 或回车为止);
scanf 是不安全的,因为不知道要读入的内容和长度。
#include <stdio.h>
int main(void)
{
char word[8];
scanf("%s",word);
printf("%s##\n",word);
return 0;
}
#include <stdio.h>
int main(void)
{
char word[8];
char word2[8];
scanf("%s",word);
scanf("%s",word2);
printf("%s##%s##\n",word,word2);
return 0;
}
因此,限制读入个数来避免崩溃。
#include <stdio.h>
int main(void)
{
char word[8];
char word2[8];
scanf("%7s",word);//至多读前7个
scanf("%7s",word2);
printf("%s##%s##\n",word,word2);
return 0;
}
- char [8];
- scanf("%7s",string);
在%和s之间的数字表示最多允许读入的字符的数量,这个数字应该比数组的大小小一。
3.2 字符串函数
strlen
- size_t strlen(const char*s)
- 返回s的字符串长度(不包括结尾的0)
include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
char line[] = "Hello";
printf("strlen=%lu\n",strlen(line));
printf("sizeof=%lu\n",sizeof(line));
return 0;
}
strcmp
- int strcmp(const char *s1,const char *s2);
- 比较两个字符串,返回:
- 0:s1==s2
- 1:s1>s2
- -1:s1<s2
include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
char s1[] = "abc";
char s2[] = "abc";
printf("%d\n",strcmp(s1,s2));
return 0;
}
结果为0,表示比较的两个字符串相等。
若改成 char s2[] = "bbc";
,结果为 -1。意思是 s1<s2 。因为与b相比,a在字母表更前的位置,所以b比a大。
如果改成char s2[] = "Abc";
,结果为 1 。意思是 s1>s2 。因为小写字母比大写字母大。
但有些编译器会把两个字符的ASCII码之差作为比较结果由函数值返回。
如果加上空格char s2[] = "abc ";
,结果是 -1 。
有些编译器上,输出的是 -32 。
s1[ ] | a | b | c | \0 | |
s2[ ] | a | b | c | (space) | \0 |
即 '\0' - ' ' = 0 -32 = -32 。
strcpy
- char * strcpy(char *restrict dst, const char *restrict scr);
- 把 src 的字符串拷贝到 dst
- restrict 表明 src 和 dst 不重叠(C99)
- 返回 dst 为了能链接器代码
strcat
- char * strcat(char *restrict s1, const char *restrict s2);
- 把 s1 拷贝到 s2 后面,接成一个长字符串
- 返回 s1
- s1 必须有足够的空间
本来是这样的两个字符串:
src | a | b | \0 |
dst | c | d | \0 |
把 dst 的 '\0' 变成 src 的 a ,依次排下去,最后是 '\0' 。变成这样:
c | d | a | b | \0 |
这就是链接,实质上也是一种拷贝。
如果需要拷贝或者链接的地方没有足够的空间,strcpy 和 strcat 都可能出问题。
解决办法是使用安全版本 strncpy 和 strncat 。
strchr
- 字符串中找字符
- char * strchr(const char *s, int c);
- char * strrchr(const char *s,int c);
- 返回NULL表示没有找到
下一篇:07 指针基础