草庐IT

C语言初阶之转义字符

小谢爱学C语言 2023-08-02 原文

转义字符

一、什么是转义字符

转义字符(Escape character),所有的ASCII码都可以用“\”加数字(一般是8进制数字)来表示。而C语言中定义了一些字母前加""来表示常见的那些不能显示的ASCII字符,如\0,\t,\n等,就称为转义字符;在平常的代码编写中,printf函数经常会用到。
转义字符虽然由两个及两个以上的字符构成,但它表示的却是单个字符
简单转义字符(Simple escape sequence)

转义字符含义说明
\0空字符(NULL在c语言中代表“字符串结束符”
\a警报符(alert)发出听觉或视觉上的警报
\b退格符(backspace)将当前位置移到前一列
\f换页符(form feed)换页,将当前位置移到下一页开头
\n换行符(new line)换行,将当前位置移到下一行开头
\r回车符(carriage return)将当前位置移到本行开头
\t水平制表符(horizontal tab)将当前位置移动到下一个水平制表位置
\v垂直制表符(vertical tab)将当前位置移动到下一个垂直制表位置
\\字符\
\?字符 ?
\’字符 ’
\"字符 "

八进制转义字符(Simple escape sequence)

转义字符含义说明
\dddddd是3位八进制数一般来说是在ASCII中的八进制数值为ddd的字符

十六进制转义字符(Simple escape sequence)

转义字符含义说明
\xhhhh是2位十六进制数一般来说是在ASCII中的十六进制数值为hh的字符

二、简单转义字符

1、空字符

空字符\0
它的存在是为了告诉编译器’\0’是空字符,而不是字符0.
字符’0’对应的ASCII码为00110000,而’\0’对应的ASCII码为00000000;在C语言中通常用一个字符数组来存放字符串,’\0’ 是字符串的结束标志,任何字符串之后都会自动加上’\0’。如果字符串末尾少了‘\0’转义字符,则在输出时可能会出现乱码问题。
比如:

int main() {
    char str1[] = {"abc"};
    char str2[] = {"abc\0"};
    return 0;
}

上述代码中str1str2在打印输出时均为abc
包括在使用库函数strlen计算时,str1str2均为3
原因是printf函数与strlen函数均认定’\0’ 是字符串的结束标志;
但在使用单引号进行赋值的时候,这两个函数可能会出现一些问题。
比如:

int main() {
    char str1[] = {'a','b','c'};
    char str2[] = {'a','b','c','\0'};
    return 0;
}

在上述代码中如果我们使用printf函数与strlen函数进行打印输出和计算str1时,
该数据类型会丢失’\0’ ,此时打印的时候可能会出现乱码情况和计算出随机值的情况,
这时如果非要用单引号进行赋值的话,建议使用str2的写法。

在使用库函数sizeof进行字符串计算时,输出个数会比实际字符个数多1,
比如:

int main() {
    char str[] = {"abc"};
    return 0;
}

在上述代码中,如果使用sizeof函数对字符串str进行运算时,得出的结果应该是4,而不是3,所以如果使用固定值对元素个数进行赋值时,在方括号[]中应该输入的是4,而不是3。

2、警报符

警报符\a
C语言中的转义字符\a(响铃)是在标准输出设备输出字符’\a’时,系统自带的扬声器(或蜂鸣器)会发出“叮”的一声(有些环境不发出声音,只令画面闪烁)

#include <stdio.h>
int main() {
    printf("\a你好");
    return 0;
}

在上述输出代码中输出你好时,你会听见“叮”的一声(不同操作系统提示音可能不同);

3、退格符

退格符\b
输出退格符\b后,当前显示位置就会移动到当前所在行的前一个字符。
并没有规定当前显示位置处于所在行的开头时输出退格符会怎么样,这是因为光标在某些环境下回不到前一行。那么我们怎么运用呢?
比如:

#include <stdio.h>
int main()
{
    printf("12345\n67\b\b\b\b89");
 
    return 0;
}

效果:

12345
89

在上述代码中在12345后使用换行符\n,正常我们使用两个退格符就能达到上述效果,
而在这里我使用了4个,是因为不论使用几个,退格符都不会再向上访问了。

下面我们再写一个有趣的代码:

#include <stdio.h>
#include <Windows.h>
int main() {
    printf("HelloWorld!");
    for (int i = 0; i < 11; i++) {
        Sleep(1000);//每隔一秒
        printf("\b \b");//从后出个消除
        fflush(stdout);//清空缓冲
    }
    return 0;
}

上述代码我们调用一个sleep函数和一个for循环,产生的效果如下:

4、换页符

换页符\f
输出换页符\f后,当前的显示位置就会移动到下一个逻辑页面的开头位置
但在控制台面板中,即使你使用换页符输出,也不会发生任何事情(会多一个空行,肉眼看不见)。
比如:

#include <stdio.h>
int main() {
    printf("你好\f");
    return 0;
}

效果和不输入换页符输出也是一样的。
实际在打印输出需要换页时才会用到换页符

5、换行符

换行符\n
换行符是我们在学习C语言过程中可能经常会用到的转义字符,
输入换行符后,当前显示位置就会移动到下一行的开头
比如:

#include <stdio.h>
int main() {
    printf("你好\n");
    printf("\n");
    printf("程序员");
    return 0;
}

输出结果:

你好

程序员

6、回车符

换行符\r
输出回车符\r后,当前显示位置就会移动到本行开头,灵活应用回车符,我们就能重写已经在画面上显示出来的字符。回车符(‘\r’)和换行符(‘\n’)都是c语言中的一种语言表达方式,前者的作用是输入完一行内容后光标回到当前行的开头却不向下移一行,而后者的作用是跳到下一个新行,输入完一行内容后光标下移一行却不会移到这一行的开头。
我们以下面代码为例:

#include <stdio.h>
#include <Windows.h>
int main()
{
    printf("你是谁");
    fflush(stdout);//清空缓冲

    Sleep(2000);//间隔两秒
    printf("\r程序员");

    return 0;
}

效果:

你是谁

两秒后

程序员

可以看到这段代码可以直接清除本行(调用了fflush)再重新输出,而回车符的作用则是把光标重定位到开头,达到辅助效果;但在这里需要注意的是,如果新输出的字符串比原先显示的字符串短,那么原先显示的字符就不会消失,始终留在原位。
比如:

#include <stdio.h>
#include <Windows.h>

int main()
{
    printf("你是谁");
    fflush(stdout);

    Sleep(2000);
    printf("\r程序");

    return 0;
}

则输出是:

你是谁

两秒后

程序谁

7、水平制表符

水平制表符\t
输出水平制表符\t后,当前显示位置就会移动到本行的下一个水平制表位置
没有规定当前位置位于或超过本行最后的水平制表位置时程序该如何运作,
水平制表位置要取决于操作系统的环境,
有些环境把水平制表位置设定在每行开头8位的地方,
还有些环境把水平制表位置设定在距每行开头4位的地方。
如下面代码所示:

#include<stdio.h>
void main() {
	printf("1234567812345678\n"); 
	printf("\ta\n");                    
	printf("1234\ta\n");                           
	printf("12345678\ta\n");             
	return 0;
}

输出结果:

在这段代码中,我们可以很好的观察到,在我的操作系统中,一个水平制表位是8个空格

8、垂直制表符

垂直制表符\v
输出垂直制表符\v后,当前显示位置就会移动到下一个垂直制表位置中最开始的位置
没有规定当前位置位于或超过本行最后的垂直制表位置时程序该如何运作。
如下面代码所示:

#include<stdio.h>
void main() {
		printf("123\v456"); 
		return 0;
}

理论效果:

123
   456

为什么说是理论效果,因为在控制台输出的时候只会有换行效果(手动滑稽)
垂直制表符\v和换页符 f一样,都主要在打印输出时使用

9、反斜杠字符

反斜杠表符 \\
我们用转义字符\\来表示反斜杠字符\
别问为什么,一个输出不了,转义字符用它定义,输出自己当然得再加一个嘛
这个没什么好讲的。。。

10、问号字符

问号字符 \?
表示问号的转义字符是\?。因为可以不用\? 而只用?,
所以基本上没什么人使用这个转义字符,这个和上面那个一样无聊。。。

11、单引号字符和双引号字符

单引号字符\’和双引号字符\”
表示单引号和双引号的转义字符分别是\’和\”。
在字符串常量中,双引号必须用\”来表示,表示字符串12"3的字符串常量就是"12\”3"。
另外,单引号可以用’和\’这两种方式来表示,
单引号的字符常量写为’ \’ ‘(不能写为’‘’)。表示双引号的字符常量则可以写为’ " ‘或’ \" '。
(这单双引号快给我搞吐了)
这个原理有点像上面的反斜杠,因为本身和printf函数里的双引号冲突
比如下面代码:

#include<stdio.h>
void main() {
	printf("关于字符串常量和字符常量。\n");

	printf("双引号"); 
	putchar('"');
	printf("\n");
	printf("用双引号括起来的\"123\"是字符串常量。\n");//双引号的体现

	printf("单引号"); 
	putchar('\'');
	printf("\n");
	printf("用单引号括起来的'1'是字符常量。\n");//单引号的体现

	return 0;
}

输出结果:

关于字符串常量和字符常量。
双引号"
用双引号括起来的"123"是字符串常量。
单引号'
用单引号括起来的'1'是字符常量。

三 、八进制转义字符

八进制转义字符\ddd
八进制转义字符的格式就是\ddd(有些书上是\ooo,这个字母本身替代的是八进制数,所以用什么字母替代不重要),d的范围是0~7,用1到3位八进制数来表示。
举个例子:

#include<stdio.h>
void main() {
	printf("%c\n", '\141');
	printf("%d", '\141');
	return 0;
}

输出结果是

a
97

第一个打印输出函数调用的是单个字符格式化符号,在ASCII中八进制数141是字母a;
第二个打印输出函数调用的是十进制整型数据格式化符号,八进制数141转为十进制数就是97。

四、十六进制转义字符

十六进制转义字符\xhh
十六进制转义字符的格式是\xhh(和八进制转义字符描述类似)
\x是固定的,h的范围是0-F,用任意位数的十六进制数来表示。
举个例子:

#include<stdio.h>
void main() {
	printf("%c\n", '\x2B');
	printf("%d", '\x2B');
	return 0;
}

输出结果是

+
43

第一个打印输出函数调用的是单个字符格式化符号,在ASCII中十六进制数2B是字符+;
第二个打印输出函数调用的是十进制整型数据格式化符号,十六进制数2B转为十进制数就是43。

ASCII表对应可以看这:ASCII码一览表

使用八进制和十六进制转义字符的时候一定要注意它的值的范围,它们的本质是表示那些不能显示的ASCII字符,标准ASCII码表码值的最大值为127,拓展ASCII码表码值的最大值到255.当转义字符的表示值过大时,此时的转义字符就没有实际的意义了。

五、总结

这就是所有的转义字符的介绍了,文章有些专业术语介绍来自《明解C语言中级篇》,作者也非常推荐大家看这本书,非常适合小白入门C语言。

制作不易,看了这么多,给个一键三连呦!
如有不正之处,敬请指出,感谢你的来访!!!😊😊😊

有关C语言初阶之转义字符的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. Ruby 解析字符串 - 2

    我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?

  3. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  4. ruby-on-rails - unicode 字符串的长度 - 2

    在我的Rails(2.3,Ruby1.8.7)应用程序中,我需要将字符串截断到一定长度。该字符串是unicode,在控制台中运行测试时,例如'א'.length,我意识到返回了双倍长度。我想要一个与编码无关的长度,以便对unicode字符串或latin1编码字符串进行相同的截断。我已经了解了Ruby的大部分unicode资料,但仍然有些一头雾水。应该如何解决这个问题? 最佳答案 Rails有一个返回多字节字符的mb_chars方法。试试unicode_string.mb_chars.slice(0,50)

  5. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  6. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  7. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  8. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  9. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  10. ruby - 如何使用文字标量样式在 YAML 中转储字符串? - 2

    我有一大串格式化数据(例如JSON),我想使用Psychinruby​​同时保留格式转储到YAML。基本上,我希望JSON使用literalstyle出现在YAML中:---json:|{"page":1,"results":["item","another"],"total_pages":0}但是,当我使用YAML.dump时,它不使用文字样式。我得到这样的东西:---json:!"{\n\"page\":1,\n\"results\":[\n\"item\",\"another\"\n],\n\"total_pages\":0\n}\n"我如何告诉Psych以想要的样式转储标量?解

随机推荐