(C/C++学习)15.C语言字符串和字符数组
说明:在C语言中字符串和字符数组有很多相似之处,却又有着一些不同。本文将针对其区别与联系,进行分析总结。
一.字符串
1.在C语言中,字符串是由双引号括起来的任意字符序列,如:“china”,”america”等。
2.很显然,一个字符占一个字节,那么 “china” 应该占5个字节,但这样想就错了。其实在上篇文章中提到过了,在生成一个由双引号引起的字符串时,系统会自动在其后面追加一个 ‘\0’ ,这个杠0是相当重要的,可以说是字符串的重要依据,它是字符串的结束标志。字符串的很多处理函数,如上篇文章提到的,都是依据这个杠0工作的。所以在这里如果打印 “china” 的大小,应该是 6 。需要注意的是,空串 “” 的大小是1,可以理解为只有一个 ‘\0’ 。
- 1 printf("%d\n",sizeof("china"));
- 2 printf("%d\n",sizeof(""));
- 3 //打印结果为6、1
3.C 语言将常量字符串处理为一个指向数据段中一段字符串的字符指针或字符数组。我们可以将它付给一个 char * 的指针或 char型的数组。
- 1 char *p= "abcdef";
- 2 //C++中类型检查严格,将const char *赋给 char* 会有警告
- 3 char arr[6] = "abcde";
4.字符串,准确说是字符串常量,因为其是不可以修改的。普通变量通常存储在代码段,而字符串常量则存储在数据段的只读数据段 (RO段) ,这也意味着字符串常量是不可修改的。如运行以下代码,程序将挂掉。
- 1 char *p= "abcdef";
- 2 p[1] = '0';
二.字符串和字符数组
数组前面已经说过了,字符数组也是其中的一种,只不过数组中的每个元素为字符型的。这里就直接说字符串与字符数组的关系。
1.相同之处:下面将以一段代码加以说明
- 1 char *p= "abcde";
- 2 char arr[] = "abcde";
- 3 char *pp = p;
- 4 int i = 0;
- 5 printf("%s\n",p);
- 6 printf("%s\n",arr);
- 7 //打印字符串和字符数组
- 8
- 9 printf("%d ",sizeof("abcde"));
- 10 printf("%d\n",sizeof(arr));
- 11 //打印字符串和字符数组的大小
- 12
- 13 while(*pp)
- 14 printf("%c ",*pp++);
- 15 while(arr[i] != 0)
- 16 printf("%c ",arr[i++]);
- 17 //分别单独访问各自的元素
程序运行结果:
- 1 abcde
- 2 abcde
- 3 6 6
- 4 a b c d e a b c d e
由上述结果可知,在某种情况下(下文将说明),字符串和字符数组是等价的,尤其是程序最后几行,通过单独打印字符串和字符数组的每个元素,更是可以得知两者末尾都有一个 ‘\0’ 存在。那么,在什么情况下二者不等呢?
2.不同之处
(1.)前面已经说过了,字符串是一个常量,不可修改,但字符数组却不是这样的。你可以完全通过下标法对任意一个元素进行修改。
- 1 char arr[] = "abcde";
- 2 arr[0] = '1';
- 3 arr[3] = '5';
- 4 printf("%s",arr);
(2.)二者等价条件,及前面提到的某种情况
一个没有 ‘\0’ 作为结尾标识符的字符串不叫字符串,而字符数组中元素的存储并不会像字符串那样自动追加 ‘\0’ ,因此,字符数组和字符串等价的条件便是 ‘\0’ 的拷贝问题。一个正常的字符串,其末尾必定以 ‘\0’ 结尾,如 “china” ,虽然杠0 并没有显示出来,但我们应该明确的知道其末尾有一个杠 0 的存在,这点,在前面通过打印字符串的大小也可以证明。因此,在初始化字符数组的时候,其大小应该总是大于等于字符串的大小,这样以便于将字符串末尾的 ‘\0’拷贝到数组。如以下代码,其中 n 应该大于等于 sizeof(“abcde”) = 6。
- 1 char arr[n] = "abcde";
(3.)越界情况
当数组的大小小于字符串的大小时,由于 ‘\0’没拷贝到数组中,因此,对数组的打印可能会发生越界行为,产生不确定结果。
- 1 char arr[5] = "abcde";
- 2 printf("%s",arr);
在笔者电脑上输出结果为:
- 1 abcde?6
(4.)最优做法
利用数组可以省略大小的特点,依据数组的大小自适应。这样也会避免浪费空间。
- 1 char arr[] = "china";
- 2 printf("%s\n",arr);
三.字符数组的拓展
既然字符数组可以存储任意字符元素,那么万一字符数组在前面元素中就已经出现了 ‘\0’ 而非最后一个元素是 ‘\0’ 呢?
- 1 #include<stdio.h>
- 2 #include<string.h>
- 3 int main()
- 4 {
- 5 unsigned int i = 0;
- 6 char arr[] = "c0hi0n\0a ";
- 7 printf("%s\n",arr);
- 8 printf("%d\n",sizeof(arr));
- 9 printf("%d\n",strlen(arr));
- 10 for(;i<sizeof(arr);i++)
- 11 printf("%x ",arr[i]);
- 12 return 0;
- 13 }
程序运行结果:
- 1 c0hi0n
- 2 10
- 3 6
- 4 63 30 68 69 30 6e 0 61 20 0
由以上测试可知,数组只是一个存储元素的构造类型,其中的元素可以是任意的,打印数组大小时,只会跟元素的多少以及元素的类型有关,与其中元素是不是杠 0 无关。而当用 strlen()来判断该数组的长度时,由于其判断标识为 ‘\0’ ,因此不能正确得到数组的实际长度,只能得到 ‘\0’前面元素的长度。而对整个数组以字符串的格式打印时,也是同样的道理。只有当对字符数组的元素挨个单独打印,才能见到其真貌。上述代码是以十六进制 ASCII 对数组元素进行打印的。需要注意的是:0 并不是 ‘\0’,应该加以区分。
(C/C++学习)15.C语言字符串和字符数组的更多相关文章
- C语言字符串与字符数组
字符串儿与字符数组 字符数组的定义: Char buffer[]; 字符数组初始化: Char buffer1[]="hello world"; 利用scanf输入一个字符串儿 代 ...
- c语言中的字符数组与字符串
1.字符数组的定义与初始化 字符数组的初始化,最容易理解的方式就是逐个字符赋给数组中各元素. char str[10]={ 'I',' ','a','m',' ',‘h’,'a','p','p','y ...
- 字符类型char、字符串与字符数组、字符数组与数据数组区别
字符类型是以ASCII码值运算的:小写字母比相应的大写字母大32,其中A=65,a=97 Esc键 27(十进制).'\x1B'(十六进制).'\33'(八进制) 转义字符:\0 空字符 AS ...
- 字符串,字符数组(C/C++)
这个地方困惑我好久了,废话不多说 char c1[]="12345"; char *c2="12345"; string c3="12345" ...
- 【C#】字符串与字符数组
字符串与字符数组的相互转换. 字符串转换成字符数组: string ss="abcdefg"; char[] cc=ss.ToCharArray(); 字符数组转换成字符串 ...
- JavaScript字符串和字符数组
字符串 字符串与字符数组: 字符串:var a = 'ddd'; 字符数组:var arr = 'f','o','o' 相同点: 1.都是类数组 2.都有length属性 3.都有indexOf()和 ...
- java 字符串,字符数组,list间的转化
1.关于java.lang.string.split xxx.split()方法可以将一个字符串分割为子字符串,然后将结果作为字符串数组返回. 2.字符串转字符数组 String str =" ...
- Day_09【常用API】扩展案例4_将字符串变为字符数组,并将大写字母改为小写,首尾内容不同互换,并将索引为偶数的元素替换
分析以下需求,并用代码实现 1.键盘录入一个字符串 2.将该字符串变成字符数组(不能使用toCharArray()方法) 3.将字符数组中的所有大写字母变成小写字母(不能使用toLowerCase() ...
- (C/C++学习)13.C语言字符串处理函数(一)
说明:字符串处理的函数很多,本文将例举经常遇到的一些函数加以说明. 一.字符串的输入输出 头文件:<stdio.h> 1.利用标准输出函数 printf() 来输出,将格式设置为 s% . ...
随机推荐
- 在linux上处理base64加密和解密
http://snailwarrior.blog.51cto.com/680306/142472/ 2.从标准输入读取文件内容,base64编码并打印到标准输出 [root@localhost tes ...
- Weex 和 React Native 的比较看这里
写在前面 目前主流的应用大体分成三类:Native App, Web App, Hybrid App. Native App 特点: 性能好 完美的用户体验 开发成本高,无法跨平台 升级困难 (审核) ...
- ASP.NET Core开发Docker部署
ASP.NET Core开发Docker部署,.NET Core支持Docker 部署运行.我们将ASP.NET Core 部署在Docker 上运行. 大家可能都见识过Docker ,今天我们就详细 ...
- Opencv+Zbar二维码识别(二维码校正)
二维码和车牌识别基本都会涉及到图像的校正,主要是形变和倾斜角度的校正,一种二维码的畸变如下图: 这个码用微信扫了一下,识别不出来,但是用Zbar还是可以准确识别的~~. 这里介绍一种二维码校正方法,通 ...
- 洛谷P2831 愤怒的小鸟——贪心?状压DP
题目:https://www.luogu.org/problemnew/show/P2831 一开始想 n^3 贪心来着: 先按 x 排个序,那么第一个不就一定要打了么? 在枚举后面某一个,和它形成一 ...
- bzoj2132
最小割 套路最小割... 盗一波图 来自GXZ神犇 对于这样的图,我们要么割ai,bj,要么割bi,aj,要么割ai,ci+cj,aj,要么割bi,ci+cj,bj,然后这样建图跑最小割就行了 但这不 ...
- 26.Extjs 部门列表信息展示页面
/** * @author sux * @time 2011-1-14 * @desc 部门信息显示 */ deptInfoGridPanel = Ext.extend(Ext.grid.Editor ...
- samba - linux客户端访问samba服务器的指令(转载)
转自:http://linux.sheup.com/linux/linux5303.htm linux客户端访问samba服务器的指令2004-04-23 15:18 pm来自:Linux文档现载:W ...
- ssm lodop打印图片不显示
在打印预览的时候图片就是不显示 最终解决方案就是修改过滤器
- 对路径 obj 文件夹访问被拒绝
TFS 刚下载的项目,出现该问题. 解决方案: 将文件夹属性“只读”,取消