跳到内容

C 编程/数组和字符串

来自维基教科书,开放世界中的开放书籍
(重定向自 C 编程/数组)

C 语言中的数组用于在单个变量名下存储相关数据,并使用索引(也称为下标)。最简单地将数组视为相同类型变量的列表或有序分组。因此,数组通常有助于程序员有效且直观地组织数据集合。

稍后我们将考虑指向的概念,这是 C 语言的基础,它扩展了数组的性质(数组可以被称为常量指针)。目前,我们将只考虑它们的声明和用法。

C 语言中的数组以以下形式声明

type name[number of elements];

例如,如果我们想要一个包含六个整数(或整数)的数组,我们在 C 语言中编写

int numbers[6];

对于一个名为 letters 的六个字符数组,

char letters[6];

等等。

你也可以在声明时初始化。只需将初始元素放在花括号中,用逗号隔开,作为初始值

type name[number of elements]={comma-separated values}

例如,如果我们想用六个整数初始化一个数组,其中0, 0, 1, 0, 0, 0作为初始值

int point[6]={0,0,1,0,0,0};

虽然在这种情况下的初始化时,数组维度可以省略,并且数组将自动调整大小以容纳初始数据

int point[]={0,0,1,0,0,0};

这非常有用,因为数组的大小可以通过简单地添加或删除初始化元素来控制,而无需调整维度。

如果指定了维度,但未初始化数组中的所有元素,则剩余元素将包含值为 0。这非常有用,尤其是在我们有非常大的数组时。

int numbers[2000]={245};

上面的例子将数组的第一个值设置为 245,其余设置为 0。

如果我们想访问存储在数组中的变量,例如上面的声明,以下代码将把 1 存储在变量中x

int x;
x = point[2];

C 语言中的数组从 0 开始索引,而不是从 1 开始索引。上面数组的第一个元素是point[0]. 数组中最后一个值的索引是数组大小减一。在上面的例子中,下标从 0 到 5。C 语言不保证对数组访问进行边界检查。编译器可能不会抱怨以下情况(尽管最好的编译器会这样做)

char y;
int z = 9;
char point[6] = { 1, 2, 3, 4, 5, 6 };
//examples of accessing outside the array. A compile error is not always raised
y = point[15];
y = point[-4];
y = point[z];

在程序执行期间,数组越界访问并不总是会导致运行时错误。你的程序可能会在从 point[-1] 中检索到值后继续运行。为了缓解索引问题,sizeof() 表达式通常在编写处理数组的循环时使用。

许多人使用一个宏,它反过来使用 sizeof() 来查找数组中的元素数量,这个宏被各种命名为 "lengthof()"、[1] "MY_ARRAY_SIZE()" 或 "NUM_ELEM()"、[2] "SIZEOF_STATIC_ARRAY()"、[3] 等。

int ix;
short anArray[]= { 3, 6, 9, 12, 15 };
 
for (ix=0; ix< (sizeof(anArray)/sizeof(short)); ++ix) {
  DoSomethingWith("%d", anArray[ix] );
}

请注意,在上面的例子中,数组的大小没有显式指定。编译器知道将其大小设置为 5,因为初始化列表中有五个值。在列表中添加一个额外的值将导致它被设置为 6,并且由于在for循环中使用了 sizeof 表达式,代码会自动调整以适应此变化。良好的编程习惯是声明一个名为 size 的变量,并在其中存储数组中的元素数量。

size = sizeof(anArray)/sizeof(short)

C 语言还支持多维数组(或者更确切地说,数组的数组)。最简单的类型是二维数组。这将创建一个矩形数组 - 每行都有相同数量的列。为了在 C 语言中创建一个具有 3 行 5 列的字符数组,我们写

char two_d[3][5];

要访问/修改此数组中的值,我们需要两个下标

char ch;
ch = two_d[2][4];

two_d[0][0] = 'x';

类似地,多维数组可以像这样初始化

int two_d[2][3] = {{ 5, 2, 1 },
                   { 6, 7, 8 }};

列数必须显式声明;但是,编译器将根据初始化列表找到适当的行数。

还有一些可能的奇怪表示法

int a[100];
int i = 0;
if (a[i]==i[a])
{
  printf("Hello world!\n");
}

a[i] 和 i[a] 指的是同一个位置。(这将在下一章中详细解释。)

字符串

[编辑 | 编辑源代码]
存储在内存中的字符串 "Merkkijono"

C 语言没有内置的字符串处理功能;因此,字符串被定义为字符数组。C 语言允许用字符数组来表示字符字符串而不是字符列表,并在末尾自动添加空终止符。例如,要存储字符串 "Merkkijono",我们会写

char string[11] = "Merkkijono";

char string[11] = {'M', 'e', 'r', 'k', 'k', 'i', 'j', 'o', 'n', 'o', '\0'};

在第一个例子中,字符串将由编译器在末尾自动添加一个空字符;按照惯例,库函数期望字符串以空字符结尾。后面的声明表示单个元素,因此需要手动添加空终止符。

字符串并不总是必须与显式变量相关联。正如你已经看到的那样,可以直接创建一个字符字符串,作为直接使用的无名字符串(如 printf 函数)。

要创建一个很长的字符串,你必须将字符串分成多个部分,用引号结束第一个部分,并在下一行重新开始字符串(也用引号开头和结尾)

char string[58] = "This is a very, very long "
                "string that requires two lines.";

虽然字符串也可以通过在行尾加上反斜杠来跨越多行,但这种方法已过时。

有一个有用的字符串处理例程库,你可以通过包含另一个头文件来使用它。

#include <string.h>  //new header file

这个标准字符串库将允许对字符串执行各种任务,将在 字符串 章节中进行讨论。

参考资料

[编辑 | 编辑源代码]


华夏公益教科书