【C语言学习】字符与字符串(包含转义字符的详解及大量实例说明)


前言

一、字符:包含ASCll码表,及提到控制字符(不可打印字符)和可打印字符的概念
二、字符串:在证明’\0’作用过程中解释了库函数strlen()的用法
三、转义字符:使用大量代码实例说明各种转义字符的效果


一、字符和ASCll编码

字符指类字形单位或符号,包括字母、数字、运算符号、标点符号和其他符号,以及一些功能性符号。在键盘上可以敲出各种字符,如:a,5,+,#等,这些符号都被称为字符,C语⾔中字符是⽤单引号括起来的,如:‘a’,‘5’,‘+’,‘#’。

我们知道在计算机中所有的数据都是以⼆进制的形式存储的,那这些字符在内存中分别以什么样的⼆进制存储的呢?如果我们每个⼈⾃⼰给这些字符中的每个字符编⼀个⼆进制序列,这个叫做编码,为了⽅便⼤家相互通信,不造成混乱,后来美国国家标准学会(ANSI)出台了⼀个标准 ASCII 编码,C语⾔中的字符就遵循了 ASCII 编码的⽅式。

下列ASCll码表含有全部 128 个 ASCII 十进制 (dec) 、八进制 (oct) 、十六进制 (hex) 及字符 (ch) 编码:
在这里插入图片描述

参考链接: link

ASCII中的0-31为控制字符;32-126为打印字符;127为Delete(删除)命令,也属于控制字符。
故ASCII中的0~31及127 (共33个)都是控制字符(表示某一控制功能的字符),也称不可打印字符,它们无法被打印在屏幕上观察。

单个字符的打印可以使用%c来指定格式:

#include <stdio.h>

int main()
{
	printf("%c\n", 'A');
	printf("%c\n", 65);//这⾥的65是字符A的ASCII码值,也是可以正常打印的

	printf("%d\n", 'A');//字符在内存中实际是以ASCll码值的形式存储,以%d的格式可以直接打印出字符所对应的ASCll码值
	printf("%d\n", 65);
	return 0;
}

在这里插入图片描述

(因为字符在内存中是以ASCll码值的形式存储的,所以我们可以直接用相应的ASCll码值来打印字符;同样我们使用%d的格式可以直接打印出字符所对应的ASCll码值)

可打印字符展示:

#include <stdio.h>

int main()
{
	int i = 0;
	for (i = 32; i <= 126; i++)
	{
		printf("%c ", i);
		if (i % 32 == 31)
			printf("\n");
	}
	return 0;
}

在这里插入图片描述

二、字符串

使用双引号括起来的⼀连串字符就被称为字符串,如:“abc9#=”,就是⼀个字符串。

字符串的打印格式可以使用 %s 来指定,也可以直接打印,如下:

#include <stdio.h>

int main()
{
	char arr[] = "hello world";

	printf("%s\n", arr);
	printf("%s\n", "hello world");
	printf("hello world");
	return 0;
}

在这里插入图片描述
字符串中还有一个特殊的小知识,就是字符串的末尾隐藏了一个’\0’字符,这个 '\0’字符是字符串的结束标志,接下来展开介绍。

1.字符串的结束标志’\0’字符

在这里插入图片描述
对于字符串"abc",我们看到的有3个字符:‘a’,‘b’,‘c’,但是实际上在末尾还隐藏⼀个’ \0’ 的字符,通过对代码的调试我们可以看到实际上字符串"abc"中包含了’a’,‘b’,‘c’,'\0’共4个字符。

那么’\0’ 是字符串的结束标志这一点在C语言中是如何体现的呢?
当我们使用库函数 printf() 打印字符串或者strlen() 计算字符串长度的时候,它们遇到 ‘\0’ 的时候就会认为这个字符串结束了,然后就会自动停止了。

(1)我们用printf()验证一下’\0’作为字符串结束标志这一功能,代码如下:

#include <stdio.h>

int main()
{
	char arr1[] = "abc"; //arr1数组中存放字符串
	char arr2[] = { 'a','b','c' }; //arr2数组中存放3个字符,末尾不放'\0'

	printf("%s\n", arr1);
	printf("%s\n", arr2);
	return 0;
}

在这里插入图片描述
在这里插入图片描述
我们可以看到 arr1字符数组 的打印是完全正常的,这是因为 arr1 数组是使用字符串常量初始化的,数组中有 ‘\0’作为结束标志,打印可以正常停止。
但是 arr2 字符数组在打印的时候,打印了 字符’a’ 、’ b’ 、’ c’ 后还打印了⼀些乱码(其实就是一些随机值),这就是因为 arr2在末尾的地⽅没有’ \0’ 字符作为结束标志,在打印的时候没有停止。

(2)我们再用strlen()验证一下’\0’作为字符串结束标志这一功能,代码如下:
(strlen()库函数的头文件是<string.h> , strlen()的作用是计算字符串的长度,遇到’\0’字符时停止计算,返回计算到的字符串长度,返回值的类型是size_t,这种类型要使用%zd格式来打印。而且’\0’作为字符串的结束标志,将不记入字符串长度)

#include <stdio.h>
#include<string.h>

int main()
{
	char arr1[] = "abc"; //arr1数组中存放字符串
	char arr2[]= { 'a','b','c','\0'};//arr2数组中存放4个字符,末尾放'\0'
	char arr3[] = { 'a','b','c' }; //arr2数组中存放3个字符,末尾不放'\0'

	printf("%zd\n", strlen(arr1));
	printf("%zd\n", strlen(arr2));
	printf("%zd\n", strlen(arr3));
	return 0;
}

在这里插入图片描述
在这里插入图片描述
我们可以看到 arr1和arr2字符数组的长度计算都是3,这是因为 arr1 和arr2字符数组结尾都有结束标志’\0’,字符串的长度计算可以正常停止。
但是 arr3字符数组在字符串长度的计算时,strlen()计算到arr3字符数组的末尾时没有遇到结束标志’\0’,所以strlen()函数的计算不会停止,strlen()会接着往后计算直到遇到’\0’才停止,而arr3字符数组后面的空间存储的数据是未知的,strlen()往后计算了42个字符后恰好遇到未知空间中的’\0’,于是计算停止。

从上述的例子中我们应该就能感受到’ \0’ 的作为字符串结束标志的重要作用。
但其实’\0’不止能够呆在的字符串结尾,当我们主动将’\0’字符放在字符串的中间部分时,库函数 printf() 打印字符串或者strlen() 计算字符串长度的时候就会提前停止了,如下:

#include <stdio.h>
#include<string.h>

int main()
{
	char arr1[] = "abcd\0efg"; 

	printf("%s\n", arr1);
	printf("%zd\n", strlen(arr1));
	return 0;
}

在这里插入图片描述
在这里插入图片描述

三、转义字符

在字符中有⼀组特殊的字符是转义字符,转义字符顾名思义就是转变原来意思的字符

比如’a’,‘b’,‘f’,'n’等字符,用printf()打印它们时能够自然打印出这些字符:

#include <stdio.h>

int main()
{
	printf("abfnrtv");
	return 0;
}

在这里插入图片描述
但在这些字符前加一个 \ 就能转变它们本来的意思,构成一个转义字符,如下:

\a :警报,这会使得终端发出警报声或出现闪烁,或者两者同时发⽣。(字符'a'的ASCll码值是97,'\a'的ASCll码值是7)
\b :退格键,光标回退⼀个字符,但不删除字符。(字符'b'的ASCll码值是98,'\b'的ASCll码值是8)
\f :换⻚符,光标移到下⼀⻚。在现代系统上,这已经反映不出来了,⾏为改成类似于 \v 。(字符'f'的ASCll码值是102,'\f'的ASCll码值是12)
\n :换⾏符。(字符'n'的ASCll码值是110,'\n'的ASCll码值是10)
\r :回⻋符,光标移到同⼀行的开头。(字符'r'的ASCll码值是114,'\r'的ASCll码值是13)
\t :制表符,光标移到下⼀个⽔平制表位,通常是下⼀个4/8的倍数。(字符't'的ASCll码值是116,'\t'的ASCll码值是9)
\v :垂直分隔符,光标移到下⼀个垂直制表位,通常是下⼀行的同⼀列。(字符'v'的ASCll码值是118,'\v'的ASCll码值是11)

(1)'\a’的使用效果:

#include <stdio.h>

int main()
{
	printf("\abfnrtv");
	return 0;
}

在这里插入图片描述
'\a’这个转义字符实际上变成了ASCll码值为7的控制字符,而控制字符是不可打印字符,所以运行结果中我们就看不到这个字符了。我们虽然打印不出这个字符,但它的效果是实际存在的,当我们把电脑声音调大,可以听到电脑发出警告声。

(2)'\b’的使用效果:

#include <stdio.h>

int main()
{
	printf("afnrtv");
	printf("\n");//换行
	printf("a\bfnrtv");
	return 0;
}

在这里插入图片描述

‘\b’这个转义字符实际上变成了ASCll码值为8的控制字符,它的效果是光标回退一个字符。
第一次我们正常打印"afntrv"这个字符串;第二次打印时我们在’a’字符后面增加’\b’转义字符,我们会发现打印结果中’a’消失了,这是因为打印"a\bfnrtv"的过程中,在打印了’a’字符后,光标移到’a’后面一个位置准备打印下一个字符,下一个字符是’\b’,在执行了它让光标回退一个字符的效果之后,光标又回到’a’的脚下,这时再往后打印’f’字符时,'a’就会被’f’覆盖掉。

(3)'\n’的使用效果:

#include <stdio.h>

int main()
{
	printf("abf\nrtv");
	return 0;
}

在这里插入图片描述
'\n’这个转义字符实际上变成了ASCll码值为10的控制字符,它的效果就是打印到这个字符时就换行。

(4)'\r’的使用效果:

#include <stdio.h>

int main()
{
	printf("abcd\refghi");
	return 0;
}

在这里插入图片描述
‘\r’这个转义字符实际上变成了ASCll码值为13的控制字符,它的效果就是让光标移到同⼀行的开头。
在打印"abcd\refghi"字符串的时候,在连续打印了abcd四个字符之后,光标移到’d’后面一个位置准备打印下一个字符,下一个字符是’\r’,在执行了它会让光标移到同⼀行的开头效果之后,光标又回到这一行开头的字符’a’的脚下,这时再往后打印efghi这些字符时,abcd这四个字符就会完全被覆盖掉。

(5)'\t’的使用效果:

#include <stdio.h>

int main()
{
	printf("a\taa\taaa\taaaa\taaaaa\taaaaaa\taaaaaaa\ta\n");
	printf("aaaaaaaaa\ta");
	return 0;
}

在这里插入图片描述
‘\t’这个转义字符实际上变成了ASCll码值为9的控制字符,它的效果是以4/8个字符的倍数对齐。
第一个’a’字符后面跟了7个空格字符对齐到8个字符;后面紧接着的aa,它们后面跟了6个空格字符对齐到8个字符;后面以此类推…
需注意的是第二行我们打印9个连续的’a’字符,再遇到’\t’,因为大于8个字符,于是对齐到8个的倍数,也就是16个字符。

我们再介绍剩下的几个特殊转义字符:

\' :⽤于表示字符常量'
\" :⽤于表示⼀个字符串内部的双引号
\\ :⽤于表示⼀个反斜杠,防止它被解释为⼀个转义序列符。
\? :在书写连续多个问号时使⽤,防止他们被解析成三字母词,在新的编译器上没法验证了。

下⾯2种转义字符可以理解为:字符的8进制或者16进制的表示形式
\ddd :d d d表示1~3个八进制的数字。 如: \130 表⽰字符X
\xdd :d d表式2个十六进制数字。 如: \x30 表⽰字符0

(6)\ ’ 的使用效果:
当我们想单独打印 单引号这个字符的时候,我们发现编译器会报错,因为编译器会优先将靠近的单引号配对,前面两个单引号 ’ 构成了一对单引号,它们之间没放字符,而且后面还有一个落单的单引号 ’ ,就会出现问题了:
在这里插入图片描述
单引号这个字符前加上 \ ,它就会被解析成不会和其他 ’ 配对的字符常量 ',然后就可以正常打印出这个字符了:

#include <stdio.h>

int main()
{
	printf("%c",'\'');
	return 0;
}

在这里插入图片描述
(7)\ " 的使用效果:
当我们想打印字符串中的 " 双引号时,遇到的问题和单独打印 单引号字符时类似,因为编译器会优先将靠近的双引号配对,所以编译器就会报错:
在这里插入图片描述
" 双引号这个字符前加上 \ ,它就会被解析成不会和其他 " 配对的字符常量 ",然后我们就可以在字符串中正常打印出这个字符了:

#include <stdio.h>

int main()
{
	printf("ab$#\"kl = ");
	return 0;
}

在这里插入图片描述
(8)\ \ 的使用效果:
我们想正常打印C盘的一个文件路径,结果发现打印出来的路径很奇怪,这是因为 \ 和 t 结合变成了’\t’的转义字符,所以就会出现这种效果:

#include <stdio.h>

int main()
{
	printf("c:\test.c");
	return 0;
}

在这里插入图片描述
在 \ 反斜杠这个字符前再加上一个 \ ,就可以防止它被解释为⼀个转义序列符,它就不会和 t 结合变成一个转义字符,然后我们就可以正常打印出这个文件路径:

#include <stdio.h>

int main()
{
	printf("c:\\test.c");
	return 0;
}

在这里插入图片描述
(9)\ddd 和 \xdd 的使用效果:
(在字符部分提供的ASCll码表,所有字符对应的10进制、8进制和16进制的ASCll码值都可查到)

#include <stdio.h>

int main()
{
	printf("%c\n", '\141');//141(8进制)在ASCll码表中对应的字符是'a'
	printf("%c\n", '\75');//75(8进制)在ASCll码表中对应的字符是'='

	printf("%c\n", '\x41');//41(16进制)在ASCll码表中对应的字符是'A'
	return 0;
}

在这里插入图片描述
补充:
\0 :null 字符,代表没有内容, \0 就是 \ddd 这类转义字符的⼀种,用于字符串的结束标志,其ASCII码值是0.


  • 13
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值