Sorry,博主最近在学习,没有时间维护该网站,开放时间10月左右。

Linu常用命令

当前路径---./相对于当前目录下路径 
绝对路径---/从根目录开始的路径

Linux下磁盘分区和目录的关系

变量

变量命名规则

命名方法:

交换两个变量

#include <stdio.h>
int main()
{
    int a = 10;
    int b = 20;
    int t;
    t = a;
    a = b;
    b = t;
    return 0;
}

内存模型

补码

char类型原码:

ASCII编码

转义字符

常量

格式输入输出

类型转换

运算符和表达式

前++ 后++区别

 #include <stdio.h>
 int main()
{
//单独使用++a和b++无区别
int a = 5;
a++;
printf("a++ = %d\n",a);
int b = 5;
++b;
printf("++b = %d\n",b);
printf("---------华丽分割线--------\n");
//参与赋值或者其他运算时,a++和++b则有区别
//赋值情况++a先自身加1在赋值
//b++先赋值在+1
int c=0;
int d=0;
c=a++;
d=++b;
printf("c = %d\n",c);
printf("d = %d\n",d);
return 0;
}

程序结构设计

if选择

- 如果需要控制多条语句就加上{}

switch

switch(5)
{
    case 1:
        printf("星期一");
        break;
    case 2:
        printf("星期二");
        break;
    case 3:
        printf("星期三");
        break;
    case 4:
        printf("星期四");
        break;
    case 5:
        printf("星期四");
        break;
    case 6:
        printf("星期四");
        break;
    case 7:
        printf("星期四");
        break;
    default:    //default:上面都不匹配的情况下执行;
        printf("输入错误");
        break;
}

switch案例优化代码

 #include <stdio.h>
 int main()
{
    int number;
    printf("请输入你的号码:");
    scanf("%d",&number);
switch(number)
{
    case 4:
    case 5:
    case 6:
        printf("微波炉\n");
        break;
    case 3:
        printf("华为手机\n");
        break;
    case 2:
        printf("三星显示器\n");
        break;
    case 1:
        printf("外星人笔记本\n");
        break;
    default:
        printf("很遗憾,未中奖!\n");
        break;
    }
    return 0;
}

for循环三要素

while循环

int i=0;
while(i<100)
{
    i++;
}

do while

int i=0;
do
{
    执行语句;
    i++;
}while();

for循环

for(循环变量初始化;循环终止条件;趋势循环终结条件) {

}

案例九九乘法表:

#include <stdio.h>

int main()
{
for(int i=1;i<=9;i++)
{
for(int j=1;j<=i;j++)
{
   printf("%d * %d = %d ",i,j,i*j);
}
    putchar(10);
}
    return 0;
}

四大跳转

数组

- 二维数组的本质就是一维数组,一维数组的成员又是一个一维数组

指针

函数

变量作用域

全局命名污染

生命周期

修饰符

字符串

字符形态

Strcat 链接 - 被连接的串必须要有足够的空间 - 返回char*是为了链式表达式

Strcpy - 被拷贝的区域,必须有足够的空间容纳 - 先拷贝,在判断在++

Strcmp 比较 - 以此比较ASCII 的值

1.把一类功能函数写到xxx.c里面 2.把xxx.c中所有的函数声明写到xxx.h 3.在xxx.h加入,避免头文件重复包含的语句

ifnedef MYSTRINGH

define MYSTRINGH

4.将xxx.h包含到xxx.c中去,自包含实现用"" 5.在main函数中,包含xxx.h 谁用谁包含

注解 1.实现 2.声明 3.把1 作成库libmystr.so给别人提供mystr.h就可以了

指针数组

访问方式 大刀长矛 array &array[0] 小米加步枪 p[i]
*(p+i) 冲锋枪 *p++

内存管理

源代码/程序/进程
    源程序由开发者编写的
    程序是指源程序编译后,可执行的程序
    进程是指程序打开到结束这一段时间的过程
进程空间
    系统空间
    栈空间Stack
        栈存放内容
            存放任意类型的变量,auto修饰的变量
        栈特点
            即用即开,用完即消,不需要人工干预
        栈大小
            栈很小,所以不是用来存储,而是用来数据交换
        栈溢出
            由于变量过多或者递归调用过多,会导致栈溢出
    堆空间Heap
        堆特点
            可以存放任意类型,但是需要自己手动申请空间和释放
        堆大小
            相对于栈而言,无穷大
        堆内存
            malloc
                用于申请空间,但是申请的空间没有初始化
            calloc
                用于申请空间,但是申请的空间会初始化
            realloc
                用于对空间扩容或者缩小
                    如果当前空间后面还有空间则直接扩容
                    如果没有则开辟一个空间,把内容拷过来,销毁之前空间,然后指向这个空间
                如果不是对当前空间扩容,第一次使用则是开辟空间并且初始化
            free
                释放空间
                    谁申请空间,谁释放
                    不能多次释放同一个空间,否则会产生double free错误
            动态数组案例
                之前VLA变长数组,在运行时只有一次初始化长度的机会
                容易发生栈溢出
                现在用堆空间的动态申请与释放,动态数组就有意义了
            常见错误
                置空与判空
                    如果内存被释放后,未置空作为判空使用
                    或者释放后非法使用
                重复申请
                    未释放原有空间时,在后面又重新申请了,导致前面的空间泄露了
                谁申请谁释放
                    如果没有协同原则,则可能导致空间被重复释放
            其他常见错误
                free非molloc函数申请赋值的指针
                    free不能乱释放指针,必须是molloc申请赋值的指针,不然在linux中会报错
                free(p+i)
                    释放一个未知空间,会导致程序挂掉。
            开放地址
                地址是永远存在的,与内容无关。
            栈与堆的返回
                栈上的构造类型不能返回
                堆可以返回,因为要自己手动释放
    Data空间
        未初始化
        初始化
    Text

结构体

    结构体存在的意义
        一组元素可以使用一维数组
        多个元素也可以使用二维数组但是要求类型一致
        使用结构体可以自定义类型,可以使用多种类型
    单变量/数组/结构体
        单变量:        描述一个人的年龄
        数组:     描述多个人的年龄
        结构体:        不但可以描述N个人的年龄,还能描述他的体貌特征
    构造类型定义
        定义结构体
            结构名
            结构成员
        无名结构体
            优势:     不带来多余的类型名
            弊端:     若不在定义类型时定义变量,则会带来代码冗余
        有名结构体
            一处定义多出使用
        别名结构体
            更好的使用结构体
    结构体变量初始化及成员访问
        两个凡是
            凡是基本类型,可以即可以在定义时赋值,也可以在使用时赋值
            凡是构造类型,如果不在定义时赋值,那么不能再以初始化的方式初始化
        点成员运算符(.)
            构造类型.成员
        指向成员运算符(->(*).)
        成员运算符本质
            依然是通过计算便宜来实现。此处不考虑内存对齐
        赋值
            同类变量间,可以赋值。
    结构体类型作参数和返回值
        结构体参数和返回值会发生在同类型赋值(本质是赋值)
        同类型结构体间,是可以相互赋值的
    结构体指针作参数
        指针作为参数有一个好处,就是避免了同类型赋值,无论结构体多大,只传4个字节的指针
    结构体数组
        定义初始化
            与之前数组相同
            内存存储形式也是一样
    结构体嵌套
        结构体中嵌套结构体
        嵌套结构体变量定义和初始化
    结构体类型大小
        结构体类型本身不占用内存空间,只有它生成的变量才占有内存空间的
    内存对齐
        什么是不对齐
            一个成员变量需要多个机器周期去读的现象,称为内存不对齐。
            本质是牺牲空间,换取时间的方法
        对齐规则
            x86(linc 默认是#pragma pack(4),window  默认#pragma pack(8)).linux最大支持4字节对齐.
            方法pack=N的值
            取结构体中最大的值=M
            两者取小即为外对齐大小Y(m<n?m:n)
            将每个结构体的成员大小与Y比较取小者为X作为内对齐大小
            所谓按X对齐,即为地址(设起始地址为0)能被X整除的地方开始存放数据
            外部对齐原则是依据Y的值(Y得最小整数倍),进行补空操作
    结构体注意事项
        向结构体未初始化的指针拷贝
        未释放的结构体内指针所指向的空间
            由内至外释放空间

    结构体类型
        类型本身是不占用空间,类型产生的变量才占空间
        结构体中的每个成员的地址均可以获取

    内存对齐?
        用多个机器周期去读一个变量,这种现象造成的原因,就是内存不对齐
        要实现内存对齐,牺牲空间,换取时间

    申请空间的时候从外至内,释放空间的时候,从内到外
    对于结构体而言,如果不考虑内存对齐,其大小,就是所有元素大小之和
    对于共用体而言,其大小,就是最大元素的空间大小

    成员地址
    对于结构体而言,每一个成员都有独立的地址
    对于共用体而言,所有成员,独有一个地址

共用与枚举

共用体大小 对于共用体而言,其大小,就是最大元素的空间大小 成员地址 对于共用体而言,所有成员,独有一个地址

枚举:

单向链表

链表价值 ####

我们使用malloc申请空间时,内存足够但是碎片太多,没有连续内存时,只能申请失败,链表这种数据结构可以组织数据。

静态链表

        静态链表不常用,因为数据存在栈上,容量太小,定义不方便。
        代码:
#include <stdio.h>
typedef struct _node
{
    int data;
    struct _node * next;
}NODE;

int main()
{
    NODE a;
    NODE b;
    NODE c;
    NODE d;

    a.data = 1;
    b.data = 2;
    c.data = 3;
    d.data = 4;
    a.next = &b;
    b.next = &c;
    c.next = &d;
    d.next = NULL;
    NODE *head = &a;
while(head)
{
    printf("%d",head->data);
    head = head->next;
}

}

链表名解释

    头指针
        →头节点    →(Data)a1地址 →(Data)a2地址 →...... →(Data)尾节点(NULL)

链表的作用

尾插法

思想:
    把新来的链表保存值,然后把地址保存前面链表中的地址NULL,再把新来空间的地址赋给前面的链表。


//尾插法
Node * TailList()
{
    Node * head = (Node *)malloc(sizeof(Node)); //申请一个head空间
    head->next = NULL;  //把head地址置为NULL
    Node * t = head,*cur;   //把t指向head 在创建一个cur用于开辟新的空间

    int data;   //新建变量用于存放数据
    scanf("%d",&data);  //从键盘获取数据
while(data) //只要输入的数据不为空
{
    cur = (Node *)malloc(sizeof(Node)); //cur申请新空间
    cur->data = data;   //把数据存放至新空间
    cur->next = t->next;//把cur的next置为NULL
    t->next = cur;  //把cur的地址存放到t现在的head.next中
    t = cur;//把t指向cur空间

    scanf("%d",&data);  //继续获取数据
}
    t->next = NULL; //数据为0不进上面循环,现在t.next是最后一个元素,地址置为NULL
     return head;//返回head
}

头插法

思想:
    新开辟的链表保存数据,然后把head的地址值给新开辟的链表.next,再把head地址指向cur。


//头插法
Node * HeadList()
{
    Node * head = (Node*)malloc(sizeof(Node));  //申请head空间
    head->next = NULL;  //把head地址置为NULL
    Node * cur; //申请一个cur,用于开辟新的空间
    int data;   //用于存放获取的数据
    scanf("%d",&data);   //从键盘获取数据
while(data) //只要获取的数据不为0
{
    cur = (Node*)malloc(sizeof(Node));   //开辟新空间
    cur->data = data;//存放获取到的数据
    cur->next = head->next;  //把head的地址给cur.next
    head->next = cur; //把新开辟的空间指向head.next

    scanf("%d",&data);  //继续录入数据
    }
    return head;//返回head
}

链表遍历

思想:
只要链表不为空就输出,每次head指向下一个链表。
//遍历
void displayList(Node * head)
{
    head = head->next;  //头节点没数据,无意义,所以向前走一格
while(head) //head不为空
{
    printf("%d\n",head->data);  //输入当前head保存的值
    head = head->next;  //head指向下一链表
    }
}

链表长度

思想:
先定义一个变量,并且初始化值,只要head不为空,长度+1,head在指向下一个链表。

//长度
int LenList(Node *head)
{
    head = head->next;  //第一个为头节点没有值,所以指向下一个链表
    int len = 0;//定义记录长度变量
while(head) //只要head不为空
{
    len++;  //长度+1
    head = head->next;  //head指向下一链表
}
    return len; //返回长度
}

链表插入

        头插法适合插入,如果是尾插法,每次要多遍历一次,效率太低了。

链表查找

Node * FindList(Node *head,int find)
{
    head = head->next;  //头节点没数据,无意义,所以向前走一格
while(head) //head不为空
{
if(head->data == find)
{
    break;  //找到 结束程序
}
    head = head->next;//head指向下一链表
}

    return head;//返回找到的地址
}

    Node * find= FindList(head,8);
if(find != 0 )
{
   printf("找到了\n");
}
else
{
printf("没找到\n");
}


            思想:
        只要找到查找的值,则直接结束,并返回。

链表修改

        先查找要修改的元素,在进行修改即可。

链表删除 ####

void DelList(Node* head,Node* find)
{
    head = head->next;  //头节点没数据,无意义,所以向前走一格
while((head->data!=find->data)) //只要没找值
{
    head = head->next;  //head继续指向下一个链表
}
    Node * t = find->next;
    head->data = find->next->data;
    head->next = find->next->next;
    free(t);

}

前提是这个链表,不在最后一个。 //删除优化版

链表排序

链表反转

链表销毁

文件

....丢失

位操作

位操作与逻辑操作
    逻辑操作只有真假,而按位操作是按位论真假
位操作
    & 位与    同1为1 不同则为0,在某些位不变的情况下,将其余位置0
    | 位或    同0为0    不同则为1,在某些位不变的情况下,将其余位置1
    ~ 位取反 1为0   0为1
    ^ 位异或 相同时为0,不同时为1,将其余位取反。
    <<左移 低位补0,高位溢出,位数为非负整数,且默认对32求余
    >>右移  低位舍去,位数非负整数,默认对32求余
优先级
    ( )>成员运算>(!)>算术>关系>逻辑>赋值>,
    ( )>成员运算符>(^/!)算术>关系>(>><<)位逻辑(&|^)>逻辑>赋值>,
掩码(mask)
    掩盖掉一些东西,然后留下一些东西,这就是掩码得意义

预处理

....没做