《C语言程序设计》读书笔记(第7章——数组)

按序排列同类型数据元素的集合称为数组。在C语言中,数组属于构造数据类型。数组中的数组元素可以是基本数据类型,也可以是构造类型。因此数组按元素类型的不同可分为:数值数组、字符数组、指针数组、结构数组等。

7.1 一维数组的定义和引用

7.1.1 一维数组的定义方式

在C语言中使用数组必须先定义,基本语法如下:

// 语法
类型说明符 数组名[常量表达式];

// 示例
int a[10];// 整型数组a,有10个元素
float b[20];// 浮点数数组,有10个元素
char c[20];// 字符数组,有20个元素

说明:

  • 类型说明符是任一种基本数据类型或构造数据类型。如intfloat等。
  • 数组名是用户定义的数组标识符。
  • 方括号中的常量表达式表示数据元素的个数,也称为数组的长度。

注意事项:

  • 数组的类型实际上是指数组元素的取值类型。对于同一个数组,其所有元素的数据类型都是相同的。如int a[20];中所有元素都是整型。
  • 数组名的书写规则应符合标识符的书写规定。
  • 数组名不能与其它变量名相同。如int a;float a[10];不能同名。
  • 方括号中常量表达式表示数组元素的个数,如a[5]表示数组a有5个元素。但是其下标从0开始计算。因此5个元素分别为a[0]、a[1]、a[2]、a[3]、a[4]。
  • 不能在方括号中用变量来表示元素的个数,但是可以是符号常数或常量表达式。如int n=5; int a[n];是错误的;如int a[3+2];是正确的。
  • 允许在同一个类型说明中,说明多个数组和多个变量。如int a,b,c,m[10],n[20];

7.1.2 一维数组元素的引用

数组元素是组成数组的基本单元。数组元素也是一种变量, 其标识方法为数组名后跟一个下标。下标表示了元素在数组中的顺序号,下标从0开始,以数组长度减去1结束。数组元素的语法如下:

数组名[下标]

说明:

  • 下标只能为整型常量或整型表达式。如为小数时,C编译将自动取整。如a[5]a[i+j]a[i++]都是合法的数组元素。
  • 数组元素通常也称为下标变量。必须先定义数组,才能使用下标变量。
  • 在C语言中只能逐个地使用下标变量,而不能一次引用整个数组,如int a[5]; printf("%d", a)是错误的。

示例:

#include <stdio.h>

int main() {
    // 定义数组
    int nums[10];
    // 给数组中所有元素赋值
    for (int i = 0; i < 10; i++) {
        nums[i] = i * 10;// 通过下标访问数组元素并且赋值
    }
    // 打印赋值后数组的所有元素
    for (int i = 0; i < 10; ++i) {
        printf("%d\t", nums[i]);
    }
}

7.1.3 一维数组的初始化

给数组赋值的方法有:

  • 利用赋值语句给数组元素逐个赋值。如nums[2]=22;
  • 初始化赋值。即在数组定义的同时给数组赋予初值,在编译阶段进行的,这样将减少运行时间,提高效率。
  • 动态赋值。

初始化赋值的语法如下:

// 语法,其中在{ }中的各数据值即为各元素的初值,各值之间用逗号间隔
类型说明符 数组名[常量表达式]={,, ...,};
// 示例
int a[10]={0,1,2,3,4,5,6,7,8,9};// 等价于a[0]=0;a[1]=1;...a[9]=9

数组初始化赋值的注意事项:

  • 可以只给部分元素赋初值。当{ }中值的个数少于元素个数时,只 给前面部分元素赋值。如int a[10]={0,1,2,3,4};表示只给a[0]~a[4]五个元素赋值,而后五个元素自动赋为零值。
  • 只能给元素逐个赋值,不能给数组整体赋值。如给数组是个元素全部赋为1值,只能写成:int a[10]={1,1,1,1,1,1,1,1,1,1};
  • 给全部元素赋值,可以不给出数组元素的个数。如int a[5]={1,2,3,4,5};可以写成int a[]={1,2,3,4,5};

示例:

#include <stdio.h>

int main() {
    // 定义数组
    int nums[10], max;
    // 从键盘输入10个数存入数组
    for (int i = 0; i < 10; ++i) {
        scanf("%d", &nums[i]);
    }
    // 然后计算数组中的最大值
    max = nums[0];
    for (int i = 0; i < 10; ++i) {
        if (nums[i] > max) {
            max = nums[i];
        }
    }
    // 打印结果
    printf("max=%d", max);
}

7.2 二维数组的定义和引用

7.2.1 二维数组的定义

C语言允许构造多维数组。多维数组元素有多个下标,以标识它在数组中的位置,所以也称为多下标变量。二维数组的定义语法如下:

// 语法
类型说明符 数组名[常量表达式1][常量表达式2];

// 示例
int a[3][4];

说明:

  • 量表达式1表示第一维下标的长度,常量表达式2 表示第二维下标的长度。如int a[3][4];表示一个三行四列的数组,数组名为a。
  • 注意,实际的硬件存储器却是连续编址的,也就是说存储器单元是按一维线性排列的。如何在一维存储器中存放二维数组,可有两种方式:一种是按行排列, 即放完一行之后顺次放入第二行。另一种是按列排列, 即放完一列之后再顺次放入第二列。在C语言中,二维数组是按行排列的。

7.2.2 二维数组元素的引用

引用二维数组元素的语法如下:

数组名[下标][下标]

说明:

  • 下标应为整型常量或整型表达式。如a[3][4]

示例:

#include <stdio.h>

int main() {
    // 设一个二维数组scores[5][3]存放五个人三门课的成绩。再设一个一维数组avg[3]存放所求得各分科平均成绩,设变量average为全组各科总平均成绩。
    int scores[5][3], avg[3], sum, average;
    for (int i = 0; i < 3; i++) {// 各科
        printf("请输入第%d科各人的成绩:\n", (i + 1));
        for (int j = 0; j < 5; j++) {// 各人
            printf("\t请输入第%d个人的成绩:", (j + 1));
            scanf("%d", &scores[j][i]);
            sum += scores[j][i];
        }
        avg[i] = sum / 5;
        sum = 0;
    }
    average = (avg[0] + avg[1] + avg[2]) / 3;// 计算各科总平均成绩
    printf("各分科平均成绩:%d, %d, %d\n", avg[0], avg[1], avg[2]);
    printf("各科总平均成绩:%d", average);
}

7.2.3 二维数组的初始化

二维数组初始化在数组定义的同时并进行赋值。二维数组可按行分段赋值,也可以按行连续赋值。如对数组a[5][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};
#include <stdio.h>

int main() {
    // 按行分段赋值
    int a[5][3] = {{80, 75, 92},
                   {61, 65, 71},
                   {59, 63, 70},
                   {85, 87, 90},
                   {76, 77, 85}};
    // 按行连续赋值
    int b[5][3] = {80, 75, 92, 61, 65, 71, 59, 63, 70, 85, 87, 90, 76, 77, 85};

    for (int i = 0; i < 5; ++i) {
        for (int j = 0; j < 3; ++j) {
            printf("%d\t", a[i][j]);
        }
        printf("\n");
    }
}

二维数组初始化赋值的注意事项:

  • 可以只对部分元素赋初值,未赋初值的元素自动取0值。如int a[3][3]={{1},{2},{3}};是对每一行的第一列元素赋值,未赋值的元素取0值。
  • 如对全部元素赋初值,则第一维的长度可以不给出。如int a[3][3]={1,2,3,4,5,6,7,8,9};可以写为int a[][3]={1,2,3,4,5,6,7,8,9};,因为第一维的长度可以计算出来。
  • 数组是一种构造类型的数据。二维数组可以看作是由一维数组的嵌套而构成的。设一维数组的每个元素都又是一个数组,就组成了二维数组。一个二维数组也可以分解为多个一维数组。如二维数组a[3][4]可以分解为三个一维数组,其数组名分别为:a[0]a[1]a[2]。并且这三个一维数组都有4个元素,例如:一维数组a[0]的元素为a[0][0]a[0][1]a[0][2]a[0][3]
  • a[0]a[1]a[2]不能当作下标变量使用,它们是数组名,不是一个单纯的下标变量。
#include <stdio.h>

int main() {
    // 可以只对部分元素赋初值,未赋初值的元素自动取0值
    int a[3][3] = {{1},
                   {2},
                   {3}};
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 3; ++j) {
            printf("%d\t", a[i][j]);
        }
        printf("\n");
    }

    // 如对全部元素赋初值,则第一维的长度可以不给出
    int b[][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
}
/*
    1       0       0
    2       0       0
    3       0       0
*/

7.3 字符数组

用来存放字符量的数组称为字符数组。

7.3.1 字符数组的定义

与前面定义数值数组的语法一样,如:

  • 定义一维字符数组:char c[10];
  • 定义二维或多维数组:char c[5][10];

7.3.2 字符数组的初始化

字符数组也可以在定义的同时就初始化赋值。如char c[12]={'h','e','l','l','o',' ', 'w', 'o', 'r', 'l', 'd'};

#include <stdio.h>

int main() {
    // 字符数组也允许在定义时作初始化赋值。
    char c[12] = {'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd'};

    for (int i = 0; i < 15; ++i) {
        printf("%c\t", c[i]);
    }

    // 也允许对全体元素赋初值时省去长度说明
    char d[] = {'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd'};
}

7.3.3 字符数组的引用

通过下标引用字符数组中的元素即可。

#include <stdio.h>

int main() {
    int i, j;
    char a[][5] = {{'B', 'A', 'S', 'I', 'C',},
                   {'d', 'B', 'A', 'S', 'E'}};

    for (i = 0; i <= 1; i++) {
        for (j = 0; j <= 4; j++) {
            printf("%c", a[i][j]);
        }
        printf("\n");
    }
}

7.3.4 字符串和字符串结束标志

在C语言中没有专门的字符串变量,通常用一个字符数组来存放一个字符串。当把一个字符串存入一个数组时,也把结束符'\0'存入数组,并以此作为该字符串是否结束的标志。有了'\0'标志后,就不必再用字符数组的长度来判断字符串的长度了。

C语言允许用字符串的方式对数组作初始化赋值。有下面三种方式:

  • char c[] = {'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd'};
  • char c[]={"hello world"};
  • char c[]="hello world";

注意,用字符串方式赋值比用字符逐个赋值要多占一个字节,因为需要存放字符串结束标志'\0'。所以上面的数组c在内存中的实际存放情况是:

helloworld\0

'\0'是由C编译系统自动加上的。由于采用了'\0'标志,所以在用字符串赋初值时一般无须指定数组的长度,而由系统自行处理。

7.3.5 字符数组的输入输出

除了上述用字符串赋初值的办法外,还可用printf函数和scanf函数一次性输出输入一个字符数组中的字符串,而不必使用循环语句逐个地输入输出每个字符。

  • 利用printf函数一次性输出字符串。
#include <stdio.h>

int main() {
    // 声明一个字符串
    char c[] = "hello world";
    // 利用%s一次性输出字符串
    printf("%s", c);
}
  • 利用scanf函数一次性输入字符串。
#include <stdio.h>

int main() {
    // 创建字符数组,用来存放字符串
    char str[15];
    // 一次性输入字符串
    scanf("%s", str);// 注意不是&str
    // 一次性输出字符串
    printf("%s", str);
}

当使用scanf函数一次性输入字符串时需要注意如下几点:

  • 对于定义一个字符数组,如果不初始化赋值,则必须声明数组长度。并且输入字符串的长度应该小于定义的数组的长度,以留出一个字节用于存放字符串结束标志'\0'
  • 当用scanf函数输入字符串时,字符串中不能含有空格,否则将以空格作为串的结束符。如输入hello world则只会保留hello
  • 注意scanf("%s", str);而不是scanf("%s", &str);,是直接传入了数组名。因为在C语言中规定,数组名代表了该数组的首地址,整个数组是以首地址开头的一块连续内存单元。因此scanf("%s", &str);是错误的。
  • 如设数组str的首地址为2000,即str[0]单元地址为2000,则数组名str就代表这个首地址,因此不能在str前面加地址运算符&。在执行函数printf("%s", str) 时,按数组名str找到首地址,然后逐个输出数组中各个字符直到遇到字符串终止标志'\0'为止。

7.3.6 字符串处理函数

C语言提供了丰富的字符串处理函数, 大致可分为字符串的输入、输出、合并、修改、比较、转换、复制、搜索几类。

  • 如果想要使用输入输出的字符串函数,则应该引入"stdio.h"库文件。
  • 如果想要使用其他字符串函数,则应该引入"string.h"库文件。

常用的字符串函数:

函数语法功能备注
字符串输出函数puts(字符数组名)把字符数组中的字符串输出到显示器。 即在屏幕上显示该字符串。puts函数完全可以由printf函数取代。当需要按一定格式输出时,通常使用printf函数。
字符串输入函数gets(字符数组名)从标准输入设备键盘上输入一个字符串。本函数得到一个函数值,即为该字符数组的首地址。并且gets函数并不以空格作为字符串输入结束的标志,而只以回车作为输入结束。这是与scanf函数不同的。
字符串连接函数strcat(字符数组名1, 字符数组名2)把字符数组2中的字符串连接到字符数组1 中字符串的后面,并删去字符串1后的串标志"\0"本函数返回值是字符数组1的首地址。要注意的是,字符数组1应定义足够的长度,否则不能全部装入被连接的字符串。
字符串拷贝函数strcpy(字符数组名1, 字符数组名2)把字符数组2中的字符串拷贝到字符数组1中。串结束标志"\0"也一同拷贝。字符数名2,也可以是一个字符串常量。这时相当于把一个字符串赋予一个字符数组。本函数要求字符数组1应有足够的长度,否则不能全部装入所拷贝的字符串。
字符串比较函数strcmp(字符数组名1, 字符数组名2)按照ASCII码顺序比较两个数组中的字符串,并由函数返回值返回比较结果。如果字符串1等于字符串2则返回值等于0;如果字符串1大于字符串2则返回值大于0;如果字符串1小于字符串2则返回值小于0。本函数也可用于比较两个字符串常量,或比较数组和字符串常量。
测字符串长度函数strlen(字符数组名)测字符串的实际长度(不含字符串结束标志'\0') 并作为函数返回值。无。

示例:

#include <stdio.h>
#include <string.h>

int main() {
    // 字符串输出函数 puts
    char c1[] = "hello\tworld";
    puts(c1);

    // 字符串输入函数 gets
    char c2[15];
    gets(c2);
    puts(c2);

    // 字符串连接函数 strcat
    char c3[] = "hello ";
    char c4[] = "world";
    strcat(c3, c4);
    puts(c3);

    // 字符串拷贝函数 strcpy
    char c5[15];
    char c6[] = "hello world";
    strcpy(c5, c6);
    puts(c5);

    // 字符串比较函数 strcmp
    char c7[] = "hello";
    char c8[] = "world";
    int r = strcmp(c7, c8);
    if (r == 0) {
        puts("c7=c8");
    } else if (r > 0) {
        puts("c7>c8");
    } else if (r < 0) {
        puts("c7<c8");
    }

    // 测字符串长度函数 strlen
    char c9[] = "hello world";
    int len = strlen(c9);
    printf("len=%d", len);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值