在程序设计中,为了方便处理,通常把具有相同类型的若干变量按有序的形式组织起来。这些按序排列的同类数据元素的集合称为数组。在C语言中,数组属于构造数据结构。一个数组可以分解成多个数组元素,这些数组元素可以是基本数据类型或是构造类型。因此按照数组元素的类型不同,数组又可分为数值数组、字符数组、指针数组、结构数组等各种类别。

本文主要介绍一维数组、二维数组和字符数组,其余的数组将会在以后的文章中介绍到。

数组概述

数组就是用来存储和处理一组相同类型的数据的。

数组在C语言中有着特殊的地位,它有很多的特性,比如它的存储是连续的、数组的名称是数组的地址等。

一维数组

一维数组是使用同一个数组名存储一组数据类型相同的数据,用索引或下标区别数组中的不同元素。

  • 一维数组的定义方式为:
类型说明符 数组名[常量表达式]

在定义数组时,应该注意以下几点:

  1. 数组使用的方括号[],不是小括号;
  2. 常量表达式表示数据元素的个数,必须是一个正的整数值,不能含有变量,但是可以是符号常量或者常量表达式;
  3. 数组定义后,其长度不可更改。
  • 一维数组的数据元素的一般形式为:
数组名[下标]

在引用数组元素时,应该注意以下几点:

  1. 一位数组元素的下标从0开始,最大下标为n-1;
  2. 在C语言中只能逐个地使用数组元素,而不能一次引用整个数组。
  • 一维数组的初始化:除了用赋值语句对数组元素逐个赋值外,还可采用初始化赋值和动态赋值的方法。

初始化赋值的一般形式为:

类型说明符 数组名[常量表达式] = {初始值表};int a[5]={1,2,3,4,5};

在初始化赋值时,应该注意以下几点:

  1. 数组定义时初始化可以整体赋初值,但是除了定义初始化之外,不能整体赋值!
  2. 当初始值表给出全部元素值时,可以不给出数组元素的个数;
  3. 可以只给部分数组中的部分元素赋初始值(没有赋值的位将补0)。也就是说可以这样:
int a[]={1,2,3,4,5};
int b[5]={1,2,3};

二维数组

  • 二维数组定义的一般形式为:
类型说明符 数组名[常量表达式1][常量表达式2];

二维数组被定义后,编译系统将为该数组在内存中分配一片连续的存储空间,按行的顺序连续存储数组的各个元素。即先顺序存储第一行元素,再存储第二行元素……直到存储最后一行元素。数组名代表着数组的起始地址。

  • 二维数组元素引用的基本语法格式为:
数组名[下标][下标]
  • 初始化赋值的一般形式为:
类型说明符 数组名[常量表达式1][常量表达式2] = {初始值表};int a[3][4] = { { 1,2,3,4 },{ 5,6,7,8 },{ 9,0,1,2 } };

由于二维数组在内存中是按照线性顺序存储的,所以内存括号可以省去,不会产生影响。也就是说可以这样:

int a[3][4] = { 1,2,3,4,5,6,7,8,9,0,1,2 };

在初始化赋值时,应该注意以下几点:

  1. 当初始值表给出全部元素值时,可以不给出二维数组的常量表达式1(但常量表达式2必须给);
  2. 可以只给部分数组中的部分元素赋初始值(没有赋值的位将补0)。也就是说可以这样:
int a[][4] = { { 1,2,3,4 },{ 5,6,7,8 },{ 9,0,1,2 } };
int a[][4] = { 1,2,3,4,5,6,7,8,9,0,1,2 };
int b[3][4] = { { 1 },{ 5 },{ 9 } };

在这里,省去3是可以的,但是4不能省去的。编译器会根据所附的数值的个数以及数组的列数,自动计算出数组的行数。

数组是一种构造类型的数据。二维数组可以看作是由一维数组的嵌套而构成的。设一维数组的每个元素都是一个数组,就组成了二维数组。当然前提是各元素的类型必须相同。根据这样的分析,一个二维数组也可以分解成多个一维数组。C语言允许这样的分解。如二维数组a[3][4],可以分解成3个一维数组,a[0]、a[1]、a[2]。

数组与链表的区别:

  • 从逻辑结构上来看,数组必须实现定义固定的长度,不能适应数据动态增减的情况。当数据增加时,可能会造成空间的不够;当数据减少时,可能造成空间浪费。而链表动态地进行存储分配,可以适应数据动态增减的情况,方便插入和删除;
  • 从内存储存上来看,数组从栈中分配空间,方便快捷,但自由度小。而链表从堆中分配空间,自由度大,但申请管理比较麻烦。

字符数组与字符串

字符数组的说明与初始化

用于存放字符的数组称为字符数组,它是数组的一种特殊类型,字符数组的每个元素存放一个字符。

  • 字符数组的定义的一般形式为:
char 数组名[常量表达式];
char 数组名[常量表达式1][常量表达式2];
  • 字符数组的初始化:除了数组的基本初始化方式外,字符数组还可以使用字符串常量初始化。
char a[5]={'a','b','c','d','e'};
char a[]={'a','b','c','d','e'};

把一个字符串存入一个数组时,也会将结束符'\0'存入数组,并以此作为该字符串是否结束的标志。有了'\0'标志后,就不必再用字符数组的长度来判断字符串的长度了。

用字符串方式赋值比用字符逐个赋值要多占1个字节,用于存放字符串结束标志'\0'。以下三种初始化的效果是一样的:

char b[]={"How are you"};
char b[]="How are you";
char b[]={'H','o','w',' ','a','r','e',' ','y','o','u','\0'};

同时,需要注意:字符数组可以使用在定义初始化的时候用字符串初始化,但是不能使用赋值语句整体赋值:

char c[11] = "How are you";            /* 正确 */
char c[11];
c = "How are you";            /* 错误 */

为了证实'\0'的存在,例如:

#include<stdio.h>int main()
{int i;char c[] = "How are you!";for (i = 0;; i++) {if (c[i] == '\0')break;}printf("%d\n", i);return 0;
}

最终结果输出12,代表字符数组下标为12的字符是'\0',这与我们的理论是一致的。

字符串和字符数组

C语言中没有专门的字符串变量,如果要将一个字符串存放到某一个变量中,必须使用字符数组,即用一个字符数组来存放一个字符串,数组中每个元素存放一个字符。

  • 字符串:必须以'\0'结尾;
  • 字符数组:可以包含多个'\0',也可以不包含'\0'。

字符串的处理函数

在采用字符串方式后,字符数组的输入/输出变得更加简单方便。除了可以使用字符串对字符数组赋初值的方法外,还可以用printf()函数和scanf_s()函数一次性输入/输出一个字符数组的所有字符,而不必利用循环单个操作。

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

在使用输入/输出的字符串函数之前,需要包含头文件stdio.h;使用其他字符串函数之前,需要包含头文件string.h;

由于没有字符串变量这个说法,所以对任何字符串的操作都是将它放在字符数组里。

  • 字符串输入函数gets()

从键盘上输入一个字符串(包括空格),赋予从字符数组起始的存储单元,直到读入一个回车符为止。回车符读入后,不作为字符串的内容,系统将自动用'\0'替换,作为字符串结束的标志。

char c[20];
gets(c);
  • 字符串输出函数puts()

将字符数组起始地址开始的第一个字符串(以'\0'结束的字符序列)输出到显示器,并将字符串结束标志'\0'自动转换成'\n'。

char c[]="Hello!";
puts(c);

区分printf()与puts()、scanf_s()与gets()函数的区别:

  1. puts()函数在遇到'\0'时,会自动转换成'\n'。而printf()函数则不输出'\0',同时也不输出'\n';
  2. gets()函数接受字符串,读入换行符才停止。而scanf_s()函数则读入到空格或者换行符就停止。
  • 字符串长度函数strlen()

测试字符数组起始地址开始的字符串(以'\0'结束的字符序列)有效长度,此长度不包括'\0'在内。

char c[]="Hello";
printf("%d",strlen(c));
  • 字符串连接函数strcat()
strcat(字符数组1,字符数组2);

将字符数组2连接到字符数组1之后,函数值为字符数组1的起始地址。连接字符数组1和字符数组2的尾部都有一个'\0',连接时将字符数组1后的'\0'自动取消,字符数组2后的'\0'一并连接到字符数组1后。

这里还有一个注意点:

#include<stdio.h>int main()
{char c1[20] = "Hello ";        /* 这里必须要指定足够的长度,否则会报错! */char c2[] = "World!";printf("%s", strcat(c1, c2));return 0;
}

字符数组1必须要足够长度,以便在其有效字符后能够容纳字符数组2的字符串。

  • 字符串复制函数strcpy()
strcpy(字符数组1,字符数组2);

将字符数组2复制到字符数组1中去,函数值为字符数组1的起始地址。字符数组1的长度能够容纳字符数组2的长度;将字符数组2的字符串结束标志'\0'一起复制到字符数组1中去了;同时,strcpy()函数能够将字符数组2前面若干个字符复制到字符数组1中,例如:

strcpy(字符数组1,字符数组2,长度);
  • 字符串比较函数strcmp()
strcmp(字符数组1,字符数组2);

将两个字符数组自左向右对应的字符逐个进行比较(按照ASCII码值大小比较),直到出现不同的字符或者遇到'\0'字符为止,函数值为一个整型。具体返回的情况如下表所示:

strcmp函数返回值
字符串大小情况 返回值
字符串1等于字符串2 0
字符串1大于字符串2 1
字符串1小于字符串2 -1

关于数组的小例子

1、杨辉三角形:

#include<stdio.h>int main()
{int a[10][10],i,j;for (i = 0; i < 10; i++) {a[i][0] = 1;a[i][i] = 1;}for (i = 2; i < 10; i++) {for (j = 1; j < i; j++) {a[i][j] = a[i - 1][j - 1] + a[i - 1][j];}}for (i = 0; i < 10; i++) {for (j = 0; j < i+1; j++) {printf("%d ", a[i][j]);}printf("\n");}return 0;
}

这段程序的运行结果为:

1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
请按任意键继续. . .

2、找出下面程序中的错误:

#include<stdio.h>int main()
{unsigned char a[256], i;for (i = 0; i < 256; i++) {a[i] = i;}return 0;
}

unsigned char的取值范围为0-255,当i最大为255的时候,下次循环i++,i就变成了0,造成无限循环。

【C】C语言数组与字符串(包括:字符串与字符数组)相关推荐

  1. 第十节 字符串指针变量与字符数组的区别(十一)

    用字符数组和字符指针变量都可实现字符串的存储和运算.但是两者是有区别的.在使用时应注意以下几个问题: 1) 字符串指针变量本身是一个变量,用于存放字符串的首地址.而字符串本身是存放在以该首地址为首的一 ...

  2. php对象怎么拆分字符串数组,在PHP中将字符串拆分为Unicode字符数组的最佳方法是什么?...

    在PHP中,将字符串拆分为Unicode字符数组的最佳方法是什么?如果输入不一定是UTF-8? 我想知道输入字符串中的Unicode字符集是否是另一组Unicode字符的子集. 为什么不直接运行mb_ ...

  3. 输入5个学生的名字(英文),使用冒泡排序按从大到小排序。 提示:涉及到字符串数组,一个字符串是一个一维字符数组;一个 字符串数组就是一个二维字符数组。...

    输入5个学生的名字(英文),使用冒泡排序按从大到小排序. 提示:涉及到字符串数组,一个字符串是一个一维字符数组:一个 字符串数组就是一个二维字符数组. #include <stdio.h> ...

  4. java字符字节数组_【JAVA基础】字符数组与字节数组的区别

    String.getBytes()和String.tocharArray(),字节数组和字符数组的区别 String.getBytes()是将字符串转化为一个字节数组.而String.toCharAr ...

  5. C++ 不能通过给字符数组名赋值的方法给字符数组赋值

    已知有数组定义:char a[3][4]; 形如:"a[0] = "AAA";"的赋值语句是错误的,因为在C++中,无法通过给字符数组名赋值来实现给字符数组每一 ...

  6. c 将数字数组转成字符串_C+|用指针指向字符串字面量、字符数组及字符指针数组...

    指针可以指向一个字符串字面量,可以指向一个字符数组,可以指向一块动态分配的内存单元: char *s1, *s2, *s3 = "abcde"; char ch[] = " ...

  7. 字符串常量是一个字符数组

    1 #include<iostream>2 using namespace std;3 4 int main()5 {6 char var = '5';7 char *p_var;8 p_ ...

  8. C语言学习笔记---结构体中的字符数组和字符指针

      在结构体中可以使用字符数组来存储字符串,也可以使用字符指针来存储字符串.比如: struct str{char s1[5];char s2[5];};struct str str1= {" ...

  9. 【C语言】将文本中汉字读入字符数组输出乱码

    输出中文字符乱码 今天从文件中将中文读入字符数组后输出发现其中文变成了乱码,,令人头大. 解决办法 将文本编码格式改成ANSI即可. 打开记事本->文件->另存为->更改编码格式-& ...

  10. 指针指向字符串常量和给字符数组赋值字符串常量的本质

    众所周知任何类型的指针在32位模式下大小都为4BYTE,很多人对数组和指针并不能很好的区分它们的区别,首先在C语言层面,数组名是一个常量不可修改,而指针可以随意指向,其次如果在a.cpp中定义了 ch ...

最新文章

  1. 基建狂魔:硬核技术之隔绝厌氧菌的涂料
  2. FSWD_3_JavaScriptAdvance
  3. [NIOS] 如何Erase EPCS flash內容
  4. Debina解决浏览器中乱码(将系统字体改为中文)
  5. 微服务【1.1】Swagger的使用
  6. 操作多个表_6_生成笛卡尔积
  7. java url特殊字符转义字符_URL中包含有特殊字符,进行转义
  8. 【转】Treeview 无限分类非递归终极解决方案
  9. jsp和html的作用域,JSP(二):JSP九大内置对象、四个作用域对象
  10. mac快速切换大小写_快速模式匹配–如果是大小写,请切换为大小写
  11. mysql information_schema库结构
  12. 京东商城选择地址信息
  13. 超级干货 :一文总览数据科学全景:定律、算法、问题类型...
  14. 基于JAVA电商购物商城系统设计与实现 开题报告
  15. 苹果外接屏幕鼠标移动方向问题
  16. 利用腾讯 优图visionseed硬件 实现人脸疲劳检测项目(包括数据读取,数据保存,数据web端展示)
  17. 7、A kernel method for multi-labelled classification
  18. 学习、恋爱、交朋友 大数据告诉你大学真相
  19. js分页列表找出最后一页的最后一条数据
  20. 神经网络处理器设计原理,神经网络控制系统设计

热门文章

  1. 步进电机和交流伺服电机性能比较
  2. DevOps工具链学习——相关工具知多少
  3. 手把手教你阿里云如何进行网站备案(图文教程)
  4. MySQL主从一致的校验
  5. HDU2527 Safe Or Unsafe(哈夫曼的一道简单题)
  6. 简历上的照片怎么制作?这两种方法真的很简单
  7. 【日语】日语学习计划(转载)
  8. 百度统计中的索引量和site:命令的百度收录量不一致的原因
  9. mser python车牌识别_基于MSER与SVM算法的车牌定位识别方法
  10. c语言在数学方面的应用编程,浅谈数学在C语言编程中的应用.doc