目录
数组的概念
数组是一种数据类型,它可以存储相同类型的多个元素。数组可以通过一个名称和一个索引来引用其中的一个元素。
类型:数组按照下标个数来区分,可以分为一维数组和多维数组(如二维数组、三维数组等),本篇我们主要复习一维数组和二维数组。
一维数组的定义、初始化及访问
定义数组(声明一个数组)
声明一个数组需要指定数组的类型、名称和大小,一般形式如下。
数据类型 数组名[整型常量表达式]
eg:
int arr[5]; //声明一个包含 5个整数的数组
声明数组时,可以使用值常量,也可以使用符号常量定义数组的长度。例如:
float s[5];
#define N 5
float s[N];
const int n=5;
float s[n];
注:
1.定义数组时必须声明数组长度,下标范围[0~长度-1]
2.不可使用变量说明长度,即使变量已被初始化,元素数量必须是编译阶段确定的常量。
初始化数组
数组也可以像其他简单类型变量一样被赋初值。初始化数组可以在声明的同时进行,也可以在后面赋值。
·声明的同时初始化
一般初值应被组织在花括号{}中。
1.全部元素赋初值时,数组长度可省略。例如:
int a[5]={0,2,4,6,8};
也可写为:
int a[]={0,2,4,6,8};//依次赋给a[0]~a[4]的元素
2.部分元素赋初值时,未被赋值元素默认为0.
·后面赋值
int arr3[4];
arr3[0] = 10;
arr3[1] = 20;
arr3[2] = 30;
arr3[3] = 40;
注:
1.数组必须先定义后使用;
2.数组名不能和程序中的其他变量同名;
3.数据集合中的数据个数不能超过数组长度。
访问数组
访问数组元素需要使用下标,数组的第一个元素的下标为0,最后一个元素的下标为数组长度减1。访问形式:数组名[下标] 例如:
int arr[3] = {10, 20, 30};
int x = arr[0]; //将x设置为数组的第一个元素(10)
arr[1] = 50; //将数组的第二个元素设置为50
注:
1.不能整体使用数组中的元素,即不能将数据集合赋给数组;
2.对数组名不允许进行“++”或“--”运算。
二维数组的定义、初始化及访问
形式上有行有列的数据结构更适合用二维数组来描述。
定义数组
定义形式为: 数据类型 数组名[常量表达式1][常量表达式2];
datatype arrayname[row][column];
//其中datatype为数据类型,arrayname为数组名称,row和column分别指定了二维数组的行数和列数。
二维数组在内存中“按行”存放,一行元素储存完毕后再存储下一行。
初始化数组
对于二维数组的初始化,需要在定义时指定每个元素的值,具体方式如下:
datatype arrayname[row][column] = { {val1, val2, ...}, {val1, val2, ...}, ... };
其中,每一对花括号表示二维数组中的一行,每一组大括号内部的值用逗号隔开,表示该行中每个元素的值。
访问数组
二维数组的引用形式为:数组名[行下标][列下标]
因为含双下标,批量处理时需两重循环控制下标的变化。往往外循环控制行下标,内循环控制列下标。
例如,假设有一个名为matrix的二维数组,我们要访问第2行第3列的元素,可以使用以下代码:
int value = matrix[1][2]; // 注意索引从0开始计数,因此第2行实际上是第1行
同样,也可以使用下标对二维数组中的元素进行赋值操作:
matrix[1][2] = 10; // 将第2行第3列的元素设置为10
数组的常见算法
问题只做举例,不在此处详细展开,后续可在专题“C语言练习”查看。
一维数组
排序问题(选择法排序和冒泡法排序)、插入与删除问题、查找问题、最值问题、输出控制。
二维数组
与双重循环的配套使用、纳什均衡——求解矩阵的鞍点。
字符数组及字符串处理
文本数据处理
字符串常量是用双引号引起的一串字符。如“Go ahead!”,在内存中存储时系统会自动在最后一个字符“!”的末尾加一个字符“\0”,该字符被称为字符串结束符,标志字符串的结尾。
对于逐个字符赋初值:
以“\0”结尾,为字符串,可直接全部输出;%s
未以“\0”结尾,为字符数组,只能逐一使用;%c
(若有数组s[10,给前9个赋值,则末尾自动添加“\0”)
字符数组处理字符串的方法
·初始化
#有以下两种初始化形式
char s[20]={"go ahead!"};
char s[20]="go ahead!";
s代表了字符串在内存中存放的首地址,系统会自动在末尾添加“\0”。如果像数值型数组那样逐元素初始化,则不代表字符串。
·输入
假设有定义
char s[20];
可通过如下两个函数输入字符串:
scanf("%s",s);//不能提取 s中空白符后面的内容。
gets(s);//适用于输入包含空格、制表符等空白符在内的字符串时采用。
·输出
字符串的输出不同于一般数组,需整体输出,方法有如下两种:
printf("%s",s);
puts(s);//自动换行输出
输入输出字符串的函数gets和puts的原型说明在stdio.h中。
字符串的常见处理
·从身份证号码中提取生日信息
·字符串比较
常用字符串处理函数
为处理方便,系统提供了包括字符串连接、复制、比较等功能在内的一系列字符串处理函数。
常用库函数如下:
函数名称 | 函数原型 | 功能 |
---|---|---|
strlen | int strlen(char *str) | 获取字符串长度,不包括‘\0’在内 |
strcpy | char *strcpy(char *str1, char *str2) | 复制字符串str2的内容到str1 |
strcat | char *strcat(char *str1, char *str2) | 连接字符串str2的内容到str1后面 |
strcmp | int strcmp(char *str1, char *str2) | 比较字符串大小,从左至右逐字符比较ASCII码值,直到出现不相同字符或出现“\0”为止 |
strupr | char *strupr(char *str) | 将字符串str中的小写字母转换成大写字母 |
strlwr | char *strlwr(char *str) | 将字符串str中的大写字母转换成小写字母 |
atoi | int atoi(const char *nptr) | 将字符串转换为整数 |
补充:有关字符串比较函数strcmp
str1 小于 str2 返回-1
str1 等于 str2 返回0
str1 大于 str2 返回1
这些函数的原型说明在头文件string.h中。处理复制和连接两个函数中的第一个参数不能取字符串常量外,其他的参数都可以为字符数组、字符指针变量和字符串常量。
指针与数组关系初步
指针的算数运算
C语言中指针的算数运算可以使用加、减、自增和自减四种运算符。这些运算符作用于指针时,会根据指针所指向的数据类型确定指针移动的距离。
以下是指针算术运算符的详细介绍:
加法运算(+):
将一个整数值加到指针变量中,指针变量将会向前移动相应的字节数。例如:
int arr[5] = {1, 2, 3, 4, 5};
int *p = arr; // p 指向数组的第一个元素
p = p + 2; // 将 p 向前移动两个 int 类型占用的字节数
printf("%d", *p); // 输出 3
减法运算(-):
将一个整数值从指针变量中减去,指针变量将会向后移动相应的字节数。例如:
int arr[5] = {1, 2, 3, 4, 5};
int *p = &arr[4]; // p 指向数组的最后一个元素
p = p - 2; // 将 p 向后移动两个 int 类型占用的字节数
printf("%d", *p); // 输出 3
自增运算(++):
将指针变量的值增加一个指针类型的距离,指针变量将会指向下一个元素。例如:
int arr[5] = {1, 2, 3, 4, 5};
int *p = arr; // p 指向数组的第一个元素
p++; // 将 p 向前移动一个 int 类型占用的字节数
printf("%d", *p); // 输出 2
自减运算(--):
将指针变量的值减少一个指针类型的距离,指针变量将会指向上一个元素。例如:
int arr[5] = {1, 2, 3, 4, 5};
int *p = &arr[4]; // p 指向数组的最后一个元素
p--; // 将 p 向后移动一个 int 类型占用的字节数
printf("%d", *p); // 输出 4
指针变量相减:
两个相同类型(指都指向同一块连续的内存空间)的指针变量可以相减,具体来说,如果有两个指针变量p和q,它们分别指向内存中的两个位置,那么p-q的结果将是一个整数,表示从p到q之间的距离(以字节为单位)。这个距离可以是正数、零或负数,取决于p和q指向内存中的实际位置。
此外,在对指针变量进行减法运算前,应该确保这些指针已经被初始化并指向有效的内存位置,否则可能会导致未定义的行为和内存错误。
以下是一个简单的示例代码,展示了指针变量相减的用法:
#include <stdio.h>
int main()
{
int arr[5] = {1, 2, 3, 4, 5};
int *p = &arr[2];
int *q = &arr[4];
printf("p - q = %ld", p - q);
printf("q - p = %ld", q - p);
return 0;
}
输出结果为:
在这个例子中,我们定义了一个整数数组arr,并让指针变量p和q分别指向arr[2]和arr[4]。然后我们计算了p和q之间的地址差值,并使用printf函数进行输出。由于p指向arr[2],q指向arr[4],因此它们之间的距离是2个int类型数据的大小,即8个字节。由于p在q之前,所以p-q的结果是负数-2,而q-p的结果是正数2。
需要注意的是,指针算术运算不应该超出所指向的数据结构的范围。否则可能导致错误的结果和程序崩溃。因此,在进行指针算术运算时,一定要小心谨慎。
数组元素的指针表示法
数组元素的访问方式有如下三种:
1.下标方式:数组名[下标]
2.地址方式:*(地址)
3.指针方式:*指针
我们可以通过下标运算符[]来获取数组元素的值,并且可以使用指针来表示数组元素。例如,如果我们有一个整数类型的数组a,我们可以使用以下代码来获取第i个元素的值:
int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int *p = &a[0]; // 获取数组首元素地址
int i = 3;
int value = *(p + i); // 获取第4个元素的值
在上面的代码中,我们首先定义了一个整数类型的数组a,并且初始化了数组的值。然后我们定义了一个指向整型的指针p,该指针指向数组a的首元素地址。最后,我们使用指针表示数组元素时,通过指针的加法运算,得到第i个元素的地址,并且使用解引用运算符*获取该元素的值。