热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C语言下标为字符串的数组,C语言快速入门——理解字符数组与字符串

字符数组现在让我们把已经习惯的int型数组转换为char型。一般来讲,char型数组通常是用于a,b,c,d这类具有可读性的字符。在《类型与变量》一节中讲过ÿ

字符数组

现在让我们把已经习惯的int型数组转换为char型。一般来讲,char型数组通常是用于'a', 'b', 'c', 'd'这类具有可读性的字符。在《类型与变量》一节中讲过,char类型的数据占用1个字节的存储空间,本质上它是一种小整型类型。这表明char型数组也可用来处理数据,如保存一张图像的像素值,保存接收到来自服务器的回复信息等。随着以后对指针的深入理解,我们会对此有更深的见解。此时,我们只用它来处理可阅读字符。

首先,让我们尝试输出"hello"这个字符串,不同的是,这次是使用数组输出。

170381677_1_20190907094459313

170381677_2_20190907094459500

为了明确的看到各种输出之间的不同,我以大写串END_STR来标识当前输出的结束。第一个"hello",我们使用字符数组存储5个对应字符,并借助for循环输出。

第二个与之类似,但却是6个字符,数组以一个转义字符'\0'结束。如果没有特殊的结束符,看上去会与第一行输出没什么不同。

第三个使用我们熟悉的printf()函数输出,使用的格式符是%s,表示以字符串的方式输出。最后一个同样使用%s输出了str1,除了输出hello外,后面还跟有奇怪的字符。你可以尝试多运行几次,这些奇怪字符每次都不一样。

分析后两项输出

最后两个"hello",我们都是使用printf函数加%s格式符输出,为什么最后一个乱码了?最明显的不同之处在于数组的定义。str2的最后一个字符是'\0'值,而str1没有这个值。这说明这个'\0'有特殊意义。

我们知道数组传递给函数时,会转换为对应的指针类型,也就是说str2、str1传递给printf函数时,实际会形成类似printf( char *str )形式。回想一下计算数组平均值的函数,对于传递数组的函数,除了数组变量本身外,通常还需要一个int变量以指明数组元素的个数。而我们把str2,str1传递给printf函数时,并没有给定元素的个数!

但是由于str2具有特殊标记'\0',%s格式符对于该字符数组输出了正确值,但str1却没有这么幸运,它乱码了!这就说明了,'\0'指示了字符串的结束,如同给函数间接传递了元素个数一般。实际情况也确实如此,当printf+%s输出char*类型时,碰到'\0'就认为字符串结束了。

'\0'结束字符串

170381677_3_20190907094459578

170381677_4_20190907094459672

可以看到,"world"没有被输出,这表明C的字符串是以'\0'表示 “我的话讲完了”。

那'\0'到底是什么呢?咳咳~~,又到了说说ASCII码表的时候了!'\0'是一个转义字符,它代表的是ASCII码值为0的值,也是ASCII码表中的第一个值,在C语言中用于表示字符串结尾标记。 注意数值0与字符'0'是不同的概念,字符'0'可以理解为是书写上用于交流0值的0。

动手试一下

现在你可以尝试将第一个'\0'变为数值0,你会发现得到同样的输出。再尝试将0变为字符'0',再次观察输出并思考一下。假如你一直跟随我们的教程在学习,还是有点紧张你会用什么样的方式来完成这个试验呢?我们已经学习过数组的基础操作,希望你能使用下标运算符去修改数组中的某个值,而不是把代码拷贝多份......

170381677_5_20190907094459813

170381677_6_20190907094459891

让生活再简单点

假定你现在在编写一款RPG游戏,主人公有千言万语要向玩家诉说。基于现在所掌握的知识,把每个字符用单引号括起来并放到数组中,那简直就是噩梦!好在你的担心是多余的,你发现的问题,语言的设计者已经解决了,那就是使用char*指向常量字符串!

170381677_7_20190907094459985

与单个字符赋值到数组相比,这种方式真的是轻松多了,而且也具有更好的可读性。这个程序会完整的输出"hello, world!",也不会出现乱码。这就表明,以这种赋值方式保存的字符串,语言自身会在结束加上结束标记。

这就是C风格的字符串,以0结束。

在这种形式下,你可能想要尝试修改一下某个字符,如hw[0]='a',程序可以编译过去,但执行会出错。这是因为"hello, world!"是字面常量,确切的说是常量字符串,是不可修改的。(在古老的编译环境下可能是正确的,如VC++6.0。另外,我们的声明还可以更加精确一些,使用const chr *hw代替会更好一些,由于目前没有学习const的意义,所以先不加;如果使用的是vs2017之类的编译器,这里的声明估计有问题。)

详细的说,可以这么理解:想像一下,不管是变量还是常量,总要有能存储这种东西的地方,这地方就是内存,是内存就有地址,对于常量存储区域,具有不可写标记(即只读)。hw仅是一个指针,指针的有效性就是指向一个地址,当为hw赋值后它就指向了这个常量地址,因此编译时是成功的。当使用下标修改时,系统发现你想要修改只读内存,然后被无情打脸。

你可能会抱怨,如果我真的想要修改字符串该怎么办?1:把常量字符串转换为数组。2:使用动态内存分配。作为练习,你可以基于现有的知识,尝试按自己的思路去实现方法1。当然,这些知识在后续的教程中也会一一道来。



推荐阅读
  • C语言常量与变量的深入理解及其影响
    本文深入讲解了C语言中常量与变量的概念及其深入实质,强调了对常量和变量的理解对于学习指针等后续内容的重要性。详细介绍了常量的分类和特点,以及变量的定义和分类。同时指出了常量和变量在程序中的作用及其对内存空间的影响,类似于const关键字的只读属性。此外,还提及了常量和变量在实际应用中可能出现的问题,如段错误和野指针。 ... [详细]
  • 《2017年3月全国计算机等级考试二级C语言上机题库完全版》由会员分享,可在线阅读,更多相关《2017年3月全国计算机等级考试二级C语言上机题库完全版( ... [详细]
  • C语言注释工具及快捷键,删除C语言注释工具的实现思路
    本文介绍了C语言中注释的两种方式以及注释的作用,提供了删除C语言注释的工具实现思路,并分享了C语言中注释的快捷键操作方法。 ... [详细]
  • c语言\n不换行,c语言printf不换行
    本文目录一览:1、C语言不换行输入2、c语言的 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • C语言判断正整数能否被整除的程序
    本文介绍了使用C语言编写的判断正整数能否被整除的程序,包括输入一个三位正整数,判断是否能被3整除且至少包含数字3的方法。同时还介绍了使用qsort函数进行快速排序的算法。 ... [详细]
  • ejava,刘聪dejava
    本文目录一览:1、什么是Java?2、java ... [详细]
  • c语言基础编写,c语言 基础
    本文目录一览:1、C语言如何编写?2、如何编写 ... [详细]
  • 利用空间换时间减少时间复杂度以及以C语言字符串处理为例减少空间复杂度
    在处理字符串的过程当中,通常情况下都会逐个遍历整个字符串数组,在多个字符串的处理中,处理不同,时间复杂度不同,这里通过利用空间换时间等不同方法,以字符串处理为例来讨论几种情况:1: ... [详细]
  • C语言的经典程序有哪些
    本篇内容介绍了“C语言的经典程序有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • 本文介绍了C函数ispunct()的用法及示例代码。ispunct()函数用于检查传递的字符是否是标点符号,如果是标点符号则返回非零值,否则返回零。示例代码演示了如何使用ispunct()函数来判断字符是否为标点符号。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
author-avatar
xkxk22
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有