目录
Part.1 C 语言面向过程编程
Part.2 字符串与ASCII码
Part.3 如何把指针玩出花
/*本贴总结适用于已经学过 C 语言的同学,旨在提供一些技术应用时的小技巧*/
一、C 语言中的字符串
如果你会使用多门编程语言,你一定有这样的疑惑:
在 Java 中,可以使用 string 关键字进行字符串的声明;
在 Python 中,可以使用 string 关键字进行字符串的声明;
在 C++ 中,可以使用 string 关键字进行字符串的声明。
但是,为什么一到 C 语言这里,string 关键字就仿佛符间蒸发了一样,压根就无法使用它,
反而还要使用 char name[] = ""; 这样的语句进行声明呢?
实际上,这是由于 C 语言属于偏底层的语言。它是紧贴在汇编语言上方的程序语言。
而 Java 、Python 、C++ 等语言是建立在 C 语言上的高级语言。
这些高级语言的关键字 string 实际上是提前其他程序员写好的,在标准库中的一个类。
但是我们的 C 语言它明显不支持面向对象编程,自然也就没有类。存储字符串的方式就落到了字符数组的头上。
因此,在 C 语言中字符串就要使用 char name[] = ""; 这样的语句去声明。
二、伪装成字符串的字符数组
通过 char name[] = "Hello world!!"; 这一条语句,你可以很轻松地声明一个“字符串”。
但是,当我们正常使用 printf(name); 去打印一行 Hello world!! 之前,我们来仔细看看这种语法。
变量类型 变量名称[] = 内容;
这不就是数组的声明方式吗?
其实,这样声明出来的字符串,在 C语言和 C++ 中就是字符数组。
三、字符数组是如何保存文字信息的?
要明白字符数组是如何保存信息的,首先就要明白字符变量是如何存储字符的。
首先,char 类型的变量占用一个字节的空间,能够存储八个比特,也就是说:
它的取值范围为 -128 ~ 127
从本质上,char 与其他变量一样,都可以进行赋值、运算、比较。
唯一不同的是,char 类型占用的空间要比其他类型(甚至是 short )更小。
(你可以利用这一点,在例如单片机等对 ROM 要求苛刻的地方使用 char 来代替 int 从而节省 ROM 空间)
那么为什么要单独设计一个 char 来存储数字呢?
当然是因为 ASCII 码表没有那么多的对应关系
“一张完整的 ASCII 码表!”
你不需要背诵这张表,只需要记下 48 - 0、65 - A、97 - a 这几个关键的值即可
等到需要的时候可以往后面推,实在需要其他字符直接查表即可
ASCII 码表显然是一种针对英文的文字处理方式,关于汉字如何存储这里不表,详见“UTF-8”的资料。
ASCII码表使用一个数字对应一种操作(十进制 0~31)或者一个字符(十进制 32~127)
刚好仅需一个字节即可表达出所有字符(英语语境下的)
我们的电脑其实直到现在也支持 ASCII 码表的直接输入
例如我们可以随便点进一个输入框,按住 Alt 键不松开,同时依次按下 '8' '3'
再按住 Alt 键不松开,同时依次按下 '6' '6'
然后看看你在输入框里输入了什么(笑)
总之,char 类型的变量仅有一个字节,是因为这一个字节就能存储所有和ASCII码表有关的数字了
所以实际上,当你使用单引号输入单个字符的时候,编译器会默认根据ASCII码表,把它等价于它对应的数字
例如
int a = 48;
int b = '0';
显然 a 与 b 的值相等。
但值得一提的是,char 变量本身是不具备这样的转换能力的。
具备转换能力的是需要传入 char 类型的函数!!!
当多个这样的 char 变量组合成一个字符数组
我们依次再按顺序读出ASCII表中的对应字符
一句话,或者说,一个字符串就被保存下来了
但是,学过数组的同学应该知道,如果一个数组只有 4 个元素
那么访问它的第 5 位就会访问到别的内存空间去
计算机不知道这个数组一共有多长,所以它会在字符数组的最后一位存上一个 '\0'(截止位)
(对应ASCII表的第 0 位)
所以,当我们使用字符串为字符数组格式化赋值的时候
要记住我们向字符数组中存储的其实要多一个 '\0'
例如
char tmp1[] = "Hello world!!";
char tmp2[] = {'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', '!', '\0'};
显然, tmp1 字符数组和 tmp2 字符数组存储的内容是相同的。
类似的你可以使用
char a = "";
在双引号内部什么也不写,为 a 变量赋上 '\0',也就是数字 0
四、我们是怎样修改 C 语言字符串的?
一定有同学使用过例如
char a[] = "Hello";
a = "Goodbye";
这样的语句尝试进行对字符串的修改,然后最后发现程序报错了
这是正常的,因为当你创建一个名为 a 的字符数组后,再次使用名 a 就要遵循数组的定义了
也就是,a 的值这个字符数组的首地址
既然 a 代表这个字符数组的首地址那一定是常量不能更改的
每当我们使用 "" 进行字符串的创建时,都会占用内存中的字符常量区的空间,这点还请注意
因此我们无法修改已有的字符串,只能让数组指向另一个字符串,以此达到“修改”的目的
类似于 strcpy() strcat() sprintf() sscanf() 这些修改方式在此不表,它们属于初学就要学会的内容,这里仅提供技巧和原理说明
五、小结
在本Part中:
1. C 语言是偏向底层的语言,它没有字符串容器和类,因此不能使用 string 关键字;
2. char 关键字可以声明一个取值范围只有 -128 ~ 127 的小变量;
3. char 类型本身不具备字符转换能力,在更多时候,程序员可以把它当做 short short int 类型使用;
4. ASCII码表不需要背诵,只需记住几个关键数字 48 - 0、65 - A、97 - a,关键时刻往后推即可;
5. 使用 "" 声明字符数组会自动在末尾加上 '\0' 表示结束位,你可以使用 "" 来直接代表 '\0';
6. 字符串本身一旦声明就不能修改,属于常量。但你可以更改字符数组内部的值。
题外话:
有人用过字符指针创建字符串吗?
真的超好用!推荐试试!