00. 常用指令
指令组成: 指令 [选项] [参数]
0001. ls
查看文件目录内容 ls
查看文件目录中的隐藏文件 ls -a
查看文件目录中的详细信息 ls -l
第一个字符表示文件类型,文件类型包括:
-
:表示普通文件d
:表示目录l
:表示符号链接c
:表示字符设备文件b
:表示块设备文件s
:表示套接字文件p
:表示管道文件
后面九个字符分别表示当前用户、当前用户所属组、其他用户的读写执行权限。
0002. mkdir
创建文件目录 mkdir 文件目录名
创建多个文件目录 mkdir [-p] 文件目录1 文件目录2
0003. cd
进入文件目录中 cd 相对路径/文件目录
,相对路径是相对于当前文件目录中的文件目录
cd 绝对路径/文件目录
,绝对路径表示从根目录开始找到要进入的文件目录。
根目录/
。
bin
:系统的启动程序
etc
:系统的配置文件
home
:家目录、用户目录
lib
:第三方库
回到主目录 cd ~
或者cd
回到根目录 cd /
返回上一级 cd ..
0004. touch
创建文件 touch 文件名
仅创建
0005. gedit
编辑文件 gedit/vi/vim 文件名
,gedit
会打开编辑界面,vi/vim
没有编辑界面还是依赖于命令窗口。gedit
特点是文件不存在在保存时进行创建文件,若文件存在编辑文件。
0006. cat
查看文件内容 cat
,仅查看
0007. cp
复制(粘贴)文件 cp 文件/路径下文件 目的路径/目标文件
,重名会覆盖文件。
复制文件目录 cp -r 文件目录/路径下的文件目录 目标文件目录/目的路径下的文件目录
0008. mv
剪切文件/文件目录 mv 文件/文件目录/路径下文件/路径文件目录 目标文件/目标文件/目标文件目录/目标路径下文件/目标路径下文件目录
0009. rm
删除文件,永久删除 rm 文件名
删除文件目录 rm -r 文件目录
,也是永久删除
0010. tar
压缩文件,使用tar
命令, 其中c
表示压缩,x
表示解压,v
压缩/解压的详细过程,f
后紧跟压缩后/解压文件。
组合压缩指令为tar -cvf 压缩后文件名.gz 要压缩的文件目录名
组合解压指令tar -xvf 要解压的压缩文件
0011. pwd
查看当前位置路径 pwd
0012. sudo
权限下放,不单独使用 sudo 命令
0013. passwd
修改用户密码 passwd 用户名
0014. apt-get
在线安装 sudo apt-get install ...
在线更新资源包 sudo apt-get update
0015. clear
清理屏幕 clear
0016. history
查看历史操作记录 history
01. 数据类型
0101. C语言程序
运行一个C语言程序需要三个步骤,分别是编写源程序、编译源程序和运行源程序。所有C语言程序的后缀都是以.c
结尾。
010101. 编写源程序
按照一下创建并编写一个C语言源程序文件。
在C语言的编写中一定要有一个良好的编码习惯,下面是一些编码习惯:
- 每行只写一句代码。
- 每行代码以分号
;
结尾。 - 每行代码注意缩进。
- 注释 ---- 注释的内容不参与编译。
-
单行注释 ----
//
-
多行注释 ----
/**/
-
010102. 编译源程序与运行
C语言是一个高级语言,需要使用第三方编译器,我们这里用的是gcc
编译器。编译有两种方式,第一种是直接生成,使用gcc xxx.c
,会自动生成a.out
文件。第二种是自定义编译文件,可以自定义编译名字,使用gcc xxx.c -o 自定义文件名
。运行的时候只需要执行生成的可执行文件即可。
0102. 数据类型
所谓的数据都是二进制类型的数据。在程序中的数据主要是十进制、八进制、十六进制的数据,而处理的最终结果仍然是二进制的数据。首先需要说一下关于进制转换。
010201. 进制转换
-
八进制:以
0
开头或者以\
开头,如\101
,逢8进1 ---- 0~7。 -
十进制:逢10进1 ---- 0~9。
-
十六进制:以
0X
开头,逢16进1 ---- 0~9 和 A~F。 -
十进制转二进制 ---- 短除法逆序取余。
-
二进制转十进制---- 每位数字 × 2 n − 1 每位数字 \times2^{n-1} 每位数字×2n−1相加,n表示位数,比如
1011
。
1011 = > 1 × 2 3 + 0 × 2 2 + 1 × 2 1 + 1 × 2 0 1011=> 1\times 2^3 + 0 \times 2 ^ 2 + 1 \times 2 ^ 1 + 1 \times 2^0 1011=>1×23+0×22+1×21+1×20 -
二进制转八进制 ---- 三位一体,例如
1011
=>001 011
=>013
。 -
八进制转二进制 ---- 一位变三位,例如
0101
=>001 000 001
。 -
二进制转十六进制 ---- 四位一体,例如
1011
=>0XB
。 -
十六进制转二进制 ---- 一位变思维,例如
0XB
=>1011
。
关于进制的C语言示例代码如下:
#include <stdio.h>
/*
作者: HT
时间:2023-11-02
功能描述:进制输出
*/
int main()
{
printf("%d\n", 11);
printf("%#o\n", 11);
printf("%#x\n", 11);
return 0;
}
010202. 数据分类
学习数据类型需要记忆以下要点:
- 数据类型的意义 ---- 为什么
- 数据类型的表现形式 ---- 干什么
- 数据类型的空间大小 ---- 所占空间
- 数据类型的应用 ---- 怎么用
这也就是3w1h
,分别是why、what、where、how。下面是数据类型的分类:
- 基本数据类型
char
、int
、float
、double
- 构造数据类型
- 数组、指针、结构体、共用体、枚举
首先说一下关于内存单位的换算:
- 1 Byte = 8 bit
- 1 KB = 1024 Byte
- 1 MB = 1024 KB
- 1 GB = 1024 MB
- 1 TB = 1024 GB
- 1 PB = 1024 TB
- 1 EB = 1024 PB
- 1 ZB = 1024 EB
- 1 YB = 1024 ZB
接下来详细说一下数据类型。
char
类型
char
类型,用于保存字符型数据,存储的是ASCII码,空间大小占用1字节,也就是8个二进制位。根据二进制最小为0000 0000
,最大为1111 1111
。无符号的时候取值范围为0~255
,用unsigned
修饰。有符号的时候取值范围为-128~127
,用signed
修饰。其中有符号的时候最高位是符号位,0
表示正数,1
表示负数。符号位的产生的是为了减法,而为了计算正负数的运算我们产生了原码、反码、补码,在此不对这些做介绍。char
类型的赋值可以使用单个的字符,也可以使用ASCII码。下面是一个ASCII表。
int
类型
int
用于保存整型数据,其空间大小为4
个字节,无符号取值范围为
0
∼
2
32
−
1
0 \sim 2^{32}-1
0∼232−1,有符号取值范围为
−
2
31
∼
2
31
−
1
-2^{31} \sim 2^{31} - 1
−231∼231−1,默认是有符号数。
short
类型
short
用于保存短整型数据,空间大小为2
字节。
long
类型
long
用于保存长整型数据,空间大小为4~8
字节。在32位机器上是4
字节,在64位机器上是8
字节。
float
类型
float
用于保存单精度浮点型数据,小数点后6
位是有效位数,空间大小为4字节,默认显示6
为小数。
double
类型
double
用于保存双精度浮点型数据,小数点后12 ~ 15
位是有效位数,空间大小为8字节,默认显示6
为小数。
0103. 数据类型转换
数据类型转换分为自动数据类型转换和强制类型转换。
- 自动数据类型转换:小类型往大类型转换。
- 强制类型转换:大类型转小类型转换,例如
(int)12.5
。强制类型转换会导致精度的丢失。
0104. 变量
变量是一个可变的量,表示的是一个内存空间。
接下来我们需要从变量的定义、初始化、使用来讨论。
-
变量定义:
数据类型 标识符(变量名) = 初始值;
。- 数据类型包括了基本数据类型和构造数据类型。
- 标识符是由数字、字母、下划线组成。标识符不能以数字开头,也不能是关键字。标识符区分大小写,例如
num
和NUM
是不一样的。最后标识符一定要有意义。 - 上面表达式中的
=
是赋值符号,将右边的内容赋值给左边变量(左边通常是一个变量空间)。 - 局部变量的初始值默认是随机的,我们一般把初始值一般默认赋值为0。
-
变量的初始化:变量的初始化默认一般初始化为0。
-
变量的应用:
- 输入输出:输入输出在头文件
stdio.h
中。-
输入我们常用
printf
函数,输出可有两种,一种是原样输出,如printf("10+10");
;另一种是格式输出,格式输出需要用一些格式符,格式符如下:%c
–char
%d
–int
%f
–float
%lf
–double
%ld
–long
%5d
– 间隔5位,右对齐%.2f
– 保留2位小数%#X
– 十六进制数据%#o
– 八进制数据
格式的作用可以起到占位和约束的作用。格式可以多格式输出,参数列表用逗号隔开。格式对应的数据要与
""
中的格式类型、数量、顺序保持一致。如printf("%d-%d-%d", a, b, c);
。
-
输入我们使用的是
scanf
。输入有原样输入,但是我们一般不用。我们一般使用格式输入。输入格式如下:%c
–char
%d
–int
%f
–float
%lf
–double
%ld
–long
输入的时候接收的数据是往空间地址存的,所以需要一个取地址符
&
。在输入的格式中不要加入换行符(\n
)。scanf
也可以用于多格式输入,例如:scanf("%d%d", &a, &b);
。
-
- 运算
- 比较
- 输入输出:输入输出在头文件
02. 运算符
0201 分类
运算符可以根据操作数进行分类,可以分为单目运算符、双目运算符、三目运算符。比如a++
就是弹幕运算符,a+=b
就是双目运算符、a>b?a:b
就是三目运算符。
运算符还可以根据功能进行划分,分类如下:
-
赋值运算符 ----
=
- 可以将右边的内容赋值到左边变量(左边通常是变量空间)
-
算术运算符 ----
+
、-
、*
、/
、%
/
:int/int=int
,比如5/2=2
,如果想要得到小数,可以5/2.0
。同类型相除得到的是同类型,不同类型相除得到的是大类型。%
:只能int%int=int
-
复合运算符 ----
+=
、-=
、*=
、/=
、%=
- 比如
a += 2
,实际上等效于a = a + 2
。
- 比如
-
自增自减运算符 ----
++
、--
-
比如
a++
等效于a += 1
即a = a + 1
。 -
特性:
++
在前,先加后用;++
在后,先用后加。#include <stdio.h> /* 作者: HT 时间:2023-11-03 功能描述:运算符 */ int main() { int a = 10; printf("a = %d\n", a ++); printf("a = %d\n", a); printf("a = %d\n", ++ a); return 0; }
运行结果为:
-
-
关系运算符 ----
>
、<
、>=
、<=
、==
、!=
- 只有两个结果:真(
1
)、假(0
)。比如m=a>b
,此时m
要么为0
,要么为1
。
- 只有两个结果:真(
-
逻辑运算符 ----
&&
、||
、!
&&
:两个条件都为真才为真。第一个条件为假,则第二个条件不执行。例如int m = 2, n = 2, a = 5, b = 10; m = a > b || n = a < b;
,结果为m = 0, n = 2
。||
:只要有一个条件为真,即为真。第一个条件为真,则第二个条件不执行。
-
条件运算符 ----
条件?真:假
- 结果是一个值。例如
int x = 10, y = 9; --x == y++?--x:++y;
,最后结果是x = 8, y = 10
。
- 结果是一个值。例如
-
位运算符 ---- 二进制运算符
- 按位与(
&
):全1
则1
,与0
则0
。
- 按位或(
|
):全0
则0
,与1
则1
。
- 按位取反(
~
):0
变1
,1
变0
。 - 按位异或(
^
):相同为0
,不同为1
。
- 左移(
<<
):放大2的位移次方
- 右移 (
>>
):缩小到原数据除以2的位移次方取商。
- 按位与(
-
逗号运算符 ----
,
#include <stdio.h> /* 作者: HT 时间:2023-11-03 功能描述:运算符 */ int main() { //定义变量 -- 同时定义多个相同类型的变量 int a = 0, b = 0; //变量赋值 a = (12, 13); // a = 13 //输入输出 printf("%d-%d\n", a, b); return 0; }
-
sizeof()
----整型表达式,用于获取数据类型的空间大小。#include <stdio.h> /* 作者: HT 时间:2023-11-03 功能描述:运算符 */ int main() { int a = 10; printf("%ld\n", sizeof(int)); printf("%ld\n", sizeof(a)); return 0; }
0202. 运算符的优先级
在运算符中,优先级最高的是()
,优先级最低的是=
,算术运算符的优先级大于关系运算符,关系运算符的优先级大于逻辑运算符。
03. 流程控制语句
0301. 流程控制语句
程序是自上向下运行,想要谁先运行就把谁放前边。流程控制语句就是通过判断条件来控制程序的走向。流程控制语句总共只有9
条。流程控制语句分为选择结构、循环结构、控制语句。
030101. 选择结构
03010102. if
选择结构
首先是关于if
的选择结构。包括了if
选择结构、if-else
选择结构、多重if-else
选择结构三种。主要适合于区间范围的判断。
-
第一个场景:小明考试成绩如果成绩大于90分就会获得奖励。
思路就是:
选择结构:
if
选择结构
语法为:if(条件){真};
实现为:
#include <stdio.h> /* 作者: HT 时间:2023-11-06 功能:流程控制语句 if 小明考试成绩如果成绩大于90分就会获得奖励。 */ int main() { printf("请输入小明的成绩:"); int score; scanf("%d", &score); if(score > 90) { printf("获得奖励\n"); } return 0; }
-
第二个场景:小明考试成绩如果成绩大于90分就会获得奖励,否则惩罚。
思路就是:
选择结构:
if-else
选择结构
语法为:if(条件){真}else{假};
实现为:
#include <stdio.h> /* 作者: HT 时间:2023-11-06 功能:流程控制语句 if-else 小明考试成绩如果成绩大于90分就会获得奖励,否则惩罚。 */ int main() { printf("请输入小明的成绩:"); int score; scanf("%d", &score); if(score > 90) { printf("获得奖励\n"); } else { printf("惩罚\n"); } return 0; }
-
第三个场景:小明考试成绩如果成绩大于90分就会获得奖励手机,成绩大于80分则奖励500元,成绩大于60分奖励100元,成绩小于等于60惩罚混合双打加试卷。
思路就是:
选择结构:多重
if-else
选择结构
语法为:if(条件1){真}else if(条件2){真}else{假};
代码实现为:
#include <stdio.h> /* 作者: HT 时间:2023-11-06 功能:流程控制语句 多重if选择结构 小明考试成绩如果成绩大于90分就会获得奖励手机,成绩大于80分则奖励500元,成绩大于60分奖励100元,成绩小于等于60惩罚混合双打加试卷。 */ int main() { printf("请输入小明的成绩:"); int score; scanf("%d", &score); if(score > 90) { printf("获得手机\n"); } else if(score > 80) { printf("奖励500元\n"); } else if(score > 60) { printf("奖励100元\n"); } else { printf("惩罚混合双打加试卷"); } return 0; }
需要注意的是if(60 < score > 90)
是不合法的,多个条件应该用逻辑运算符if(score > 60 && score > 90)
。上面的三种场景的if
都可以相互嵌套。当if
选择结构的{}
里面只有一句代码的时候,{}
也可以省略不写,但是不建议不写。例如:
if(score > 90)
printf("奖励手机一部\n");
else
printf("奖励混合双打\n");
03010102. switch
选择结构
switch
主要用于等值判断,用于最多的是菜单。语法为:
swicth(变量)
{
case 值1:
代码;
break;
case 值2:
代码;
break;
case 值3:
代码;
break;
default:
代码;
break;
}
示例代码:
#include <stdio.h>
/*
作者: HT
时间:2023-11-06
功能描述:switch选择结构
场景菜单 ----- 自助银行菜单
1. 开户 2. 登陆
1. 取钱 2. 存钱 3. 查询余额 4. 修改密码 5. 退出
*/
int main()
{
printf("*********自助银行服务系统************\n");
printf("1. 开户 2. 登陆\n");
printf("*************************************\n");
printf("请选择:");
int n = 0;
scanf("%d", &n);
switch(n)
{
case 1:
printf("-->开户\n");
break;
case 2:
printf("-->登陆\n");
break;
default:
printf("输入有误,请重新输入\n");
break;
}
return 0;
}
需要注意的是break
可以省略,但是省略后无法跳出switch
,继续向下执行。default
也可以省略,省略后没有兜底输出,与其位置无关,等值匹配优先匹配case
中的值。而且在case
中我们也不要去定义变量,根据编译器的不同会出现各种不同的错误。
030102. 循环结构
循环结构有三个,分别是while
、do-while
、for
。
03010201. while
循环结构
先看看使用场景。小明问作业是否合格,若不合格则上午理论学习,下午代码练习,询问是否合格,不合格则继续重复。合格就结束,不再做练习。
上述场景的流程图为:
```mermaid
graph TB
start(开始) --> judge{是否合格}--no-->work[上午理论学习,下午代码练习]-->judge--yes-->pass[合格]
pass-->e(结束)
```
语法为: `while(条件){循环体}`
代码实现为:
```cpp
#include <stdio.h>
/*
作者: HT
时间:2023-11-06
功能描述:while循环结构 小明问作业是否合格,若不合格则上午理论学习,下午代码练习,询问是否合格,不合格则继续重复。合格就结束,不再做练习。
*/
int main()
{
printf("是否合格?(y/n):");
char ch = 0;
scanf("%c", &ch);
while(ch == 'n')
{
printf("上午理论学习,下午代码练习\n");
printf("是否合格?(y/n):");
getchar();
scanf("%c", &ch);
}
return 0;
}
```
`while`先判断后执行,循环体可能一次都不执行,适用于循环次数未知的情况。
03010202. do-while
循环结构
流程图为:
```mermaid
graph LR
start(开始) --> work[上午理论学习,下午代码练习] -->judge{是否合格}--no-->work
judge--yes-->pass[合格]-->en(结束)
```
语法为:`do{循环体}while();`
实现代码为:
```cpp
#include <stdio.h>
/*
作者: HT
时间:2023-11-06
功能描述:do-while循环
*/
int main()
{
char ch = 0;
do
{
printf("上午理论学习,下午代码练习\n");
printf("是否合格?(y/n):");
scanf("%c", &ch);
getchar();
} while(ch == 'n');
printf("合格了\n");
return 0;
}
```
`do-while`特点为先执行后判断,循环体至少被执行一次。适用于循环次数未知,循环体至少执行一次的场景。
在这种结构中需要注意变量的作用域,用于判断的变量需要定义在`do`的外边。
03010203. for
循环结构
`for`循环同`while`循环,是循环次数已知的简化。执行顺序为先执行初始化,再执行循环条件,若条件为真就执行循环体,再继续执行循环条件,再判断是否为真,为真继续执行循环体。直到循环条件为假结束`for`循环的执行。
语法为:`for(初始化;循环条件;计数器改变){循环体}`
示例代码:
```cpp
#include <stdio.h>
/*
作者: HT
时间:2023-11-06
功能描述:for循环
*/
int main()
{
int i = 1;
while(i <= 10)
{
printf("%d ", i);
i ++;
}
for(int i = 1; i <= 10; i ++)
{
printf("%d ", i);
}
return 0;
}
```
`for`循环的特点是先判断后执行,循环体也可能一次都不执行。适用于循环次数已知的情况下。
循环结构解决了代码重复的问题。使用循环的时候需要找到循环条件,循环条件决定终止循环。同时也需要找到循环操作,也就是循环的内容。循环允许相互嵌套,理论上不允许嵌套超过三层(实际上是可以,但是不推荐)。
030103. 控制语句
控制语句一共有四个,如下:
continue
:结束当前本次循环进入下一次循环,只能在循环中使用。break
:结束当前整个循环,只能在switch
和循环中使用。goto
:跳转到标记位,可以在整个函数中都可以使用。标记位后续必须要有可以执行的代码。return
:第一个作用是结束整个函数,在整个函数中使用。第二个作用是返回值。
04. 数组
记录班级中40位同学的成绩。如果我们用前面的方法,就需要定义40个变量,也就是score1
、score2
、… score40
。这种方法非常麻烦也很繁琐。为了解决这个问题,在C语言中我们提供了一个数组的概念。
数组是一个数据类型,可以用于保存具有相同数据类型的一组数据。数组有两个特点,第一个是数组中的元素具有相同的数据类型,第二个就是数组开辟的多个空间地址是连续的。(如果我们需要存储不同的数据类型的数据,那么需要使用后期学习的结构体。如果我们需要地址不连续的空间,则也需要后期学习的链表。)
数组的表现形式为类型 []
,类型可以有char
、int
、float
、double
、指针、结构体等。定义数组变量时,[]
要写在标识符后面。数组的空间代销由类型(单个数据所占的空间大小)和长度(数组空间中保存的数据个数)决定。计算空间大小的方式有两种,第一种是数组空间大小 = 类型的空间大小 * 长度
,或者数组空间大小 = sizeof(数组名)
。已知数组的空间大小,我们也可以求出来数组的长度,加入数组名为table
,则数组的长度为sizeof(table) / sizeof(table[0])
。
数组的长度是需要提前确定好的。如果后期要修改可以使用宏定义的方式去定义数组的长度.将来需要改的时候只需要修改SIZE
后面的值就行了,宏定义会在预处理阶段进行完全替换。如下面就是一句宏定义。
#define SIZE 5
int num[SIZE];
在Linux的gcc
编译器中也可以使用一个变量来定义长度,通过输入的值来确定数组的长度。但是不建议这样用,因为在其它编译器中并不支持。例如下面代码应该尽量避免:
int size = 0;
scanf("%d", &size);
int arr[size];
数组变量的定义为类型 标识符[长度] = 初始值
。下面是一个定义的示例:
#include <stdio.h>
/*
作者: HT
时间:2023-11-08
功能描述:数组
*/
int main()
{
int num[5] = { 0 }; // 初始化为0
for(int i = 0; i < 5; i ++)
{
printf("%d\n", num[i]);
}
return 0;
}
数组的定义以及初始化有以下一些方式:
int num[5]; // 全是随机数
// 定义的时候进行初始化
int num[5] = { 0 }; // 部分初始化, 全部初始化为0
int num[5] = { 1, 2, 3, 4, 5 }; // 标准初始化
int num[5] = { 1, 2, 3 }; // 部分初始化,只初始化前三个数据, 后面的全补0
int num[] = { 1, 2, 3, 4, 5 }; // 数组长度由数据的个数决定
// 先定义后初始化
int num[5]; // 定义
num[0] = 1;
num[1] = 2;
num[2] = 3;
接下来我们说一下数组下标。数组下标是数组定义时自动产生,默认从0~ 长度-1
结束。在编写程序的时候会出现段错误(核心已转储),这是数组的下标越界错误。通过数组下标进行初始化使用数组名[下标]
表示的是该下标的空间。