【C】C语言数组与字符串(包括:字符串与字符数组)
在程序设计中,为了方便处理,通常把具有相同类型的若干变量按有序的形式组织起来。这些按序排列的同类数据元素的集合称为数组。在C语言中,数组属于构造数据结构。一个数组可以分解成多个数组元素,这些数组元素可以是基本数据类型或是构造类型。因此按照数组元素的类型不同,数组又可分为数值数组、字符数组、指针数组、结构数组等各种类别。
本文主要介绍一维数组、二维数组和字符数组,其余的数组将会在以后的文章中介绍到。
数组概述
数组就是用来存储和处理一组相同类型的数据的。
数组在C语言中有着特殊的地位,它有很多的特性,比如它的存储是连续的、数组的名称是数组的地址等。
一维数组
一维数组是使用同一个数组名存储一组数据类型相同的数据,用索引或下标区别数组中的不同元素。
- 一维数组的定义方式为:
类型说明符 数组名[常量表达式]
在定义数组时,应该注意以下几点:
- 数组使用的方括号[],不是小括号;
- 常量表达式表示数据元素的个数,必须是一个正的整数值,不能含有变量,但是可以是符号常量或者常量表达式;
- 数组定义后,其长度不可更改。
- 一维数组的数据元素的一般形式为:
数组名[下标]
在引用数组元素时,应该注意以下几点:
- 一位数组元素的下标从0开始,最大下标为n-1;
- 在C语言中只能逐个地使用数组元素,而不能一次引用整个数组。
- 一维数组的初始化:除了用赋值语句对数组元素逐个赋值外,还可采用初始化赋值和动态赋值的方法。
初始化赋值的一般形式为:
类型说明符 数组名[常量表达式] = {初始值表};int a[5]={1,2,3,4,5};
在初始化赋值时,应该注意以下几点:
- 数组定义时初始化可以整体赋初值,但是除了定义初始化之外,不能整体赋值!
- 当初始值表给出全部元素值时,可以不给出数组元素的个数;
- 可以只给部分数组中的部分元素赋初始值(没有赋值的位将补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(但常量表达式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()函数的区别:
- puts()函数在遇到'\0'时,会自动转换成'\n'。而printf()函数则不输出'\0',同时也不输出'\n';
- 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'字符为止,函数值为一个整型。具体返回的情况如下表所示:
字符串大小情况 | 返回值 |
字符串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) 字符串指针变量本身是一个变量,用于存放字符串的首地址.而字符串本身是存放在以该首地址为首的一 ...
- php对象怎么拆分字符串数组,在PHP中将字符串拆分为Unicode字符数组的最佳方法是什么?...
在PHP中,将字符串拆分为Unicode字符数组的最佳方法是什么?如果输入不一定是UTF-8? 我想知道输入字符串中的Unicode字符集是否是另一组Unicode字符的子集. 为什么不直接运行mb_ ...
- 输入5个学生的名字(英文),使用冒泡排序按从大到小排序。 提示:涉及到字符串数组,一个字符串是一个一维字符数组;一个 字符串数组就是一个二维字符数组。...
输入5个学生的名字(英文),使用冒泡排序按从大到小排序. 提示:涉及到字符串数组,一个字符串是一个一维字符数组:一个 字符串数组就是一个二维字符数组. #include <stdio.h> ...
- java字符字节数组_【JAVA基础】字符数组与字节数组的区别
String.getBytes()和String.tocharArray(),字节数组和字符数组的区别 String.getBytes()是将字符串转化为一个字节数组.而String.toCharAr ...
- C++ 不能通过给字符数组名赋值的方法给字符数组赋值
已知有数组定义:char a[3][4]; 形如:"a[0] = "AAA";"的赋值语句是错误的,因为在C++中,无法通过给字符数组名赋值来实现给字符数组每一 ...
- c 将数字数组转成字符串_C+|用指针指向字符串字面量、字符数组及字符指针数组...
指针可以指向一个字符串字面量,可以指向一个字符数组,可以指向一块动态分配的内存单元: char *s1, *s2, *s3 = "abcde"; char ch[] = " ...
- 字符串常量是一个字符数组
1 #include<iostream>2 using namespace std;3 4 int main()5 {6 char var = '5';7 char *p_var;8 p_ ...
- C语言学习笔记---结构体中的字符数组和字符指针
在结构体中可以使用字符数组来存储字符串,也可以使用字符指针来存储字符串.比如: struct str{char s1[5];char s2[5];};struct str str1= {" ...
- 【C语言】将文本中汉字读入字符数组输出乱码
输出中文字符乱码 今天从文件中将中文读入字符数组后输出发现其中文变成了乱码,,令人头大. 解决办法 将文本编码格式改成ANSI即可. 打开记事本->文件->另存为->更改编码格式-& ...
- 指针指向字符串常量和给字符数组赋值字符串常量的本质
众所周知任何类型的指针在32位模式下大小都为4BYTE,很多人对数组和指针并不能很好的区分它们的区别,首先在C语言层面,数组名是一个常量不可修改,而指针可以随意指向,其次如果在a.cpp中定义了 ch ...
最新文章
- 基建狂魔:硬核技术之隔绝厌氧菌的涂料
- FSWD_3_JavaScriptAdvance
- [NIOS] 如何Erase EPCS flash內容
- Debina解决浏览器中乱码(将系统字体改为中文)
- 微服务【1.1】Swagger的使用
- 操作多个表_6_生成笛卡尔积
- java url特殊字符转义字符_URL中包含有特殊字符,进行转义
- 【转】Treeview 无限分类非递归终极解决方案
- jsp和html的作用域,JSP(二):JSP九大内置对象、四个作用域对象
- mac快速切换大小写_快速模式匹配–如果是大小写,请切换为大小写
- mysql information_schema库结构
- 京东商城选择地址信息
- 超级干货 :一文总览数据科学全景:定律、算法、问题类型...
- 基于JAVA电商购物商城系统设计与实现 开题报告
- 苹果外接屏幕鼠标移动方向问题
- 利用腾讯 优图visionseed硬件 实现人脸疲劳检测项目(包括数据读取,数据保存,数据web端展示)
- 7、A kernel method for multi-labelled classification
- 学习、恋爱、交朋友 大数据告诉你大学真相
- js分页列表找出最后一页的最后一条数据
- 神经网络处理器设计原理,神经网络控制系统设计