2018-2019-1 20189221 《从问题到程序》第 5 周学习总结

2018-2019-1 20189221 《从问题到程序》第 5 周学习总结

第六章 数据对象的顺序组合:数组

简洁性与方便性

数据机制基本框架通常包括下面几个互相联系的方面:

  • 把语言要处理的数据对象划分为一些类型,每个类型是一个数据值的集合。例如 C 语言里的int类型就是该类型能表示的所有整数值的集合。
  • 提供一组基本数据类型,确定其书写方式(文字量),提供一组基本操作(运算),支持基本数据对象的表示和使用。例如 C 语言的int、double等。
  1. 提供一组由简单数据类型或数据对象构造更复杂数据类型或数据对象的手段。反复使用这些手段可以构造出任意复杂的数据结构,以满足复杂数据处理的需要。这里提到的数据结构是计算机科学中的一个重要概念,也是一门后续计算机课程的名称。

数组的概念、定义和使用

数组(array)是 C 语言中用于组合同类型数据对象的机制。

数组机制要解决三个问题:

  • 描述数组的性质,定义数组变量;
  • 使用数组,包括通过数组变量使用元素;
  • 实现数组,即在内存里为数组安排一种存储方式,使程序里可以方便地操作它们。

定义数组需要说明两个问题:

  • 该数组(变量)的元素是什么类型的
  • 这个数组里包含多少个元素。

根据定义位置不同,数组也分为外部数组和函数内的局部数组,包括函数内的静态数组(用关键字static)和普通的自动数组,定义方式(及位置)决定了它们的作用域与存在期。

使用数组的基本操作是元素访问,对数组的使用 终都通过对元素的使用而实现。

标运算符[]是 C 语言里优先级 高的运算符之一,它的两个运算对象的书写形式比较特殊:一个运算对象写在方括号前面,应表示一个数组(简单情况是数组名);另一个应该是整型表达式,写在括号里面表示元素下标。

数组的真正意义在于它使我们可能以统一方式描述对一组数据的处理。

越界访问:用超出数组下标合法范围的下标表达式进行访问的现象.

越界访问的可能后果:

  • 在有些操作系统里,每个程序的合法数据访问范围受到严格监控。如果程序里的数据访问越出了程序数据区的范围,就会被这些操作系统认定为非法访问,从而导致一个动态错误,操作系统将强制性地终止造成这种错误的程序。
  • 另一些系统(如 DOS)里根本不检查程序访问地范围,但越界访问操作可能破坏这个程序本身的代码,甚至破坏系统里正在运行的其他软件,例如操作系统的子程序或数据结构。这通常会造成系统死机或出现其他莫名其妙的现象。
  • 即使数组越界访问没有超出本程序的合法数据区域,这种访问也是无意义的,甚至是很危险的。越界取得的数据显然不会是有意义的东西,在程序里使用这种数据没有任何价值。越界赋值则更加危险,即使这种操作没有被检查和禁止,其后果也是可怕的。这种赋值操作会破坏被赋值位置的原有数据,其后果难以预料,因为根本就无法知道被这个操作实际破坏的到底是什么。

外部数组和局部静态数组同样在程序开始执行前建立并初始化;局部自动数组也是在程序执行进入相应函数时建立和初始化。

数组的存储实现:

  • C 语言系统将为每个数组分配一个连续存储区域,其中足以存放数组的所有元素。各元素顺序排列,下标为 0 的元素排在 前面,每个元素占的空间相同。
  • int a[8];

数组程序实例

从字符到下标

写一个程序,统计由标准输入得到的文件中各数字字符出现的次数。


 int main () {     
	int c, i, cs[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 
	while ((c = getchar()) != EOF)         
	if (c >= '0' && c <= '9') 
            ++cs[c - '0']; 
for (i = 0; i < 10; ++i)         printf("Number of %d: %d ", i, cs[i]);     putchar('\n'); 
     return 0; 
} 

字符数组与字符串

字符数组也是数组,其定义方式与其他数组相同:

char line[1000]; 

标准库字符串处理函数

  1. 字符串长度函数strlen(const char s[])。本函数求出字符串的长度,也就是字符串里的字符个数。在计算字符个数时不计表示字符串结束的空字符。参数说明前面加了const修饰符说明函数执行中不会修改参数。

  2. 字符串复制函数 strcpy(char s[], const char t[])。本函数与前面定义 str_copy类似。第二个实参的应是字符串。strcpy把字符串t复制到s,s应是一个足够大的字符数组,以保证字符串复制不越界。下面是使用strcpy的例子:

char a1[20], a2[20]; 
... 
strcpy(a1, "programming"); 
... 
strcpy(a2, a1); 
... 

标准库还提供了一个字符串限界复制函数strncpy,使用形式与strcpy类似,增加了第三个int 类型的限界参数,用于限制复制的 大长度。字符串复制完毕或者达到限界长度时复制工作结束。例如:
strncpy(a1, s, 20);
把字符串s里 多 20 个字符复制到a1,如果s较短,a1的多余部分补满\0字符。
3. 字符串比较函数int strcmp(const char s1[], const char s2[])。在两个字符串s1和s2相同时返回 0;字符串s1大于字符串s2时返回一个正值(并没有规定采用什么值),否则就返回负值。判断字符串大小的标准是字典序。简单地说,字典序就是普通英语词典里排列单词词条时所用的顺序,其严格定义见下面文字框里的解
释。标准库还提供了一个限界比较函数,它只在给定范围内判断字符串的大小:

int strncmp(const char s1[], const char s2[], int n); 

返回值的规定与strcmp相同。
4. 字符串连接函数strcat(char s[], const char t[])。第二个实参应当是一个字符串,对应第一个参数s 的实参应是一个存放着字符串的字符数组。strcat 把作为第二个实参的字符串复制到这个实参字符数组中已有字符的后面,形成相当于两个串连在一起的字符串。这里也要求第一个实参数组足够大,使复制工作能合法完成。下面是函数使用的例子:
5.

char b1[40] = "Programming", b2[10]; strcat(b1, " language"); strcpy(b2, " C"); strcat(b1, b2); 

乘积矩阵的元素cij =∑nk=1aikbkj ,其中的aik 和bkj 分别是两个被乘矩阵的元素。求一个元素的乘积需要一个循环,完成整个矩阵乘积需要用一个三重循环。

#include <stdio.h> 
 
enum { N = 4 }; 
 
double A[N][N] = { ... ...}, /* 数组A和B的实际数据需要填充 */ 
       B[N][N] = { ... ...}, 
       C[N][N];   
 int main () {     int i, j, k;     double x; 
     for (i = 0; i < N; ++i)         for (j = 0; j < N; ++j) 
            for (C[i][j] = 0.0, k = 0; k < N; ++k) 
                C[i][j] += A[i][k] * B[k][j]; 
     for (i = 0; i < N; ++i)         for (j = 0; j < N; ++j) 
            printf("%f%c", C[i][j], j == N-1 ? '\n' :' '); 
 
    return 0; 
} 
posted @ 2018-11-16 08:19  古厉  阅读(130)  评论(0编辑  收藏  举报