字符串的存储方式有字符数组和字符指针,我们先来看看字符数组。

因为字符串是由多个字符组成的序列,所以要想存储一个字符串,可以先把它拆成一个个字符,然后分别对这些字符进行存储,即通过字符数组存储。字符数组是一个数组,且是存储字符的数组,该数组中一个元素存放字符串的一个字符。

字符数组的定义

因为字符数组首先是一个数组,所以前面讲的数组内容通通都适用。其次它是存放字符的数组,即数组的类型是 char 型。比如:

  1. char name[10];

表示定义了 10 字节的连续内存空间。

1) 如果字符串的长度大于 10,那么就存在语法错误。这里需要注意的是,这里指的“字符串的长度”包括最后的 '\0'。也就是说,虽然系统会自动在字符串的结尾加 '\0',但它不会自动为 '\0' 开辟内存空间。所以在定义数组长度的时候一定要考虑 '\0'。

2) 如果字符串的长度小于数组的长度,则只将字符串中的字符赋给数组中前面的元素,剩下的内存空间系统会自动用 \0' 填充。

字符数组的初始化

字符数组的初始化与数组的初始化一样,要么定义时初始化,要么定义后初始化。下面写一个程序来说明这个问题:

# include <stdio.h>
int main(void)
{
char a[];
a[] = 'i'; a[] = ' '; a[] = 'l'; a[] = 'o'; a[] = 'v';
//空格字符的单引号内一定要敲空格
a[] = 'e'; a[] = ' '; a[] = 'y'; a[] = 'o'; a[] = 'u';
//空格字符的单引号内一定要敲空格
a[] = '\0';
char b[];
b[] = 'i'; b[] = ' '; b[] = 'm'; b[] = 'i'; b[] = 's';
//空格字符的单引号内一定要敲空格
b[] = 's'; b[] = ' '; b[] = 'y'; b[] = 'o'; b[] = 'u';
//空格字符的单引号内一定要敲空格
char c[] = "i believe you";
char d[] = {'i', ' ', 'l', 'i', 'k', 'e', ' ', 'y', 'o', 'u','\0'};
//空格字符的单引号内一定要敲空格
char e[] = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd'};
//空格字符的单引号内一定要敲空格
char f[] = "上课睡觉觉, 下课打闹闹, 考试死翘翘";
char g[] = "";
printf("a = %s\n", a); //输出字符串用%s, 输出参数必须写数组名
printf("b = %s\n", b);
printf("c = %s\n", c);
printf("d = %s\n", d);
printf("e = %s\n", e);
printf("f = %s\n", f);
printf("g = %s\n", g);
return ;
}

输出结果是:

a = i love you
b = i miss you烫i love you
c = i believe you
d = i like you
e = Hello World蘨 like you
f = 上课睡觉觉, 下课打闹闹, 考试死翘翘
g =
mac下输出:


首先要说明的是,这个程序只有在 .cpp 文件中才能运行,在 .c 文件中会有很多错误。因为我们在前面讲过,C89 标准规定变量的定义只能在程序的开头,或者说定义变量的前面不能有其他非声明或非定义的语句。而 .cpp 文件是编写 C++ 程序的,C++ 向下完全兼容 C,而且它对变量定义的位置没有特殊要求,只要在使用位置之前即可。

数组 a 是先定义后初始化。一方面与以前讲的数值型数组一样,先定义后初始化必须一个一个地进行赋值,不能整体赋值;另一方面与以前讲的数值型数组又不一样,对于字符串,先定义后初始化也可以整体赋值,但是要调用 strcpy 函数,这点稍后再讲。

总之上面这个程序中给数组 a 一个一个进行初始化的方式很麻烦。而且这样写需要注意:前面讲过系统会在字符串的最后自动添加结束标志符 '\0',但是当一个一个赋值时,系统不会自动添加 '\0',必须手动添加。如果忘记添加,虽然语法上没有错误,但是程序将无法达到我们想要的功能。数组 b 就是这样的例子。

此外,空格字符必须要在单引号内“敲”一个空格,不能什么都不“敲”,什么都不“敲”就是语法错误。也不能多“敲”,因为一个单引号内只能放一个字符,“敲”多个空格就是多个字符了。

数组b就是最后没有手动添加 '\0' 的例子。程序是希望数组 b 输出“i miss you”,但输出结果是“i miss you烫i love you”。原因就是系统没有在最后添加'\0'。

虽然程序中对数组 b 的长度进行了限制,即长度为 10,但是由于内存单元是连续的,对于字符串,系统只要没有遇到 '\0',就会认为该字符串还没有结束,就会一直往后找,直到遇到 '\0' 为止。被找过的内存单元都会输出,从而超出定义的 10 字节。

数组 c 是定义时初始化。定义时初始化可以整体赋值。整体赋值有一个明显的优点——方便。定义时初始化可以不用指定数组的长度,而先定义后初始化则必须要指定数组的长度,如数组 a 和数组 b。不用指定数组长度有一个好处:不用人为确定需要多少字节的内存空间,系统会根据初始化的内容自动分配数量正好的内存空间。而且对于数组 c 的写法系统会自动在最后添加结束标志符 '\0',不需要人为添加。

数组 d 也是定义时初始化,但它既属于整体赋值,也属于一个一个赋值。说它是整体赋值是因为不用写 d[0]、d[1]…而说它是一个一个赋值是因为它把整个句子分成了一个一个的字符。还是数组 c 的写法比较方便,而且对于数组d的写法系统也不会自动在最后添加结束标志符 '\0',必须人为添加。如果忘记添加就会出现与数组 b 同样的错误。从数组 e 的输出结果可以看出这一点。

数组 f 是存储汉字,汉字不能像数组 a 或数组 d 那样分开一个一个赋值。因为一个汉字占 2 字节,若分开赋值,由于一个单引号内只能放一个字符,即一字节,所以将占 2 字节的汉字放进去当然就出错了。因此如果用字符数组存储汉字的话必须整体赋值,即要么定义时初始化,要么调用 strcpy 函数。

数组 g 初始化为一对双引号,表示该字符数组中 10 个元素的内容都为 '\0'。下面写一个程序验证一下:

# include <stdio.h>
int main(void)
{
char str[] = "";
str[] = 'a';
printf("str = %s\n", str);
return ;
}

输出结果是:
str =

程序中定义了一个长度为 3 的字符数组,然后给第三个元素赋值为 'a',然后将整个字符数组输出。但是输出结果什么都没有,原因就是其直接初始化为一对双引号,此时字符数组中所有元素都是 '\0'。所以虽然第三个元素为 'a',但因为第一个元素为 '\0',而 '\0' 是字符串的结束标志符,所以无法输出。

需要注意的是,使用此种初始化方式时一定要指定数组的长度,否则默认数组长度为 1。

总结,字符数组与前面讲的数值数组有一个很大的区别,即字符数组可以通过“%s”一次性全部输出,而数值数组只能逐个输出每个元素。

C语言字符数组详解的更多相关文章

  1. 《C语言》—— 数组详解

    书籍使我变成了一个幸福的人,使我的生活变成轻松而舒适的诗.--高尔基 本文已经收录至我的GitHub,欢迎大家踊跃star 和 issues. https://github.com/midou-tec ...

  2. c语言贪吃蛇详解3.让蛇动起来

    c语言贪吃蛇详解3.让蛇动起来 前几天的实验室培训课后作业我布置了贪吃蛇,今天有时间就来写一下题解.我将分几步来教大家写一个贪吃蛇小游戏.由于大家c语言未学完,这个教程只涉及数组和函数等知识点. 上次 ...

  3. Python2.7字符编码详解

    目录 Python2.7字符编码详解 声明 一. 字符编码基础 1.1 抽象字符清单(ACR) 1.2 已编码字符集(CCS) 1.3 字符编码格式(CEF) 1.3.1 ASCII(初创) 1.3. ...

  4. C语言memset函数详解

    C语言memset函数详解 memset() 的作用:在一段内存块中填充某个给定的值,通常用于数组初始化与数组清零. 它是直接操作内存空间,mem即“内存”(memory)的意思.该函数的原型为: # ...

  5. 转1:Python字符编码详解

    Python27字符编码详解 声明 一 字符编码基础 1 抽象字符清单ACR 2 已编码字符集CCS 3 字符编码格式CEF 31 ASCII初创 311 ASCII 312 EASCII 32 MB ...

  6. C语言中字符串详解

    C语言中字符串详解 字符串时是C语言中非常重要的部分,我们从字符串的性质和字符串的创建.程序中字符串的输入输出和字符串的操作来对字符串进行详细的解析. 什么是字符串? C语言本身没有内置的字符串类型, ...

  7. C语言内存对齐详解(2)

    接上一篇:C语言内存对齐详解(1) VC对结构的存储的特殊处理确实提高CPU存储变量的速度,但是有时候也带来了一些麻烦,我们也屏蔽掉变量默认的对齐方式,自己可以设定变量的对齐方式.VC 中提供了#pr ...

  8. c语言贪吃蛇详解-2.画出蛇

    c语言贪吃蛇详解-2.画出蛇 前几天的实验室培训课后作业我布置了贪吃蛇,今天有时间就来写一下题解.我将分几步来教大家写一个贪吃蛇小游戏.由于大家c语言未学完,这个教程只涉及数组和函数等知识点. 蛇的身 ...

  9. c语言贪吃蛇详解1.画出地图

    c语言贪吃蛇详解-1.画出地图 前几天的实验室培训课后作业我布置了贪吃蛇,今天有时间就来写一下题解.我将分几步来教大家写一个贪吃蛇小游戏.由于大家c语言未学完,这个教程只涉及数组和函数等知识点. 首先 ...

随机推荐

  1. YOLOv3训练过程笔记

    本人使用的是linux平台,按照YOLO网页0https://pjreddie.com/darknet/yolo/的步骤操作进行下载darkenet程序包以及编译,之后可尝试用VOC2007的数据集测 ...

  2. jfinal layui easyexcel 实现文件的上传下载

    jfinal  layui easyexcel  这三样开源技术这里就不多介绍了,自行百度了解吧,他们的组合算是一个很高效又不失美观的操作体验. 操作主要分以下几步: 1.建立jfinal的操作环境, ...

  3. mybatis返回map结果集

    今天突发奇想,想用mybatis返回一个map结果集,结果我就整了一下午,不过终于解决了 1.如果你确定返回的数据只有一条,你可以这样整 xml中: <select id="searc ...

  4. python-函数4(递归、高阶函数)

    python-函数4(递归.高阶函数) 递归 在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数. 递归特性: 1. 递归必须有一个明确的结束条件 2. 每次进入更深一 ...

  5. ceph分布式存储简介

    一.Ceph简介: 什么是分布式存储? 我在一个环境当中,有很多很多的服务器,服务器上也有它自己很多的硬盘,我通过软件的形式把若干服务器都收集起来,部署成一个软件,在这个逻辑的软件里可以同时看到我若干 ...

  6. C#.net中的rank方法

    string[,] abcd = new string[2, 4];abcd[0, 0] = "a";abcd[0, 1] = "b";abcd[0, 2] = ...

  7. Zookeeper客户端使用(使用zkclient)

    Zookeeper客户端使用 二.使用zkclient 在pom.xml中加入依赖 <dependency> <groupId>com.101tec</groupId&g ...

  8. Yii和ThinkPHP对比心得

    本人小菜鸟一只,为了自我学习和交流PHP(jquery,linux,lamp,shell,javascript,服务器)等一系列的知识,小菜鸟创建了一个群.希望光临本博客的人可以进来交流.寻求共同发展 ...

  9. dubbo SPI机制

    源码分析: /** * 获取扩展类 */ @SuppressWarnings("unchecked") public T getExtension(String name) { i ...

  10. 关于web网页截图的问题(html2canvas插件)

    import html2canvas from 'html2canvas' import jpg from '@/assets/1.jpg';     htmlToImage=(element, ca ...