C语言概念之旅:解锁关键字,字符,字符串的秘密,揭秘语句和注释,程序员的宝藏
C语言往期系列文章目录
往期回顾:
- C语言是什么?编程界的‘常青树’,它的辉煌你不可不知
- VS 2022 社区版C语言的安装教程,不要再卡在下载0B/s啦
- C语言入门:解锁基础概念,动手实现首个C程序
文章目录
- C语言概念之旅:解锁关键字,字符,字符串的秘密,揭秘语句和注释,程序员的宝藏
- C语言往期系列文章目录
- 前言
- 一、关键字介绍
- 二、字符和ASCII编码
- 2.1 ASCII码表
- 三、字符串和\0
- 四、转义字符
- 4.1 三字母词
- 4.2 常见问题
- 4.3 \ddd 和 \xdd
- 五、语句和语句分类
- 5.1 空语句
- 5.2 表达式语句
- 5.3 函数调用语句
- 5.4 复合语句
- 5.5 控制语句
- 六、注释
- 6.1 注释的两种形式
- 6.1.1 /\*……\*/
- 6.1.2 //
- 6.2 编译器的处理
- 七、证明\0是字符串的结束标志
- 总结
前言
上篇学习了我们的第一个C语言程序,也知道了printf是用来打印信息到屏幕上的,以及main函数和库函数的特点我们也了解了,本期涵盖了C语言的多个关键方面,从基础的关键字介绍到字符和ASCII编码,再到字符串、转义字符、语句分类以及注释等话题。每个部分都包含了相关的文章标题或编号,方便读者快速定位感兴趣的内容。
接下来,让我们一起深入探索C语言的奥秘,开启一段充满挑战与收获的编程之旅吧!
一、关键字介绍
C语言中有一批保留的名字的符号,比如: int 、 if 、 return ,这些符号被称为保留字或者关键字。
注意,关键字都有以下特点:
- 关键字都有特殊的意义,是保留给C语言使用的
- 程序员自己在创建标识符的时候是不能和关键字重复的
- 关键字也是不能自己创建的
其次,在C99标准中加入了 inline 、 restrict 、 _Bool 、 _Comploex 、 _Imaginary 等关
键字。我们可以通过 cplusplus 网站查询关键字链接,其余的关键字,我们在后面的学习过程中,会逐渐接触的。
二、字符和ASCII编码
我们可以发现,在我们的学习过程中,我们的键盘可以在屏幕上敲出各种字符,例如:abcdef、%、¥、*……等等字符,这些字符在C语言中是用 单引号 括起来的,‘a’、‘b’、‘%’……
那它们在计算机中是如何存储的呢?计算机能够识别的是二进制,而数据在存储的时候也是二进制。那这些英文字母是如何存储的呢?
其实这些字符在计算机中的存储依赖于一种编码方案,其中最广泛使用的是ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)编码。ASCII编码为英文字母、数字和一些特殊符号分配了唯一的数字代码,这些代码以二进制形式存储。
对于ASCII码表,我们只需要记住常用的就行了。
常用的ASCII码如下:
我们可以用以下代码来打印这些字符
//C语言字符的演示
#include <stdio.h>
int main()
{
//32-127
int i = 0;
for (i = 32; i <= 127; i++)
{
if (i % 16 == 0)
printf("\n");
printf("%c ", i);
}
return 0;
}
结果如下:
我们要打印出字符,我们就得用%c来打印,这个在第三篇当中我们就了解过了占位符的概念。
2.1 ASCII码表
ASCII码可以在cplusplus网站查询 (链接)
三、字符串和\0
刚刚我们说,字符是用单引号’'括起来的,例如:‘a’,‘b’……,那什么样算字符串呢?我们看下述代码
//字符和字符串
int main()
{
//字符
'a';
'b';
'c';
//字符串
"abc";
"";//空字符串
return 0;
}
C语言中是如何表示字符串呢?使用双引号括起来的一串字符就被称为字符串,如:“abcdef”,就是⼀个字符串。
字符串的打印,我们既可以直接用printf打印,也可以使用占位符 %s 来指定,如下所示:
//字符串的打印
#include<stdio.h>
int main()
{
printf("hello world\n");
printf("%s\n", "hello world");
return 0;
}
其实C语⾔字符串中有⼀个特殊的知识,就是在字符串的末尾隐藏放着⼀个 \0 字符,这个 \0 字符是字符串的结束标志。
在VS 2022 社区版中,我们可以打开监视看到 \0 字符。
对于字符串"hello world",我们实际上看到了11个字符:h,e.l.l,o, ,w,o,r,l,d。但是实际上在未尾还隐藏一个\0的转义字符,\0是字符串的结束标志。所以我们在使用库函数 printf()打印字符串或者strlen()计算字符串长度的时候,遇到\0的时候就自动停止了。
在文章的末尾我会给大家验证,\0 是字符串结束的标志。
四、转义字符
也许在前面的代码中,看到 \n , \0 的时候很纳闷,这啥玩意,是干什么的。其实在字符中有一组特殊的字符,它们叫转义字符,顾名思义呢,就是转变原来的意思的字符。
就比如下面的两段代码:
//转义字符
//代码1
int main()
{
printf("abcdnef");
return 0;
}
//代码2
int main()
{
printf("abcd\nef");
return 0;
}
上述代码的对比如图所示,可以看到字母n被转义了,变成了\n,它的作用其实是换行。
那像这样的转义字符还有很多。
我们就讲几个特殊的概念
4.1 三字母词
三字母词是C语言早期版本中的一种特性,用于在缺少某些字符集的计算机上表示特殊字符。然而,这一特性在现代C语言中已不再常用,且许多编译器可能不再支持。
//三字母词
??) -> ]
??( -> [
三字母词在被编译的时候会被转换成一个字符,例如下面这段代码
printf("(are you ok??)");
这段代码的输出结果就会变成,are you ok],实际我们想输出are you ok??),这个时候我们想输出我们想要的片段就得把前面的两个问号单独转义变成 \? \? ) ,这样这个三字母词就不会被转义成 ] 了。
4.2 常见问题
在转义字符上,我们也常常遇到一些问题,这时候我也整理了一些问题出来
问题1:想打印单字符常量发现出现问题,无法识别
例如下面这段代码:
//错误示例
int main()
{
printf("%c",''');
return 0;
}
这是因为左边的两个被识别成一对了,后面一个无法识别,而我们本意是想打印一个单字符常量。
这时候我们就需要把中间的这个单字符常量变成转义字符。
//正确示例
int main()
{
printf("%c",'\'');
return 0;
}
问题2:想打印路径发现出现问题,无法打印出完整路径
//错误示例
int main()
{
printf("C:\Users\YunShanRuo\source\repos\Question");
return 0;
}
这是我的某个路径,我们可以发现,运行结果是一堆我根本看不懂的东西
这时候,我们可以加两个斜杠
//正确示例
int main()
{
printf("C:\\Users\\YunShanRuo\\source\\repos\\Question");
return 0;
}
这样,我们打印的时候就不会出问题了,当然在某些编译器上,如果遇到路径有问题,可以使用/来表示路径,因为一些编译器是支持识别的。
4.3 \ddd 和 \xdd
\ddd 和 \xdd 实际是一个进制的表示法,如图所示
\ddd
- 定义:\ddd 表示1~3个八进制数字。在计算机编程中,这种表示法常用于字符编码,特别是当需要表示一些特殊字符或控制字符时。
- 原理: 当编译器遇到 \ddd 这样的转义序列时,它会将 \ 后面的八进制数字转换成对应的十进制ASCII值,然后输出该ASCII值所代表的字符。
- 示例: 例如,\101 表示八进制数101,转换成十进制是65,而ASCII码65对应的是大写字母A。因此,\101 在输出时会被替换为大写字母A。
\xdd
- 定义:\xdd 表示两个十六进制数字。与 \ddd 类似,这种表示法也用于字符编码。
- 原理: 编译器会将 \x 后面的十六进制数字转换成对应的十进制ASCII值,并输出该ASCII值所代表的字符。
- 示例: 例如,\x41 表示十六进制数41,转换成十进制是65,ASCII码65对应的是大写字母A。因此,\x41 在输出时会被替换为大写字母A。
五、语句和语句分类
C语言的代码是由一条一条语句构成的,那什么是语句呢?
如果我们笼统一点说的话,一个分号就是一条语句。
C语言的语句分为以下的五大类:
5.1 空语句
空语句是最简单的语句,因为它一个分号就是一条空语句。
#include<stdio.h>
//空语句演示
int main()
{
;//这是一个空语句
return 0;
}
空语句,⼀般出现的地方是:这里需要⼀条语句,但是这个语句不需要做任何事,就可以写⼀个空语句。
5.2 表达式语句
表达式语句就是在表达式的后边加上分号。如下所示:
#include<stdio.h>
//表达式语句演示
int main()
{
int a = 5;
int b = 5;
b = a + 5 ;//这是一个表达式语句
return 0;
}
5.3 函数调用语句
函数我们之后会学,我们可以提前看看函数调用语句是什么样子的。
#include <stdio.h>
int Add(int x, int y)
{
return x + y;
}
int main()
{
printf("hehe\n");//这也是一个函数调用语句(调用库函数printf)
int ret = Add(2, 3);//这是一个函数调用语句
return 0;
}
5.4 复合语句
多条语句组合在一起就叫复合语句,也就是代码块,成对括号中的代码就构成⼀个代码块,也被称为复合语句。
#include <stdio.h>
int Add(int x, int y)//函数的⼤括号中的代码也构成复合语句
{
return x + y;
}
int main()
{
int i = 0;
for(i=0; i<10; i++) //for循环的循环体的⼤括号中的就是复合语句
{
printf("%d ", i);
}
return 0;
}
5.5 控制语句
控制语句用于控制程序的执行流程,以实现程序的各种结构方式(C语言支持三种结构:顺序结构、选择结构、循环结构),它们由特定的语句定义符组成,C语⾔有九种控制语句。
可分成以下三类:
- 条件判断语句也叫分支语句:if 语句、switch 语句;
- 循环执行语句:do……while 语句、while 语句、for 语句;
- 转向语句:break 语句、goto 语句、continue 语句、return 语句。
我们之后写到分支循环的时候会一一介绍的,提前了解一下。
六、注释
注释是对代码的说明,编译器会忽略注释,也就是说,注释对实际代码没有影响。注释是给程序员自己,或者其他程序员看的。好的注释可以帮我们更好的理解代码,但是也不要过度注释,不要写没必要的注释。当然不写注释可能会让后期阅读代码的人抓狂。
6.1 注释的两种形式
以下片段来自《高质量 C++/C 编程指南》
C 语言的注释符为“ /…/”。 C++语言中,程序块的注释常采用“ /…/”,行注释 一般采用“ //…”。
注释通常用于:
(1)版本、版权声明;
(2)函数接口说明;
(3)重要的代码行或段落提示。
虽然注释有助于理解代码,但注意不可过多地使用注释。
6.1.1 /*……*/
//注释演示
/*
#include<stdio.h>
//正确示例
int main()
{
printf("c:\\users\\yunshanruo\\source\\repos\\question");
return 0;
}
*/
在我们的VS2022 上可以看到上述代码都变绿色了,这样就代表我们注释了这一段代码。这种注释方式也有缺陷,如下所示:
//注释演示
/*
#include<stdio.h>
//正确示例
int main()
{
/*
printf("c:\\users\\yunshanruo\\source\\repos\\question");
return 0;
*/
}
*/
第一个/* 只会匹配到return 0 ; 之后的 */ ,而不会匹配到末尾的注释符号。
6.1.2 //
// 是C99标准才引入的一种注释方式,它有个坏处,就是只能注释一行。
注释演示
//#include<stdio.h>
正确示例
//int main()
//{
//
// printf("c:\\users\\yunshanruo\\source\\repos\\question");
// return 0;
//
//}
6.2 编译器的处理
注意,编译的时候,我们的注释会被替换成空格,所以注释在某些情况下,不能乱用。就比如下面这段代码:
int main()
{
int n/**/um = 10; //报错语句
return 0;
}
这里的num 实际上会被编译器处理成 n [空格] um , 编译器看到这段的时候就蒙了,n um = 10;就无法正常识别,所以注释使用的时候还是要注意一些。
七、证明\0是字符串的结束标志
要证明 \0 是字符串的结束标志,我们就得用一个概念,数组,顾名思义,数组就是一组数据。接下来就让我用代码来验证一下:
//验证'\0'是结束标志。
#include<stdio.h>
int main()
{
char arr1[] = "hello world";
char arr2[] = { 'a','b','c'};
printf("%s\n", arr1);
printf("%s\n", arr2);
return 0;
}
结果如下:
这两个数组其实是有差距的。没有\0的数组打印乱码。我们可以通过调试来观察数组:
我们发现数组,arr1的末尾是有 \0 的,它的打印是正常的,arr2的末尾是没有 \0 的,它的打印是不正常的。它们的存储是什么样的?如下图所示:
那如果arr2的末尾也有 \0 ,那打印是否正常了呢?我们将代码改成下述片段:
//验证'\0'是结束标志。
#include<stdio.h>
int main()
{
char arr1[] = "hello world";
char arr2[] = { 'a','b','c','\0'};
printf("%s\n", arr1);
printf("%s\n", arr2);
return 0;
}
按下F5,观察结果
因此我们可以发现,当字符串的末尾有 \0时,printf遇到就对自动停止打印,而没有,就会继续打印下去,直到停止打印,而这部分通常以乱码的形式呈现给我们。所以空字符 ‘\0’ 在C语言中作为字符串的结束标志起着至关重要的作用,它确保了字符串能够被正确地处理和打印。在处理字符时,一定要考虑 \0 的存在。
总结
通过本文章的学习,我们深入了解了C语言的关键字、字符编码、字符串处理、转义字符、语句分类以及注释等核心概念。我们学会了如何使用这些基础知识来编写功能强大的C语言程序,并尝试掌握了良好的编程习惯和思维方式。希望读者朋友们能够继续深化对C语言的理解和运用,为未来的编程之路打下坚实的基础。