0%

===========================
2022-7-18
===========================

一.温故知新

    运算符
        算术运算符		+ - * / %
            注意 : 除法运算符中除数不能为0
        关系运算符		> < == >= <= !=
            注意 : 
            1.一个表达式经过关系运算符的运算最后是真假值
            2.判断两个值是否相等用==
            3.if(a == 13) 建议 if(13 == a)
        逻辑运算符		&& || !
            注意 :
            1.一个表达式经过逻辑运算符的运算最后是真假值
            2.条件1 && 条件2
                条件1为真,会执行条件2
                条件1为假,不会执行条件2
            3.条件1 || 条件2
                条件1为真,不会执行条件2
                条件1为假,会执行条件2
        赋值运算符		= += -= *= /= &= |= ...
            注意 : 先计算右边的项,再和左边结合
        位运算符		<< >> & | ~ ^
            注意 : 操作数符号的问题
        条件运算符		? :
            注意 : 是C语言中唯一的一个三目运算符
        下标运算符		[]
        指针运算符		* &
        分量运算符		. ->
        求字节大小运算符sizeof()
            注意 : sizeof不是函数,是一个运算符
        强制类型转换	()
            注意 : 会在指针的时候使用
        自增自减		++ --
        逗号运算符		,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int a = 0, b = 0;

scanf("%d-%d", &a, &b);

printf("a = %d b = %d\n", a, b);
//通过某种方法交换a和b的值
/*
int tmp = 0;
tmp = a;
a = b;
b = tmp;
a = a + b;
b = a - b;
a = a - b;
*/
a = a ^ b;//a = 1101 ^ 0111 = 1010
b = a ^ b;//b = 1010 ^ 0111 = 1101
a = a ^ b;//a = 1010 ^ 1101 = 0111
printf("a = %d b = %d\n", a, b);

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int a = 10, sum = 0;

sum += a++;

printf("a = %d sum = %d\n", a, sum);

return 0;
}

逗号运算符

    如果一个表达式使用了逗号运算符
        如果没有加小括号,那么会把第一个项的结果赋值给变量
        如果有加小括号,那么会把最后一个项的结果赋值给变量
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int a = 0, b = 10, c = 20, d = 30;

a = (b++,c+5,d+10);

printf("a = %d\n", a);

return 0;
}

分支结构

    if
1.if else是C语言的关键字
2.if使用方法
    语句1
    if(条件)
    {
        语句2
    }
    语句3

语句1->条件的判断(真)->语句2->语句3
        |
        (假)->语句3
3.if else使用方法
    语句1
    if(条件)
    {
        语句2
    }
    else
    {
        语句3
    }
    语句4
语句1->条件的判断(真)->语句2->语句4
        |
        (假)->语句3->语句4
4.if else if else if使用方法
    语句1
    if(条件1)
    {
        语句2
    }
    else if(条件2)
    {
        语句3
    }
    else if(条件3)
    {
        语句4
    }
    else
    {
        语句5
    }
    语句6
语句1->条件1的判断(真)->语句2->语句6
        |
        (假)->条件2的判断(真)->语句3->语句6
                |
                (假)->条件3的判断(真)->语句4->语句6
                        |
                        (假)->语句5->语句6
5.使用if需要注意的问题
    1>if关键字之后必须要写小括号,小括号内必须写内容
    2>else关键字之后不能直接加小括号写条件,需要写成else if
    3>if(条件)之后可以直接加 ; 
        if(条件);
        {
            语句
        }
        等价于
        if(条件)
        {
            ;
        }
        {
            语句
        }
    4>if(条件)之下可以不加大括号
        if(条件)
            语句1
            语句2
        等价于
        if(条件)
        {
            语句1
    	}
        语句2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int c = 0;

scanf("%d", &c);

//if(c % 2 == 0)//判断是否是偶数的条件
if((c & 1) == 0)//位运算符(判断最低位是否为0)
{
printf("%d是偶数!\n", c);
}

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int c = 0;

scanf("%d", &c);

//if(c % 2 == 0)//判断是否是偶数的条件
if((c & 1) == 0)//位运算符(判断最低位是否为0)
{
printf("%d是偶数!\n", c);
}
else
{
printf("%d是奇数!\n", c);
}

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int year = 0;

scanf("%d", &year);

//if((year%4==0&&year%100!=0) || (year%400==0))
if((!(year%4)&&year%100) || !(year%400))
//判断是否是闰年的条件
{
printf("%d年是闰年!\n", year);
}
else
{
printf("%d年是平年!\n", year);
}

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int a = 0, b = 0, c = 0;

scanf("%d-%d-%d", &a, &b, &c);
//if error

if(a+b>c && a+c>b && b+c>a)//判断可以构成三角形的条件
{
if(a*a+b*b==c*c || a*a+c*c==b*b || b*b+c*c==a*a)
//判断可以构成直角三角形的条件
{
printf("可以构成直角三角形!\n");
}
else if(a == b || a == c || b == c)
//判断是否可以构成等腰三角形
{
if(a == b && a == c)
{
printf("可以构成等边三角形!\n");
}
else
{
printf("可以构成等腰三角形!\n");
}
}
else
{
printf("可以构成普通三角形!\n");
}
}
else
{
printf("不能构成三角形!\n");
}

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int i = 0;

scanf("%d", &i);

switch(i)
{
case 1 : printf("Hello World!\n");
case 2 : printf("北京欢迎您!\n");
case 3 : printf("物联网嵌入式!\n");
case 4 : printf("今天好热!\n");
}

return 0;
}
输入年月日,打印出是该年的第几天 //2022-7-18 是2022年的第?天 2022-1-9 9天 2022-2-9 9+31天 2022-3-9 9+(28||29)+31 2022-4-9 9+31+(28||29)+31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int year = 0, month = 0, day = 0;
int flag = 0;//用来标记闰年和平年
int days = 0;//用来存储最后总天数

scanf("%d-%d-%d", &year, &month, &day);
/*if error*/

flag = (!(year%4)&&(year%100)) || !(year%400);
//如果是闰年 flag = 1 否则 flag = 0

switch(month)
{
case 1 : days += day; break;
case 2 : days += (day + 31); break;
case 3 : days += (day + 59 + flag); break;
case 4 : days += (day + 90 + flag); break;
case 5 : days += (day + 120 + flag); break;
case 6 : days += (day + 151 + flag); break;
case 7 : days += (day + 181 + flag); break;
case 8 : days += (day + 212 + flag); break;
case 9 : days += (day + 243 + flag); break;
case 10: days += (day + 273 + flag); break;
case 11: days += (day + 304 + flag); break;
case 12: days += (day + 334 + flag); break;
}

printf("%d年%d月%d日是这一年的第%d天!\n", year, month, day, days);

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int year = 0, month = 0, day = 0;
int flag = 0;//用来标记闰年和平年
int days = 0;//用来存储最后总天数

scanf("%d-%d-%d", &year, &month, &day);
/*if error*/

flag = (!(year%4)&&(year%100)) || !(year%400);
//如果是闰年 flag = 1 否则 flag = 0

switch(month)
{
case 12: days += 30;
case 11: days += 31;
case 10: days += 30;
case 9 : days += 31;
case 8 : days += 31;
case 7 : days += 30;
case 6 : days += 31;
case 5 : days += 30;
case 4 : days += 31;
case 3 : days += (28 + flag);
case 2 : days += 31;
case 1 : days += day;
}

printf("%d年%d月%d日是这一年的第%d天!\n", year, month, day, days);

return 0;
}

循环语句

    for
1.for是C语言中的关键字
2.for循环的使用方法
    语句1
    for(循环变量的赋值; 循环变量的控制; 循环变量的变化)
    {
        循环的语句
    }
    语句2
3.for循环的执行流程
                    语句1
                        |
                        V
                循环变量的赋值
                        |
                        V
            |-<-循环变量的控制--<---|
            |			|			|
            V			V			|
            假			真			|
            |			|			^
            V			V			|
            |		循环的语句		|
            |			|			^
            |			V			|
            |	循环变量的变化-->---|
            |
            |---->------|
                        V
                    语句2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int i = 0, score = 0;

for(i = 0; i < 10; i++)
{
scanf("%d", &score);
printf("score = %d\n", score);
}

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <stdlib.h>
//求3位数字的水仙花数
//百位数字的3次方 +
//十位数字的3次方 +
//个位数字的3次方 == 3位数
int main(int argc, char *argv[])
{
int i = 0;
int b = 0, s = 0, g = 0;

for(i = 100; i < 1000; i++)//[100 ~ 999]所有三位数
{
b = i / 100;//取三位数的百位
s = i / 10 % 10;//取三位数的十位
g = i% 10;//取三位数的个位
if(i == b*b*b + s*s*s + g*g*g)
printf("i = %d\n", i);
}

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int i = 0;
int b = 0, s = 0, g = 0;

for(b = 1; b < 10; b++)
{
for(s = 0; s < 10; s++)
{
for(g = 0; g < 10; g++)
{
if(b*b*b+s*s*s+g*g*g==b*100+s*10+g)
printf("%d\n", b*100+s*10+g);
}
}
}

return 0;
}
/* 打印0~100以内所有的质数(素数) (只能被1 和 本身整除的数) */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int i = 0, j = 0;
int num = 1;

for(i = 2; i < 100; i++)
//该循环为了取出[0-100]以内所有数字
{
for(j = 2; j < i; j++)//该循环为了取出[2 - i-1]
{
if(i % j == 0)//判断是否能被整除
{
break;//如果能被整除说明不是质数,跳出
}
}
if(i == j)
printf("[%d] %d\n", num++, i);
}

return 0;
}
/* 11 是不是质数 11 % 1 = 0 11 % 2 != 0 11 % 3 != 0 11 % 4 != 0 11 % 5 != 0 11 % 6 != 0 11 % 7 != 0 11 % 8 != 0 11 % 9 != 0 11 % 10 != 0 11 % 11 = 0 8 是不是质数 8 % 1 = 0 8 % 2 = 0 能整除 8 % 3 != 0 8 % 4 = 0 能整除 8 % 5 != 0 8 % 6 != 0 8 % 7 != 0 8 % 8 = 0 i 是不是质数 i % 1 = 0 i % [2 ~ i-1] i % i = 0 */

===========================
2022-7-19
===========================

一.温故知新

    分支语句
        if
            if else
            语句1
            if(条件1)
            {
                语句2
            }
            else if(条件2)
            {
                语句3
            }
            else if(条件3)
            {
                语句4
            }
            语句5

        switch(变量)
        {
            case 整常量1: 语句1; break;
            case 整常量2: 语句2; break;
            case 整常量3: 语句3; break;
            default :     语句4; break;
        }
    循环语句
        for(; ;)//这是一个死循环

        for(表达式1; ;表达式2)

        等价于

        for(表达式1; 1; 表达式2)

        int i = 0, j = 0;

        for(i = 0; i < 10; i++)
        {
            for(j = 0; j < 10; j++)
            {
                
            }
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
```C
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int i = 0, j = 0;

for(i = 0; i < 4; i++)//管理行数
{
for(j = 0; j < 5; j++)//管理列数
{
printf("[%d %d]", i, j);
}
printf("\n");
}

return 0;
}
打印99乘法表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int i = 1, j = 1;

for(i = 1; i < 10; i++)
{
for(j = 1; j < 10; j++)
{
if(j <= i)
printf("%d X %d = %d ", i, j, i*j);
}
printf("\n");
}

return 0;
}

99乘法表

“百钱百鸡”问题,百钱买百鸡,公鸡1个3块钱,母鸡1个2块钱,小鸡3个一块钱,问公鸡,母鸡,小鸡各多少个
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int g = 0, m = 0, x = 0;//分别表示公鸡 母鸡 小鸡的个数

for(g = 0; g < 33; g++)
{
for(m = 0; m < 50; m++)
{
for(x = 0; x < 100; x += 3)
{
if((g*3+m*2+x/3==100) && (g+m+x==100))
printf("G:%d M:%d X:%d\n", g, m, x);
}
}
}

return 0;
}

随机函数

    rand();			//功能:就是用来产生随机数的
    rand() % 1000; 	//[0 ~ 999]
    rand() % 100 - 50;//[-50 ~ 49]
    
    srand();		//功能:可以保证每一次产生的随机数可变
        srand函数在调用时需要有可变的因子
        time(NULL);	//时间种子
        getpid();	//进程种子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
int sum = 0;
int i = 0;

//srand(time(NULL));
//注意:srand函数在程序中只能调用一次
srand(getpid());

for(i = 0; i < 5; i++)
{
sum = rand() % 100 - 50;
printf("sum = %d\n", sum);
}

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
int T = 0;//存储随机出的数字
int guess = 0;//存储玩家猜的数字
int num = 1;

srand(getpid());//随机种子

T = rand() % 10;

for(num = 1; ; num++)
{
scanf("%d", &guess);
if(T > guess)
printf("[%d] Small!\n", num);
else if(T < guess)
printf("[%d] Big!\n", num);
else
{
printf("[%d] Bingo!\n", num);
break;
}
}

return 0;
}

循环语句

    do...while循环
1.do while是C语言的关键字
2.do...while循环的使用方法
语句1
do
{
    要循环的语句
}while(循环条件);
语句2
3.do...while循环的执行流程
1
2
3
4
5
6
			|-------<---------<---------
| ^
V |
语句1->要循环的语句->循环条件的判断(真)->
|
(假)->语句2
4.while循环与do...while循环的对比 while : 先执行循环条件的判断,再执行循环的语句 do...while : 先执行循环的语句,再执行循环条件的判断 while : 可以一次也不执行循环的语句 do...while : 至少会执行一次循环的语句
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int i = 1;
int sum = 0;

while(i <= 100)
{
sum += i;
i++;
}

printf("sum = %d\n", sum);

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int i = 0, j = 0;

while(i < 4)
{
j = 0;
while(j < 5)
{
printf("[%d %d]\n", i, j);
j++;
}
i++;
}

return 0;
}
1
2
3
4
5
6
7
8
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{

return 0;
}

跳转语句 : break continue goto return

1.break continue goto return都是C语言的关键字
2.break关键字
    break只能出现在循环结构或者switch语句中
        使用在循环结构中是用来跳出循环的
        使用在switch语句中是用来跳出switch
    如果break关键字出现在嵌套结构中,只作用于最近的那一层
3.continue关键字
    continue关键字只能出现在循环结构中
        使用在循环结构中跳过本次循环,继续下一次循环
4.return关键字
    return关键字一般来说出现在函数最后的位置
    当一个函数碰到return关键字,这个函数会结束,
    会把返回值返回给函数的调用者
    ------------------------------------------
    return返回的返回值有两种含义
    1)返回的是运算的结果
    2)返回的是函数运行的状态
        return 0;		代表函数运行正常
        return 正数;	代表函数运行有异常
        return 负数;	代表函数运行有错误
    ------------------------------------------
    注意 : return关键字一次只能返回一个值
5.goto关键字(太灵活了)
    可以轻易改变代码的结构
    语句1
标识符:
    语句2
    goto 标识符;
    语句3;
    标识符的命名要求和变量的命名要求一致
    (标识符可以和变量重名,但是不要这样使用)
    同一个标识符不能出现在多个位置
    goto不能跨函数使用
*/

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
if(1)
{
break;
}

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int i = 0;

for(i = 0; i < 5; i++)
{
if(i == 2)
//break;
continue;
printf("i = %d\n", i);
}

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
if(!1)
{
flag:
printf("Hello World!\n");
}
else
{
printf("天气好热!\n");
goto flag;
}

return 0;
}

==============================
2022-7-14
==============================

面试题
1.在C语言中以 # 开头的操作是预处理的操作
2.预处理阶段会有哪些操作?
    3个操作,文件包含 条件编译 宏定义
3.从.c文件编译成可执行程序需要经历哪些阶段?
源程序   被预处理过的源文件   汇编文件    目标文件
hello.c-------->hello.i----->hello.s----->hello.o--->a.out
        预处理          编译         汇编        链接
4.包含头文件时使用尖括号或者双引号的区别?
    尖括号 : 默认从指定目录中查找头文件(/usr/include),
            如果找不到报错
    双引号 : 默认从当前目录中查找头文件,如果找不到再从
            指定目录中查找头文件(/usr/include),
            如果再找不到报错
5.C语言中有字符串但是没有字符串类型

#include <stdio.h>
/*
main函数(主函数) : 是程序的入口
当执行可执行程序时,从main函数进入,
按照从上往下的顺序逐行逐行执行代码,
最后从main函数退出

在刚开始写程序时,
多问问自己为什么要写这一行代码?
写这一行代码要干什么?
*/
/*
函数的返回值类型 函数名(参数列表)//该处参数指的是形式参数
{
    程序的代码
}

*/
int main(void)
{
    printf("Hello World!");
/*
    调用了printf函数
    printf函数的功能 : 
        可以把双引号引起来的内容打印输出到终端上
    在C语言中双引号引起来的内容叫做字符串
    在C语言中单引号引起来的内容叫做字符
    字符串是由一个一个单一的字符串组成的,
        最后会有一个结束标志尾0('\0')
    --------------------------------
    "0"		这是一个字符串,是由'0' + '\0'组成
    '0'		这是一个字符,ASCII值48
    '\0'	这是一个字符,并且是一个转义字符,是尾0,ASCII是0
    0		这是一个整数0
*/
}

/*
其实字符就是把计算机世界中的数字和日常生活中的符号
进行一一对应
printf函数
    1.转义字符(除了有数字的对应关系以外还有额外的含义)
        字符	ASCII值		额外的含义
        '\0'	0			字符串的结束标志
        '\n'	10			换行符
        '\r'	13			回车符
        '\t'	9			水平制表符
        '\v'	11			垂直制表符
    2.标准化输出格式
        %d	十进制整数(%03d)
        %x	十六进制输出
        %o	八进制输出
        %f	小数输出(%.2f)
        %c	字符输出
        %s	字符串输出
        %p	地址输出
        %%	打印百分号本身
    3.VT控制码
        可以控制打印输出的属性		
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int i = 0, j = 0;

for(i = 30, j = 47; i <= 37 && j >= 40; i++, j--)
{
printf("\33[%dm\33[%dmHello World!\33[0m\n",i ,j);
}

return 0;
}

==============================
2022-7-15
==============================

一.温故知新

    权限的补充(特殊的权限)
    suid	u+s	(可执行的命令文件中加入u+s)
    sgid	g+s	(目录文件中加入g+s)
    sticky	o+t	(目录文件中加入o+t)
    
    umask值
    666 - 0002 = 664 
    777 - 0002 = 775
    
    进程的介绍
    ps -aux
    kill PID

Linux下的C语言

#include <stdio.h>

int main(void)
{
    printf("Hello World!");
}

函数的返回值类型	函数名	(参数列表)
{
    代码
}
int					main	(void)
{
    printf("Hello World!");
}

'\0'	'\n'	'\r'	'\t'	'\v'
ASCII(常用ASCII表有128个字符<又补充到了256个字符>)
'\0'	0
'\n'	10
'0'		48
'A'		65
'a'		97
标准化输出格式
    %+某一个东西
    %d
    %c
    %f
    %s
    %p
    %%
    %o
    %x
VT控制码

变量

1.变量的含义
    变量是用来存储数据的
    (会把数据存储到内存中<以二进制补码的形式存储>)
2.变量的定义
    数据类型	变量名	;
    1)基本数据类型
    整型	有符号/无符号	short int long
    实型	有符号			float double
    字符型	有符号/无符号	char
    2)通过sizeof运算符进行测试
    测试出的结果以字节为单位
    1字节 = 8位
    sizeof(char) = 1
    sizeof(short) = 2
    sizeof(int) = 4
    sizeof(long) = 8
    sizeof(float) = 4
    sizeof(double) = 8
    测试的结果并不唯一,会随着硬件或者操作系统有所变化
    3)变量名的命名要求
        1>变量名是由数字 字母 下划线组成,但不能以数字开头
        2>变量名是区分大小写的
        3>变量名不能与C语言的关键字重复
        4>变量名要做到见名生义
3.变量的存储
    char c = 13;
    //将来会把十进制整数13转换成8位的二进制的数据存储到
    //c变量所占用的1个字节的存储空间中

    0 0 0 0 1 1 0 1
    在二进制数据中,最左边的是最高位
    在二进制数据中,最右边的是最低位
    第7位	0
    第6位	0
    第5位	0
    第4位	0
    第3位	1
    第2位	1
    第1位	0
    第0位	1
    如果是有符号类型,最高位是符号位,其余位是数据位
    第7位		符号位	(0代表正数 1代表负数)
    第6-0位		数据位

    unsigned char c = 13;
    无符号的数据类型所以范围是[0 ~ 255]
    
    float f = 3.2;
    有符号的数据类型
    float在内存中占用4个字节存储空间(32bit)
    第31位		符号位
    第30位		浮点偏移量的位
    第29-23位	整数位
    第22-0位	小数位
    f = 3.2
    000000011
    0.2 * 2 = 0.4	0
    0.4 * 2 = 0.8	0
    0.8 * 2 = 1.6	1
    0.6 * 2 = 1.2	1
    0.2 * 2 = 0.4	0

    变量会存储在内存中,以二进制补码的形式进行存储
原码 : 把操作数从别的进制转化成二进制,就是原码
    程序员要的是原码(printf打印出的数据是原码数据)
补码 : 如果操作数为正,那么原码等于补码
        如果操作数为负,那么原码不等于补码,需要转换
        无论是原码转换成补码,还是补码转换成原码,公式都一样
        除了符号位不变,其他位按位取反,再加1
    计算机要补码(计算机在计算的时候需要用补码计算)
为什么使用补码存储数据?
    1)保证0的唯一性
    2)为了保证加法运算的合理
    1-1 -> 1 + (-1) 
            0001 + 1001 = 1010 = -2
            0001 + 1111 = 0000 = 0

存储

二转十

进制间转换

按位取反

4.变量的初始化
    数据类型	变量名	=	数值	;
    char		c		=	13		;
    int			a		=	9527	;
    float		f		=	3.14	;
5.变量的定义和变量的初始化有什么区别?
    变量的定义 : 只是在内存中分配了相应的存储单元,
                    存储空间中是垃圾值
    变量的初始化 : 除了在内存中分配了相应的存储单元,
                    也在存储空间中保存了初始值
    注意 : 当你定义变量时一定要有初始化
6.变量的使用规则
    1)变量要先定义再使用
        (把变量的定义放到main函数的开头的位置)
    2)不同类型的变量有不同的运算要求
    3)变量在定义时在内存中占用的空间大小就已经确定了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
printf("sizeof(char) = %ld\n", sizeof(char));
printf("sizeof(short) = %ld\n", sizeof(short));
printf("sizeof(int) = %ld\n", sizeof(int));
printf("sizeof(long) = %ld\n", sizeof(long));
printf("sizeof(float) = %ld\n", sizeof(float));
printf("sizeof(double) = %ld\n", sizeof(double));

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
char c = -1;

printf("c = %p\n", c);
//%p可以打印出变量在内存中是如何存储的
/*
c = 0xff;//1111 1111
char c = -1;
原码 1 0 0 0 0 0 0 1
补码 1 1 1 1 1 1 1 1
*/

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
char c = -13;

printf("c = %p\n", c);
//%p可以打印出变量在内存中是如何存储的
/*
c = 0xff;//1111 1111
char c = -1;
原码 1 0 0 0 0 0 0 1
补码 1 1 1 1 1 1 1 1

char c = -128;
原码 1 0 0 0 0 0 0 0
补码 1 0 0 0 0 0 0 0
0x80

char c = -13;
原码 1 0 0 0 1 1 0 1
补码 1 1 1 1 0 0 1 1
c = 0xf3
*/

return 0;
}
面试题 1.进制之间转换 八进制<------->二进制<-------->十六进制 ^ | V 十进制 1)十进制转换成二进制 除以2取余 2)二进制转换成十进制 2的n次方 2.除了常用进制以外,笔试题会考三进制 五进制 七进制 十五进制 ============================================ 作业: 1.把今天讲过的内容完完整整的复习一遍 2.多做一些进制之间转换的题目 ============================================ int i = 100; int i = 'a'; char c = 13; char c = 'A';//char = 1/4int

scanf函数

函数功能 : 用来接收键盘录入的函数
    scanf("%d", &i);
注意:
    1.在scanf函数的双引号中只写标准化输出格式即可
    2.在scanf函数的双引号中不要加换行符
    3.在scanf函数的双引号之后需要的是地址
gcc编译器是不检查段错误(由于操作内存不当引起的)的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int i = 0;

printf("i = %d\n", i);

printf("请输入变量i的值:");
//scanf("%d\n", &i);
scanf("%d", i);

printf("i = %d\n", i);

return 0;
}

算术运算符

    +	加法
    -	减法
    *	乘法
    /	除法(取商)
    %	除法(取余/取模)
注意 : 
    除法运算中,除数不能为0
    int a = 13, b = 7, sum = 0;
    sum = a + b;
    sum = a - b;
    sum = a * b;
    sum = a / b;//a所在的位置是被除数,b所在的位置是除数
    sum = a % b;//a所在的位置是被除数,b所在的位置是除数
如果在除法运算中,被除数 小于 除数, 商是0, 余数是被除数本身
    sum = 7 / 13;// sum = 0
    sum = 7 % 13;// sum = 7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int a = 7, b = 13;

printf("a + b = %d\n", a + b);
printf("a - b = %d\n", a - b);
printf("a * b = %d\n", a * b);
printf("a / b = %d\n", a / b);
printf("a %% b = %d\n", a % b);

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int sum = 0;

scanf("%d", &sum);
//通过scanf函数为sum变量录入4位的正整数
//atoi(); itoa();
/* itoa();
9527 -> "9527"
9527 / 1000 = 9 + '0' = '9'
9527 / 100 % 10 = 5 + '0' = '5'
9527 / 10 % 10 = 2 + '0' = '2'
9527 % 10 = 7 + '0' = '7'
*/
printf("千位 : %d\n", sum / 1000);
printf("百位 : %d\n", sum / 100 % 10);
printf("十位 : %d\n", sum / 10 % 10);
printf("个位 : %d\n", sum % 10);

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int a = 0, b = 0;
int tmp = 0;

scanf("%d-%d", &a, &b);

printf("a = %d b = %d\n", a, b);
//通过某种方法交换a和b的值
/*
tmp = a;
a = b;
b = tmp;
*/

a = a + b;//a = 13 + 7 = 20
b = a - b;//b = 20 - 7 = 13
a = a - b;//a = 20 - 13 = 7

printf("a = %d b = %d\n", a, b);

return 0;
}

关系运算符

    >		是否大于
    <		是否小于
    ==		是否相等
    >=		是否大于等于
    <=		是否小于等于
    !=		是否不等于
一个表达式经过关系运算符的运算,最终会生成真假值
    0为假,非0为真
    默认的真值是1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
printf("13 > 7 = %d\n", 13 > 7);
printf("13 < 7 = %d\n", 13 < 7);
printf("13 == 7 = %d\n", 13 == 7);
printf("13 >= 7 = %d\n", 13 >= 7);
printf("13 <= 7 = %d\n", 13 <= 7);
printf("13 != 7 = %d\n", 13 != 7);

return 0;
}

逻辑运算符

    &&	逻辑与	表达式1 && 表达式2
        全真才为真,有假就是假
    ||	逻辑或	表达式1 || 表达式2
        全假才为假,有真就是真
    !	逻辑非	!(表达式)
        真假互换
    表达式1 && 表达式2
        如果表达式1为真,会执行表达式2的内容
        如果表达式1为假,不会执行表达式2的内容
    表达式1 || 表达式2
        如果表达式1为真,不会执行表达式2的内容
        如果表达式1为假,会执行表达式2的内容
-----------------------
1.罗列一下判断是否是闰年的条件
(能被4整除但是不能被100整除 或者 能被400整除)
(year % 4 == 0 && year % 100 != 0) || (year%400==0)
2.罗列三角形的条件(普通 直角 等腰 等边)
    a b c
    a + b > c && a + c > b && b + c > a
    a * a + b * b == c * c ||
    a * a + c * c == b * b ||
    b * b + c * c == a * a
    a == b || a == c || b == c
    a == b && a == c
-----------------------
1
2
3
4
5
6
7
8
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
	
# 赋值运算符
= += -= *= /= %= <<= ...
会把赋值运算符右边的项先进行计算,
再赋值给赋值运算符左边的项(左值)
a += 1; // a = a + 1;
int a = 10;
a *= 2 + 3;// a = a * (2 + 3);
a = 50
```C
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{

return 0;
}

条件运算符

    也是C语言唯一的一个三目运算符
    ? :
    part.1 ? part.2 : part.3;
如果part.1为真,会执行part.2的内容
如果part.1为假,会执行part.3的内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int a = 0, b = 0;
int min = 0;

scanf("%d-%d", &a, &b);

min = a < b ? a : b;

printf("min = %d\n", min);

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int year = 0;

scanf("%d", &year);

(year%4==0&&year%100!=0)||(year%400==0)?printf("%d年是闰年\n", year) : printf("%d年是平年\n", year);

return 0;
}

强制类型转换

    (数据类型)
    可以把操作的内容临时的强制转换成某种数据类型
    将来会在底层内核驱动大量使用强制类型转换的运算符
1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
float f = 3.14;

printf("f = %d\n", (int)f);

return 0;
}

自增自减运算符

    ++	自增
    --	自减
    如果a++或者++a自己为独立的一条语句,执行时没有区别
    如果和别的语句一起使用,会有区别
    a++ : 先使用a的值做操作,再自增
    ++a : 先自增,再使用a的值做操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int a = 0;

printf("a++ = %d\n", a++);

a = 0;

printf("++a = %d\n", ++a);

return 0;
}
注意 : 作为嵌入式开发工程师,2的0次方 ~ 2的10次方 在底层内核驱动中做位运算需要保证是在无符号的环境中进行运算 位运算符 << 按位左移 会把操作数的二进制位,每一位都进行左移的操作 在某种程度上来说,按位左移相当于是乘法运算 左移多少位就相当于乘以2的多少次方 char c = 13; c <<= 3;//c * 2的3次方 = 13 * 8 = 104 >> 按位右移 会把操作数的二进制位,每一位都进行右移的操作 在某种程度上来说,按位右移相当于是除法运算(取商) 右移多少位就相当于 / 2的多少次方,取商 & 按位与 全1才是1,有0就是0 | 按位或 全0才是0,有1就是1 ~ 按位取反(每一位都要取反) 0变成1,1变成0 ^ 按位异或 相同为0,不同为1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
char c = 13;//00001101

printf("c = %d\n", c);

//c = c << 2;//00110100->32+16+4=52
//c = c << 3;//01101000->64+32+8=104
c = c << 8;

printf("c = %d\n", c);

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
char c = 13;//00001101

printf("c = %d\n", c);

c = c >> 2;//00000011

printf("c = %d\n", c);

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
char a = 13, b = 7;
char c = 0;

printf("c = %d\n", c);

c = a & b;
/*
a 0 0 0 0 1 1 0 1
&
b 0 0 0 0 0 1 1 1
=
c 0 0 0 0 0 1 0 1
*/

printf("c = %d\n", c);

c = a | b;
/*
a 00001101
|
b 00000111
=
c 00001111
*/
printf("c = %d\n", c);

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
char c = 13;//00001101

printf("c = %d\n", c);
c = ~c; //11110010->-114
printf("c = %d\n", c);

return 0;
}
char c = 13; 原码 0 0 0 0 1 1 0 1 补码 0 0 0 0 1 1 0 1 ~ 补码 1 1 1 1 0 0 1 0 原码 1 0 0 0 1 1 1 0 c = -14 char c = -13; c = ~c; 原码 1 0 0 0 1 1 0 1 补码 1 1 1 1 0 0 1 1 ~ 补码 0 0 0 0 1 1 0 0 原码 0 0 0 0 1 1 0 0 c = 12
1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
unsigned char c = -2;

printf("c = %d\n", c);

return 0;
}
unsigned char c = -1; 原码 1 0 0 0 0 0 0 1 补码 1 1 1 1 1 1 1 1 printf("c = %d\n", c); c = 255 unsigned char c = -2; 原码 1 0 0 0 0 0 1 0 补码 1 1 1 1 1 1 1 0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
char a = 13, b = 7;
char c = 0;

printf("c = %d\n", c);

c = a ^ b;
/*
a 00001101
^
b 00000111
=
c 00001010
*/

printf("c = %d\n", c);

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
char c = -13;

printf("c = %d\n", c);

c <<= 4;
/*
c = -13
原 1 0 0 0 1 1 0 1
补 1 1 1 1 0 0 1 1
c << 4
补 0 0 1 1 0 0 0 0
原 0 0 1 1 0 0 0 0
c = 48
*/
printf("c = %d\n", c);

return 0;
}

位运算符的真正使用

注意:
1.在做位运算时,只改变要操作的位,其他位要保持不变
2.如果想要置1用按位或
3.如果想要清0用按位与
4.按位或上0,会保持不变
5.按位与上1,会保持不变
6.如果一次性想要操作多个位,一定要先清零再赋值

1.例如:GPIOA是一个32bit的寄存器,
    现在想要把该寄存器的第3位置1
GPIOA |= (1 << 3);
--------------------------------------------------
1			00000000 00000000 00000000 00000001
1<<3		00000000 00000000 00000000 00001000
|
GPIOA		XXXXXXXX XXXXXXXX XXXXXXXX XXXX#XXX
=
GPIOA		XXXXXXXX XXXXXXXX XXXXXXXX XXXX1XXX
--------------------------------------------------

2.例如:GPIOA是一个32bit的寄存器,
    现在想要把该寄存器的第4位清0
    GPIOA &= ~(1 << 4);
--------------------------------------------------
1			00000000 00000000 00000000 00000001
1<<4		00000000 00000000 00000000 00010000
~(1<<4)		11111111 11111111 11111111 11101111
&
GPIOA		XXXXXXXX XXXXXXXX XXXXXXXX XXX#1XXX
=
GPIOA		XXXXXXXX XXXXXXXX XXXXXXXX XXX01XXX
--------------------------------------------------

3.例如:GPIOA是一个32bit的寄存器,
    现在想要把该寄存器的第11 10 9 8位变为1010
    GPIOA &= ~(15 << 8);
    GPIOA |= (10 << 8);

=================================
2022-7-14
=================================

一.温故知新

    1.编辑器
        vim
            命令模式
                光标的定位
                    h j k l gg G 3G /string(n N)
                文本的编辑
                    yy p P dd u ctrl+r r x D
                模式的切换
                    iIoOaA
                    :
                    v
                    V
                    ctrl + v
            编辑模式
                文本的补齐
                    ctrl + p
            命令行模式
                w q wq q! wqa 
                3,6 s/srcname/destname/
                g %
            可视模式
                代码格式的调整
            可视行模式
            可视块模式
                块插入
                块删除
                块替换
            替换模式
    2.编译器
        gcc->cc
        a.out
        gcc hello.c -o hello
        gcc -Wall
    3.用户管理
        sudo useradd 用户名
        sudo passwd 用户名
        sudo userdel 用户名
            -r
    4.权限管理
        基本权限和特殊权限
符号	数字	含义		对于普通文件的影响			对于目录文件的影响
r	4	可读		是否可以读取文件内容		是否可以列出子文件
w	2	可写		是否可以修改文件内容		是否可以创建或删除子文件
x	1	可执行	是否可以执行文件内容		是否可以访问该目录

二.文件的特殊权限

    无论是suid sgid 还是 sticky,影响的都是可执行的权限
    所以加入特殊的权限将来会出现在 x 的位置
    suid	u+s		4
        sudo chmod u+s 文件名
        如果文件本身的user权限中有x权限,那么u+s之后,s是小写的
        如果文件本身的user权限中没有x权限,那么u+s之后,S是大写的
        一般来说只会在可执行命令中加入u+s的权限
        特性 : 拥有suid权限的命令,任何用户在使用这个命令时,
            都会拥有这个命令的所有者的权限来执行
        (简单来说就是在执行命令时,以命令所有者的权限来运行)
    sgid	g+s		2
        sudo chmod g+s 文件名
        如果文件本身的group权限中有x权限,那么g+s之后,s是小写的
        如果文件本身的group权限中没有x权限,那么g+s之后,S是大写的
        一般来说只会在目录文件中加入g+s的权限
        特性 : 拥有sgid权限的目录,任何用户在该目录下创建的文件
            都会继承该目录的属组
        (无论是普通用户还是超级用户,在g+s的目录下创建文件都会修改属组)
    sticky	o+t		1
        sudo chmod o+t 文件名
        如果文件本身的other权限中有x权限,那么o+t之后,t是小写的
        如果文件本身的other权限中没有x权限,那么o+t之后,T是大写的
        一般来说只会在目录文件中加入o+t的权限
        特性 : 拥有sticky权限的目录,当其他用户想要删除文件时,
            只能删除自己创建的文件
        (当超级用户进入到o+t权限的目录中,可以删除所有文件)
    没有特殊权限		0

三.削减权限umask

    当创建文件时,本身文件的权限过大,需要通过umask的值削减文件的权限
    在终端中录入 umask 可以查看当前umask值
    也可以修改umask数值 : umask 0022
    修改的umask的数值越大,创建的文件的权限越小
    在Linux系统中,默认创建的普通文件的权限是0666,
        0666 - 0002 = 0664(rw-rw-r--)
    在Linux系统中,默认创建的目录文件的权限是0777,
        0777 - 0002 = 0775(rwxrwxr-x)

四.进程的简介

    其实用户在操作系统中做的任何的操作都需要有进程的支持
    进程 : 其实是一个程序运行时的一个过程
    一个进程可以创建出多个子进程的
    主进程 : 父进程
    创建出的进程 : 子进程
    可以调用函数 : fork()
    僵尸进程 : 当父进程创建出子进程,子进程去工作,当子进程做完任务之后
            父进程没有给子进程收尸,子进程会变成僵尸进程
    孤儿进程 : 当父进程创建出子进程,子进程去工作,如果父进程提前结束了
            没有人管理子进程,子进程会变成孤儿进程

程序运行----->主进程----->父进程-->等待子进程结束-收尸->程序结束
                    |						|
                    fork()					|
                    |						|
                    子进程---->做工作----->结束(仆街)

    ps		//可以查看进程
    ps -aux	//查看所有进程信息
    当系统启动之后首先会创建一个进程PID为1叫做初始进程(init)
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
        USER		运行该进程的用户
        PID			进程ID号
        %CPU		CPU的占用百分比
        %MEM		内存的占用百分比
        VSZ			占用虚拟内存
        RSS			占用实际内存
        TTY			进程运行的终端
        STAT		进程的状态
            R		运行状态
            s		进程组,下面会有子进程
            S		睡眠状态(可以中断)
            D		睡眠状态(不可中断)
            Z		僵尸状态
            X		死掉的进程
            ...
        START		启动的时间
        TIME		占用CPU的时间
        COMMAND		进程名
    
============================================
./a.out

int max(int a, int b)
{
    return a > b ? a : b;
}

int add(int a, int b)
{
    return a + b;
}

int main(void)
{
    add(13, 7);
    max(13, 7);

    return 0;
}

    return 0;	函数正常运行
    > 0			函数有异常
    < 0			函数有错误

一个进程会有虚拟内存4Gb,实际上只占用了实际内存的4Kb
----------------------------
面试题
    1.C语言的程序会把内存分为几个区?
        5大区
        (栈区 堆区 常量区 全局区 代码区)
                    char *p = "Hello World!";
                    static
----------------------------

    1Gb		Kernel(内核)
    ----------------------
    3Gb		环境变量/命令行参数
            栈区(从上往下分配)
                空白空间
            堆区(从下往上分配)
            常量区(.RO<只读>)
            全局区(.bss .data)
            代码区(.text)
================================

=================================
2022-7-12
=================================

一.温故知新

    1.介绍
    2.课程安排
    3.Ubuntu的Linux操作系统
    4.介绍Linux由来
    5.介绍Linux系统的根目录
    6.终端的使用
    7.常用的命令
        cd ls(-a\-i\-l) pwd touch mkdir 
        cat(less more head tail)
        cp mv rm tar
drwxr-xr-x  14 root root  4096 9月  16  2021 var
lrwxrwxrwx   1 root root    30 7月  11 08:56 vmlinuz -> boot/vmlinuz-5.4.0-121-generic
    part.1		文件类型(7种文件类型)
            -	普通文件
            d	目录文件
            c	字符设备文件
            b	块设备文件
            p	管道文件
            s	网络套接字文件
            l	链接文件(符号链接文件)
    part.2		文件权限
            rwx			r--			-wx
            文件所属者	文件所属组	其他用户
            7			4			3
            r	4	可读
            w	2	可写
            x	1	可执行
            -	0	该处无权限

二.命令的补充

    在Linux环境中有两种链接文件(硬链接 和 符号链接)
    ln		(创建链接文件<既可以创建硬链接,也可以创建符号链接>)
    1.ln + 源文件名 + 目标文件名		//创建了硬链接文件
    -------------------------------------------------
    源文件和目标文件共用同一个文件inode号
    任意修改一个文件的文件内容,另外的一个文件也会发生改变
    移动或者删除源文件对于硬链接文件不会有影响
    会改变文件的硬链接数
    -------------------------------------------------
    2.ln + -s + 源文件名 + 目标文件名	//创建符号链接文件
    -------------------------------------------------
    符号链接文件类似于windows环境下的快捷方式
    源文件和符号链接文件使用文件inode号不同
    任意修改一个文件的文件内容,另外的一个文件也会发生改变
    移动或者删除源文件对于符号链接文件会有影响
    -------------------------------------------------
    3.总结
    硬链接
    创建方式 : ln 源文件 目标文件
    其实硬链接就是一个文件拥有多个文件名
    源文件和硬链接文件可以在相同目录中也可以在不同目录中
    注意:
        1)修改源文件或者硬链接文件,对于另外一个文件也会发生修改
        2)移动或者删除源文件或硬链接文件,对于另外一个文件没有影响
        3)硬链接文件不占用存储空间
        4)不能对于目录文件进行创建硬链接文件
            (即便是超级用户也不行,在Linux环境中目录是有硬链接的)
            (但是是系统默认创建出来的,用户是创建不了的)
            (. 就是当前目录的硬链接, .. 就是上一级目录的硬链接)
        5)硬链接文件不能跨系统分区或者文件系统
    符号链接
    创建方式 : ln -s 源文件 目标文件
    符号链接文件类似于windows环境下的快捷方式
    符号链接文件内部保存的是源文件的文件名或者路径
    注意 : 
        1)符号链接文件会占用存储空间,保存的是链接的文件的文件名或者路径
        2)符号链接文件是一个独立的文件,它的存在不依赖于源文件
        3)如果移动 重命名 删除源文件,对于符号链接文件会有影响
            虽然受影响,但是链接关系依然存在
    
    find		(查找文件)
    1.find -name 文件名		//通过文件名查找文件
    
    grep		(检索文件内容<针对文件内容进行过滤>)
    1.grep '过滤的内容' 过滤文件的文件名	//从该文件中过滤相关的内容
    2.grep '^root' 过滤文件的文件名	//从该文件中过滤相关的内容
                                    //^代表查找过滤的内容出现在行首
    3.grep 'bash$' 过滤文件的文件名	//从该文件中过滤相关的内容
                                    //$代表查找过滤的内容出现在行尾

三.帮助手册

    1.命令 --help				//可以查阅命令的帮助手册
    2.如果查找函数可以使用man手册	//有困难,找男人
        1)man 要查找的内容			//默认是从第一本man手册开始查找
        2)man man				//可以查阅如何使用man手册
            1   可执行程序或 shell 命令
            2   系统调用(内核提供的函数)
            3   库调用(程序库中的函数)
            4   特殊文件(通常位于 /dev)
            5   文件格式和规范,如 /etc/passwd
            6   游戏
            7   杂项(包括宏包和规范,如 man(7),groff(7))
            8   系统管理命令(通常只针对 root 用户)
            9   内核例程 [非标准
        3)man 数字 查找的内容		//可以指定打开某一本手册
            man 3 printf
            man 3 sleep
        4)man -f 查找的内容		//把man手册中所有有关查找的内容列出
        ------------------------
        在man手册中,按 q 可以退出man手册
        在man手册中,查找关键字可以用 /查找的关键字
        按 n 从上往下查找,按 N 从下往上查找
        ------------------------

四.Linux环境中软件的安装

    注意 : 
        1.在安装软件时,需要访问/etc /sys /usr /var...目录
        有些目录普通用户没有权限访问,所以在安装软件时需要加 sudo
        提升用户权限
        2.在使用sudo时,需要在终端中录入密码,在终端中录入密码是取消回现的
    1.从软件源安装软件(必须可以链接外网)
        前提准备:需要更换软件源
        显示应用程序->软件和更新->下载自->其他站点->腾讯/阿里/华为/清华
        在安装软件时可以先更新软件源 : 
        sudo apt-get update
        sudo apt-get upgrade
            可以加入 -y 的选项		默认选择yes
        sudo apt-get install 安装软件的名字 -y
        ------------------------
        可以做的实验,可以安装
        sl
        ifconfig
        fbset
        ------------------------
        sudo apt-get autoremove 要卸载的东西
            删除已安装的软件包,不会删除依赖的软件包,会保留配置文件
        注意:慎用(容易把图形化界面搞崩溃)
        sudo apt-get remove 要卸载的东西
            删除已安装的软件包,不会删除依赖的软件包,会保留配置文件
        sudo apt-get purge
            删除已安装的软件包,也会删除依赖的软件包
        sudo apt clean
            会把/var/cache/apt/archives目录中的所有.deb的包
            清除掉
    2.从官网下载官方的软件包进行安装
        (Ubuntu->从官网上下载.deb结尾的软件包)
        (Red Hat->从官网上下载.rpm结尾的软件包)
        sudo dpkg -i xxxxx.deb		//安装软件
        sudo dpkg -l 软件名			//确定软件包的名字
        sudo dpkg -r 软件名			//删除软件
        sudo dpkg -p 软件名			//清除信息
        ------------------------
        可以做的实验,可以安装
        VNC Viewer
        WPS
        百度网盘
        网易云音乐
        向日葵
        腾讯会议
        星际译王
        ------------------------
        QQ				不推荐
        搜狗输入法		不推荐
        ------------------------
    3.从官网下载源码包进行安装
        1)从官方网站下载源码包(一般来说就是tar包)
        2)把源码包进行解压缩(tar -xvf)
        3)./configure		//检查编译环境是否缺少需要的库
        4)make -j4			//编译源码(-j4调动所有硬件资源)
        5)sudo make install	//安装软件
        ------------------------
        可以做的实验,可以安装
        MPlayer
        ------------------------
--------------------------------
作业 : 
1.把今天讲过的内容完完整整的复习一遍
2.尝试使用其他的查找方法,查找文件
--------------------------------

=================================
2022-7-13
=================================

一.温故知新

    命令的补充
    ln						//用来创建链接文件
    ln 源文件 目标文件			//创建的是硬链接文件
    ln -s 源文件 目标文件		//创建的是符号链接文件

    find					//查找文件

    grep					//检索文件内容

    man手册的使用

    Ubuntu系统软件的安装
    1.sudo apt-get install
    2.从官网下载软件包,进行安装
        sudo dpkg -i
    3.从官网下载源码包,进行安装
        ./config
        make -j4
        make install

二.编辑器和编译器

    1.编辑器(编写程序)
        vi vim gedit emacs
        vim : 是vi编辑器的高级版本
        注意 :
                1.vim后边需要加文件名
                2.vim除了可以打开文件以外也可以创建文件
                3.保存退出,不要直接关闭终端,否则会生成交换文件
                vim 文件名
                    |
        按iIoOaA		V	按 :
编辑模式(插入)<-----命令模式----->命令行模式(底行)
            ----->		<-----
        按 esc			删除 :
        1)在命令模式下的操作
            1>光标的定位
                h(向左) j(向下) k(向上) l(向右)
                gg			光标回到首行
                G			光标回到末行
                23G			光标定位到第23行
                /要找的内容	光标直接定位到出现要找的内容的位置
                            (n向下查找 N向上查找)
            2>文本的编辑
                yy			复制(把光标所在行的内容进行复制)
                p			粘贴(把复制的内容粘贴到光标所在行的下面)
                P			粘贴(把复制的内容粘贴到光标所在行的上面)
                dd			剪切/删除(把光标所在行的内容进行剪切)
                3yy			复制3行内容
                3dd			剪切/删除3行内容
                3p			粘贴3次(粘贴到光标所在行的下面)
                3P			粘贴3次(粘贴到光标所在行的上面)
                ygg			从首行到光标所在行进行复制
                yG			从光标所在行到末行进行复制
                x			删除光标所在位置的内容
                D			从光标所在位置到行末进行删除
                u			撤销(undo)
                ctrl + r	重做(redo)
                r			替换(只能替换一个字符)
            3>模式的切换
                iIoOaA		进入编辑模式(插入模式)
                :			进入命令行模式(底行模式)
                v			进入可视模式
                --------------------------------
                调整代码格式
                    a.	进入到可视模式中
                    b.	把需要调整格式的代码通过上下键选中
                    c.	按 = 进行调整
                注意 : 让张老师调代码,先把代码格式调整好了
                --------------------------------
                V			进入可视行模式
                ctrl+v		进入可视块模式
                --------------------------------
                块插入
                    a.ctrl + v进入到可视块模式
                    b.通过上下键选择要插入的块
                    c.进入编辑模式(I在选择的块前插入A在选择的块后插入)
                    d.录入要插入的内容
                    e.按两下 esc
                块删除
                    a.ctrl + v进入到可视块模式
                    b.通过上下键选择要删除的块
                    c.按 d 进行删除
                块替换
                    a.ctrl + v进入到可视块模式
                    b.通过上下键选择要替换的块
                    c.按 r 进入替换的操作
                    d.录入要替换的字符
                --------------------------------
                R			进入替换模式
        2)在编辑模式下的操作
            1>文本补齐的功能
                ctrl + p
        3)在命令行模式下的操作
            1>保存退出
                :w			保存
                :q			退出
                :wq			保存并且退出
                :q!			强制退出
                :wqa		保存所有文件,退出所有文件
            2>查找和替换
                :3,7 s/root/zack/	
                        把3-7行第一次出现的root替换成zack
                :3,7 s/root/zack/g
                        把3-7行出现的所有的root替换成zack
                        g	代表的是全局的意思
                :% s/root/zack/g
                        把全文出现的所有的root替换成zack
                        %	代表的是全文的意思
        4)修改vim的配置文件
            vim /etc/vim/vimrc		会影响所有用户
            vim ~/.vimrc			会影响当前用户
            可以从网上找各种vim的配置方法
        5)使用vim打开多个文件
            注意 : 不要用vim一次性打开多个文件,否则vim会崩溃
            vim -O 多个文件		//以纵向的标签栏打开多个文件
            vim -o 多个文件		//以横向的标签栏打开多个文件
                可以使用ctrl + w(两下)切换文件
            vim -p 多个文件		//以标签页的形式打开多个文件	
                可以使用ctrl + alt + pgup/pgdn切换文件
    2.编译器
        在X86环境中有gcc编译器和cc编译器
        gcc编译器依赖于cc编译器
        在ARM环境中需要使用交叉编译工具链 : arm-linux-gcc
        X86环境和ARM环境会有大端格式和小端格式的区分
        --------------------------------------------
        设计一套程序,测试当前环境是大端格式和小端格式
        --------------------------------------------
        
        gcc .c文件
        1.编译之后什么都没有提示,代表程序没有语法错误,会生成可执行文件
        2.编译之后报出警告,代表程序有点问题,但是不是致命的错误,
                也会生成可执行文件
        3.编译之后报出错误,代表程序有致命的问题,不会生成可执行文件
        默认生成的可执行文件的名字是a.out
        以 ./a.out 的方式执行可执行文件
        gcc hello.c -o hello	//可以指定生成的可执行文件的文件名
        gcc -Wall hello.c		//可以列出所有警告

三.用户管理

    1.用户的分类
        功能上区分 : 超级用户 和 普通用户
        超级用户是在安装Linux操作系统时自动创建的用户
        普通用户是由超级用户或者普通用户创建出来的
        范围上区分 : 本地用户 和 网络用户
        创建在本地计算机上的用户是本地用户
        创建在远端服务器上的用户是网络用户
    2.用户创建的描述
        注意 : 虽然都是Linux操作系统,但是不同公司有不同区别
        当创建用户时,伴随着会创建一系列的东西
        1)系统会为新创建的用户分配一个唯一的编号,叫做UID
        2)系统会为新创建的用户,创建一个同名的组,
            并且分配一个唯一的编号,叫做GID
        3)系统会把新创建的用户加入到同名的组中,这个组也叫做这个用户的主组
        4)系统会在/home/目录中创建一个同名的目录,作为新用户的家目录使用
        5)系统会把/etc/skel目录中的文件拷贝到新用户的家目录中,
            作为基础的配置文件进行使用
        6)系统会把新用户的信息记录到/etc/passwd文件中
            查看/etc/passwd文件
            注意:
            1>/etc/passwd文件中每一行就是一个用户的信息
            2>/etc/passwd文件中每个信息通过 : 分割
            root:x:0:0:root:/root:/bin/bash
                1>root		代表的是用户名
                2>x			代表的是密码(密码移到了/etc/shadow文件)
                3>0			代表的是UID
                ----------------------
                UID : 0			是超级用户
                UID : 1 - 499	是系统用户
                UID : >= 500	是普通用户
                ----------------------
                4>0			代表的是GID
                5>root		代表对于该用户的描述
                6>/root		代表该用户的家目录
                7>/bin/bash	代表该用户登陆Linux终端时使用的命令解释器
        7)系统会把用户的密码记录到/etc/shadow文件中			
            查看/etc/shadow文件
zack:$6$1bVyc6zY$GrJ/9j8jngCDD54QkuDEgZqQJnlWV.MG2ngEFvHkQ    dLlkC7AINt6jsm74f8FZvFRuWK5zcz1kf29/LnzakCkd/:19182:0:9999    9:7:::
                1>zack		代表的是用户名
                2>$6$		代表的是加密之后的密码
                3>19182		上次更改密码的日期(从1970-1-1开始算)
                4>0			最短的密码期限(按天算,0代表无最短期限)
                5>99999		最长的密码期限(按天算)
                6>7			密码的警告期限
        8)系统会把新用户的组的信息记录到/etc/group文件中
    3.用户的创建
        sudo useradd 用户名			//创建用户(用户名不能重复)
        sudo passwd 用户名			//修改用户的密码
        sudo su 用户名				//切换用户
        ctrl + d					//结束当前终端用户的登陆
        sudo userdel 用户名			//删除用户(只删除用户)
        sudo userdel -r 用户名//除了删除用户,伴随着会删除创建的东西

四.文件权限的管理

    1.文件权限的介绍
        在Linux操作系统中用户访问的任何文件都是有权限的
        权限可以分为基本权限和特殊权限
        1)基本权限
            rwx				rw-				r--
            文件所属者的权限	文件所属组的权限	其他用户的权限
符号	数字	含义		对于普通文件的影响		对于目录文件的影响
r	4	可读		是否可以读取文件内容	是否可以列出目录的子文件
w	2	可写		是否可以修改文件内容	是否可以创建或删除子文件
x	1	可执行	是否可以执行文件内容	是否可以访问目录内容
        2)修改文件的权限
        sudo chmod 权限 文件名		//修改文件的权限
    //由于权限的表示方法有符号表示和数字表示,所以本身修改权限的方法有很多
    //如果修改目录的权限想要影响子文件或者子目录,需要加-R
        sudo chmod -R 权限 文件名
            1>使用符号表示法
            rwx				rw-				r--
            文件所属者的权限	文件所属组的权限	其他用户的权限
            u				g				o
            u	表示文件所属者的权限
            g	表示文件所属组的权限
            o	表示其他用户的权限
            a	表示所有用户的权限
                       u+r 
            sudo chmod g-w 文件名
                       o=x
            2>使用数字表示法
            数字表示法也叫做八进制表示法
            sudo chmod 456 test
            //test的文件所属者是r--
            //test的文件所属组是r-x
            //test的其他用户是rw-
        3)修改文件的属主和属组
            sudo chown 名字 文件		//用来修改文件的属主
            sudo chown .名字 文件		//用来修改文件的属组
            sudo chown 名字.名字 文件	
                //既修改文件的属主也修改文件的属组
==============================================
实验
1.创建用户			sudo useradd tom
2.修改用户密码			sudo passwd tom
3.创建家目录			sudo mkdir /home/tom
                    (tom目录创建之后本来属于root用户)
4.拷贝模板配置文件		sudo cp /etc/skel/.* /home/tom
5.修改家目录的属主属组	sudo chown -R tom.tom /home/tom
6.修改命令解释器		sudo vim /etc/passwd
                    把tom用户的命令解释器修改成/bin/bash
                    保存退出
7.切换用户->做实验
==============================================

===================================
2022-7-8
===================================

循环语句(while)

while(是C语言的关键字)
1.while循环的使用
语句1
while(循环条件)
{
    循环的语句
}
语句2
                -------<----------<------
                |						^
                V						|
语句1->循环条件的判断(真)->循环的语句-->|
                |
                (假)->语句2->结束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>

int main(void)
{
int i = 1;
int sum = 0;

while(i <= 100)
{
sum += i++;
}

printf("sum = %d\n", sum);

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>

int main(void)
{
int i = 1;
int sum = 0;

while(i <= 100)
{
sum += i++;
}

printf("sum = %d\n", sum);

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <unistd.h>

int main(void)
{
int i = 10, j = 10;

while(i-- || j--)
{
printf("i = %d j = %d\n", i, j);
sleep(1);
}

printf("=== i = %d j = %d\n", i, j);

return 0;
}

循环语句(do…while)

do...while循环(也是C语言的关键字)
语句1
do
{
    循环的语句
}while(循环的条件);
语句2
            --------<-----------<--------
            |							^
            V							|
语句1->循环的语句->循环条件的判断(真)--->
                        |
                        (假)->语句2->结束
while循环是先执行循环条件的判断,再执行循环的语句
do...while循环是先执行循环的语句,再执行循环条件的判断

while循环可以一次也不执行循环的语句
do...while循环至少会执行一次循环的语句

do...while : 在写底层内核驱动时,使用do...while循环做超时处理

*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>

int main(void)
{
int i = 1;
int sum = 0;

do
{
sum += i++;
}while(i <= 100);

printf("sum = %d\n", sum);

return 0;
}

随机函数

rand()		:	产生随机数(非负的正整数)的函数
    rand() % 1000; [0 ~ 999]以内的随机数
    随机产生5位数
    rand() % 90000;			[0 ~ 89999]
    rand() % 90000 + 10000;	[10000 ~ 99999]
    随机产生-50 ~ 50的随机数
    rand() % 100;			[0 ~ 99]
    rand() % 100 - 50;		[-50 ~ 49]
srand();	:	随机种子(可以保证每一次执行程序时,随机数可变)
    srand在调用时需要传参,参数是可变的因子
time();		:	时间种子(获取当前时间的秒数)
    time(NULL);
getpid();	:	进程种子(获取当前进程的ID号)

注意 : srand()函数在程序中值调用一次即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
int num = 0;

printf("num = %d\n", num);

num = rand();

printf("num = %d\n", num);

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{
int i = 0;
int num = 0;

//srand(time(NULL));
srand(getpid());

for(i = 0; i < 5; i++)
{
num = rand() % 100 - 50;
printf("num = %d\n", num);
}

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*
猜数游戏
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{
int T = 0;//用于保存随机数
int guess = 0;//用于保存录入的数
int i = 0;//循环变量

srand(getpid());//随机种子
T = rand() % 1001;//保存随机数

for(i = 1; ; i++)
{
scanf("%d", &guess);
if(T > guess)
printf("[%d] Small!\n", i);
else if(T < guess)
printf("[%d] Big!\n", i);
else
{
printf("[%d] Bingo!\n", i);
break;
}
}


return 0;
}

=================================
2022-7-11
=================================

一.介绍

    上课时间(课前阅读单词 | 随机抽取学生复述昨天讲过的内容)
    09:00 - 12:00
    13:30 - 17:30
    18:30 - 20:30

    周一 到 周五
    节假日以及周六周日休息(周六有自习室)

    课程安排
    预科		通过预科时间把大家的基础拉平
    --------------------------------
    Linux基础	(环境安装\命令\软件安装\权限管理\用户管理\服务搭建)
    Linux下C语言	(变量\运算符\分支语句\循环\跳转\数组\函数\指针\)
                (复合型数据类型\预处理\文件IO)
    数据结构		(链表\栈式存储结构\队列式存储结构\树存储结构\哈希表)
    ---------考试以及项目-------------	
    APUE		(标准IO\系统调用IO\信号\进程\线程\进程间通信)
                (网络套接字TCP/UDP)
    C++/QT		()
    ---------考试以及项目-------------
    智能终端		单片机开发(裸板驱动)
    ---------------项目--------------
    边缘计算		高端芯片的开发(带操作系统的驱动)
    ---------------项目--------------
    就业环节		压力面试\压力笔试

二.Linux环境的安装

    环境的安装
    1.双系统
        准备
        1)把笔记本的硬盘分出空白的空间(100G)
        2)系统盘
            (光盘安装\U盘安装\网络安装)
    2.虚拟机
        准备
        1)虚拟机软件(vmware\vboxs)
        2)镜像(开源的镜像网站)
    3.注意:无论是双系统的安装还是虚拟操作系统的安装,分区需要选择手动分区
        例如:分了100G的空间
        8192Mb			交换空间
        剩余的一半空间		/home
        剩余的所有空间		/

三.Linux的历史

    在市面上的电子产品的万年历的功能
    1.RTC的功能可以查找基准时间
        1)1900年1月1日	这一天是星期一
        2)1970年1月1日	计算机元年
        3)2000年1月1日	千禧年(千年虫)
    2.计算机元年
        在美国一家通讯公司,AT&T公司(马刺队)
        AT&T公司里面有个实验室叫做贝尔实验室
        丹尼斯.里奇(C语言之父)用闲置的电脑写了一个游戏--太空旅行
        丹尼斯.里奇和肯.汤姆逊使用BSPL语言(B语言)在机器上写通用程序
        觉得B语言不好用,所以创立了C语言
        
        丹尼斯.里奇和肯.汤姆逊写了系统,叫做UNIX
        
        美国加州学院伯克利分院一个教授通过UNIX写了一个minix,用于教学
        这个教授的学生林纳斯,写了Linux

    3.可以在电脑上查询信息
        uname -a	查询内核版本以及操作系统版本

四.Linux系统的认知

    windows			Linux
            500G
    C D E F			/(根目录)
    4棵树			1棵树
    /(根目录)
        bin			存放的是二进制的文件(命令)
        boot		存放的是用来引导内核的文件
        dev			存放的是各种设备文件
        etc			存放的是配置文件
        home		存放的是普通用户的家目录
        lib			存放的是各种库文件(动态库和静态库)
        media		用来挂载存储介质或者媒体介质的文件
        mnt			系统默认可以使用的挂载的目录
        proc		动态的目录(不能用于存储文件)
                    (系统内核的信息\进程的信息\内存映射的信息)
        root		超级用户的家目录
        sbin		存放系统的二进制文件
        sys			存放系统的文件
        usr			存放的是应用程序\头文件

五.终端的使用

    1.终端的打开
        1)通过鼠标右键->打开终端
        2)在Ubuntu左下角有显示应用程序->全部->终端
        3)快捷键ctrl + alt + t
        4)打开终端之后打开终端的标签页
            ctrl + shift+ t		//打开标签页
            ctrl + pgup/pgdn	//切换标签页
            注意 : 有同学电脑的键盘上的pgup和pgdn和别的按键在一起
            有可能在切换标签页的时候需要使用shift或者fn
    2.终端提示符
    zack@zack-CSTG:~/桌面/2022-6-29_UEA/02linux$ 
        在@之前		当前登陆这个终端的用户名
        @			分割符号
        在@之后,:之前	主机名
        :			分割符号
        在:之后		当前终端所在目录的路径
            路径分为绝对路径和相对路径
            绝对路径 : 从根目录出发.一层一层递进的目录就是绝对路径
            相对路径 : 除了绝对路径都是相对路径
            在路径中 ~ 指的是家目录的意思
            每个用户都会有家目录
            root用户		/root
            zack用户		/home/zack
            tom用户		/home/tom
        #或者$		用户的身份识别
            #		代表的是超级用户
            $		代表的是普通用户
    3.修改终端提示符的长度
        1)需要修改配置文件
            注意:
                如果修改/etc/下边的配置文件,会影响所有用户
                如果修改家目录下边的配置文件,会影响当前用户
        2)把原有的配置文件拷贝一个备份
            cp ~/.bashrc ~/bashrctest
        3)修改配置文件
            vim ~/.bashrc
            -------------------------
            1>找到要修改的位置,大约在60行左右
            2>PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
            3>把 \h\[\033[00m\]: 删掉		代表不再显示主机名
            4>把 \w 修改成 \W				代表目录路径只显示最后一级
            5>保存退出
            6>sync						代表同步一下信息

六.命令

    在Linux下一切皆文件,任何东西在Linux环境中都是以文件形式存在的

    在终端提示符之后可以录入命令 或者 可执行文件 或者 程序
    终端提示符	命令
    终端提示符	命令 + 选项
    终端提示符	命令 + 参数
    终端提示符	命令 + 选项 + 参数
    注意 : 命令 选项 参数之间需要用空格隔开
    命令 --help	可以查看命令的帮助手册

    cd		(切换目录/改变目录/进入目录)
        1.cd + 目录		//可以切换到该目录中
            如果目录不存在,会提示报错
        2.cd + 路径		//可以切换到该路径中
            可以是绝对路径或者相对路径,但是必须是一个正确的路径
        3.cd 直接回车		//可以直接回到家目录
        4.cd + ..		//可以切换到上一级目录
    ls		(显示当前目录下的文件名)
        1.ls 直接回车		//显示当前目录下的文件名
        2.ls + 文件名		//显示当前目录下该文件的文件名
        3.ls + 目录名		//显示该目录下的文件名
        4.ls + -a		//显示所有文件包括隐藏文件
                        //在Linux环境下以.开头的文件都是隐藏文件
                        //任何目录都有来两个默认的隐藏文件
                        //. 代表当前目录	.. 代表上一级目录
        5.ls + -i		//显示文件inode号
                        //文件是存储在硬盘中的,在Linux文件系统中
                        //是通过inode号来管理文件的
                        //在硬盘的同一分区中,文件inode号不会重复
        6.ls + -l		//使用较长格式显示文件信息
-rw-r--r-- 1 zack zack 8980 7月   9 15:51 examples.desktop
drwxr-xr-x 2 zack zack 4096 7月   9 16:26 公共的
        part.1			文件的类型(在Linux环境中一共有7种文件类型)
            -		普通文件
            d		目录文件
            c		字符设备文件
            b		块设备文件
            p		管道文件
            s		网络套接字文件
            l		链接文件(符号链接文件)
        part.2			文件的权限(分为基本权限和特殊权限)
            rw-			r--			r--
            文件所属者	文件所属组	其他用户
            字符表示		数字表示		含义
            r			4			可读
            w			2			可写
            x			1			可执行
            -			0			该处无权限
        part.3			文件链接数
        part.4			文件所属者
        part.5			文件所属组
        part.6			文件的字节数
        part.7			文件最后修改时间
        part.8			文件名
    pwd		(可以显示当前目录所在的绝对路径)
    touch	(创建普通文件)
        1.touch + 文件名			//创建以文件名命名的普通文件
        如果文件名已经存在,不会修改文件内容,只会修改文件最后修改时间
        如果加已存在的目录名,不会修改文件内容,只会修改文件最后修改时间
        2.touch + 文件名 + 文件名	//可以创建多个文件
        注意 : 文件名与文件名之间用空格隔开
        3.touch + {1..20}.c		//可以创建1.c ... 20.c
            touch + {a..z}.c	//可以创建a.c ... z.c
            touch + {A..Z}.c	//可以创建A.c ... Z.c
        4.touch + 路径/文件		//在该路径下创建新的文件
        注意 : 路径可以是相对路径或者绝对路径,但是必须是正确的路径
    mkdir	(创建目录文件)
        1.mkdir + 目录名				//创建以目录名命名的目录
            注意 : 不能加已有的目录名,会报错
        2.mkdir + 目录名 + 目录名		//创建多个目录
            注意 : 目录名与目录名之间用空格隔开
        3.mkdir + {a..z}dir			//创建adir ... zdir
        4.mkdir + 路径/目录名			//可以在该路径下创建目录文件
            注意 : 可以是绝对路径或者相对路径,但是必须是正确的路径
    rm		(删除文件)
        1.rm + 文件名				//删除文件(普通文件)
        2.rm + -r + 目录名		//删除目录文件
            -r	代表递归的操作
        3.rm *.c				//删除当前目录下所有以.c结尾的文件
            rm file*			//删除当前目录下以file开头的文件
            rm -r dir*			//删除当前目录下以dir开头的文件
        4.rm + 路径/目录名		//删除该目录下的该文件
            注意 : 路径可以是绝对路径或者相对路径,但是必须是正确的路径
        注意 : 在根目录中千万不要执行 sudo rm -rf *
    cat		(查看普通文件的文件内容)
        1.cat + 普通文件的文件名
        2.cat + 路经/普通文件的文件名
            注意 : 路径可以是绝对路径或者相对路径,但是必须是正确的路径
    ----------------------------
    cat		把所有的文件内容打印输出到终端中
    less	从文件的起始位置开始显示,可以通过鼠标滚轮或者键盘上下键翻阅
                按q退出
    more	从文件的起始位置开始显示(显示百分比)
                s向下翻阅		b向上翻阅		q退出
    head	默认查看文件的前10行
    tail	默认查看文件的末尾10行
    ----------------------------
    cp		(拷贝文件)
    1.cp + 源文件名 + 目标文件名	//把源文件的文件内容拷贝到目标文件中
    如果目标文件名已存在,源文件的文件内容会覆盖目标文件的文件内容
    如果目标文件名不存在,会新建以目标文件名命名的文件,
        然后把源文件的文件内容会覆盖目标文件的文件内容
    2.cp + 源文件名 + 目录名		//会把源文件拷贝到目录中
    3.cp + -r + 源目录 + 目标目录	//会把源目录拷贝到目标目录中
    如果目标目录已存在,会把源目录拷贝到目标目录内
    如果目标目录不存在,会新建目标目录,并且把源目录内的文件拷贝到目标目录中
    
    mv		(剪切文件\移动文件\改名字)
    1.mv + 源文件名 + 目标文件名	//剪切文件内容
    如果目标文件名不存在,就是把源文件改名字
    如果目标文件名已存在,也是把源文件改名字,不过会替代掉重名的文件
    注意 : mv在操作目录文件时不需要加 -r 的操作

    tar		(压缩与解压缩)
    1.tar cvf 最终生成的压缩包的名字.tar 要压缩的文件		//用来压缩的
    2.tar xvf 压缩包的名字.tar		//会把压缩包默认解压缩到当前目录下
    3.tar xvf 压缩包的名字.tar -C 路径
                                //会把压缩包解压缩到指定目录中
--------------------------------
作业 : 
1.把今天讲过的内容完完整整的复习一遍
2.抽时间自己安装一遍虚拟操作系统
3.查找ls加什么选项可以查看目录名
--------------------------------

===================================
2022-7-7
===================================

一.温故知新

    分支语句
    switch case default
    switch(变量)
    {
        case 整常量1 : 语句1; break;
        case 整常量2 : 语句2; break;
        case 整常量3 : 语句3; break;
        default : 语句4; break;
    }

    跳转语句
    break
        如果使用在switch语句中会跳出switch
        
    循环语句
    for(循环变量的赋值; 循环变量的控制; 循环变量的变化)
    {
        循环的语句
    }

    for循环的变形
    1.
    for(; ;)这是一个死循环
    或者
    for(表达式1; ;表达式2)也是一个死循环
    等价于
    for(表达式1; 1;表达式2)
    2.嵌套循环
    int i = 0, j = 0;

    for(i = 0; i < 3; i++)
    {
        for(j = 0; j < 4; j++)
        {
            
        }
    }
    3.int i = 0, j = 0;
    for(i = 0, j = 10; i < 5 && j > 5; i++, j--)

================================================

homework

1.
(1)打印4 * 5 的 *
例:
*****
*****
*****
*****
(2).打印i * j 的 * (i j 键盘接收)
    例:i = 4, j = 5
    //4-5 5-6
    *****
    *****
    *****
    *****
(3).打印i * j 的 * 边框(i j 键盘接收)
    例: i = 4, j = 5
    *****
    *   *
    *   *
    *****
2.打印99乘法表
    1 * 1 = 1
    1 * 2 = 2 2 * 2 = 4
    *
    **
    ***
    ****


3.计算1+2+3+4+5+...+n, n是从键盘输入的自然数

// 穷举
4.要将5张100元的大钞票,换成等值的50 20 10 5小钞票,每种面值至少一张,要多少张,有多少种换法

5.有1、2、3、4 4个数字,能组成多少个互不相同且无重复的三位数呢

6.有这样的一个等式,xyz+yzz=532,编程求x y z的值

7.计算1^2 + 2^2 + 3^2 + ... +10^2的结果
(1的平方 + 2的平方)

8.输入20个人的成绩,输出不及格的人数(0<=score<60 为不及格)

9.随机产生100个三位随机数,找出其中能被 3 5 7整除的数

10.打印0~100以内所有的质数
(只能被1 和 本身整除的数)

11.猜数游戏(随机产生一个1000以内的数,去猜,
        如果大了打印猜的大了,
        如果小了打印猜的小了,
        如果正确打印对的
        直到猜对了再结束,每次打印必须打印出猜的次数)

12. 把11修改成,程序开始时,先输入需要猜的数的范围n
例:(想要猜数的范围是(0~10000) 那么变量n接收键盘上10000
        范围都是从0开始)

13.
----------------------------
a + b - 9 = 4
+	-	-	
c -	d * e = 4
/	*	-
f + g - h = 4
=	=	=
4	4	4
求a b c d e f g h (0 ~ 12范围内)//除法指的是整除 c % f == 0
只有一种答案

14.求1+12+123+...前N项之和,其中N是从键盘输入的数(N取值范围(1~9))
    n = 5;
    sum = 1 + 12 + 123 + 1234 + 12345;

15.爱因斯坦出了一道这样的数学题,有一条长阶梯,若每步跨2阶,则最后剩1阶,若每步跨3阶,则最后省2阶,若每步跨5阶,则最后剩4阶,若每步跨6阶,则最后剩5阶只有每次跨7阶,最后才正好1阶不剩,请问在这条阶梯最少多少阶

16.设N是一个4位数,它的9倍恰好是它的反序数
    例:1234 反序数是4321

17.求s = a + aa + aaa + aaaa + ... + aa...a的值,其中a是1~9的一个数字(不超过十项)
例:a = 3; s = 3 + 33 + 333;

18.“百钱百鸡”问题,百钱买百鸡,公鸡1个3块钱,母鸡1个2块钱,小鸡3个一块钱,问公鸡,母鸡,小鸡各多少个

19.打印三角形	(画8个三角形)
* * * * *
  * * * *
    * * *
      * *
        *
6_1.打印三角形
    录入n,n是直角三角形的高
    例:	n = 3
      * 
    * * * 
  * * * * *
    n = 4
      * 
    * * * 
  * * * * * 
* * * * * * * 


20.猴子吃桃问题,有一天一只猴子摘了一些桃子,它吃掉一半,又吃了一个,第二天也是这样,到了第十天,只有一个桃子了,求猴子摘了多少桃子

21. 4 5 6 7总共能组成多少个不能被4整除的4位数

22.求n!(n的阶乘)

                        电子版的口算卡
随机生成10道100以内的 [加 减 乘 除 取余] 数学题 回答正确的加10分错误不加分(把正确结果打印出来) 然后显示最后成绩。(不用float类型)	
1>	操作数随机  2>	运算符随机
gcc 1.c		当执行./a.out之后,先清屏
23 + 70 = 93
Bingo!	+10分
79 * 97 = 0
Error!	==== 7663
...
总分 70分

做完的同学,如果觉得没有必要修改了,修改成以自己名字命名的.c文件,可以交给组长
组长收齐后,打包,发到组长的微信群里
17:30之前交齐

作业:

1.把这一周讲过的内容复习一遍
2.循环之后的22道练习题
3.有时间可以做做pdf里面的编程题
4.虚拟机做快照

/*
* * * * *
* * * *
* * *
* *
*
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>

int main(void)
{
int i = 0, j = 0;
int n = 0;

scanf("%d", &n);//通过scanf函数录入边长

for(i = 0; i < n; i++)
{
for(j = 0; j < n - i; j++)
{
printf("* ");
}
printf("\n");
}

return 0;
}
/* * * * * * # * * * * # # * * * # # # * * # # # # * */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>

int main(void)
{
int i = 0, j = 0;
int n = 0;

scanf("%d", &n);//通过scanf函数录入边长

for(i = 0; i < n; i++)
{
for(j = 0; j < n; j++)
{
if(j < i)
printf(" ");
else
printf("* ");
}
printf("\n");
}

return 0;
}
/* * * * * * * * * * * * * * * * */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>

int main(void)
{
int i = 0, j = 0;
int n = 0;

scanf("%d", &n);//通过scanf函数录入边长

for(i = 0; i < n; i++)
{
for(j = 0; j <= i; j++)
{
printf("* ");
}
printf("\n");
}

return 0;
}
/* # # # # * # # # * * # # * * * # * * * * * * * * * */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>

int main(void)
{
int i = 0, j = 0;
int n = 0;

scanf("%d", &n);//通过scanf函数录入边长

for(i = 0; i < n; i++)
{
for(j = 0; j < n; j++)
{
if(j < n - i - 1)
printf(" ");
else
printf("* ");
}
printf("\n");
}

return 0;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>

int main(void)
{
int i = 0, j = 0;
int n = 0;

scanf("%d", &n);//通过scanf函数录入边长

for(i = 0; i < n; i++)
{
for(j = 0; j < n + i; j++)
{
if(j < n - i - 1)
printf(" ");
else
printf("* ");
}
printf("\n");
}

return 0;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>

int main(void)
{
int i = 0, j = 0;
int n = 0;

scanf("%d", &n);//通过scanf函数录入边长

for(i = 0; i < n; i++)
{
for(j = 0; j < 2 * n - i - 1; j++)
{
if(j < i)
printf(" ");
else
printf("* ");
}
printf("\n");
}

return 0;
}