李慧芹Linux个人笔记

Linux

目录

目录的特殊表示法:

. 表示此层目录。

.. 表示上一层目录。

-表示前一个工作目录。

~ 表示当前用户身份所在的家目录。

绝对路径和相对路径

/home/tom这种写法就是绝对路径,从根目录连续写,不论在任意位置执行该命令都能移动到此路径

../mike这是相对路径写法,cd ../mike,将从/home/tom切换到/home/mike。

相对路径(Relative Pathnames)不由“/”开头,使用比较方便。虽然绝对路径写起来比较麻烦,但是能保证正确性。

查看当前路径:pwd(print working directory)

目录操作命令

创建目录

mkdir命令可以一次建立一个或几个目录。​

$ cd ~							##进入用户主目录
$ mkdir document picture		##新建两个目录
$ mkdir  ~/picture/temp			##在主目录下新建名位temp的目录
(仅能使用于在用户主目录下已创造文件夹可以使用)
如果没有的话
$ mkdir -p ~/tempx/job 			##在主目录下新建名为tempx的目录并创建位于其中的子目录

移动目录

$ mv hello bin/			##将hello文件移动到bin目录下

$ mv Photos/Desktop/	##将Photos目录移动到桌面

删除目录

rmdir

$ mkdir remove				## 新建一个名为remove的子目录
$ rmdir remove				## 删除remove目录
## rmdir 只能删除空目录

rm命令可以一次删除一个或几个文件。(通过rm命令删除的文件将永远地从系统中消失,而不会被放入一个称作“回收站”的临时目录下)

$ rm test/*.php
## 更安全的用法
$ rm -i test/hello			##输入后需回答y
## 可自动确认删除
$ rm -f hello_bak

复制目录

cp命令用来复制文件和目录。(cp命令在执行复制任务的时候会自动跳过目录。)

$ cp test.php test/
## 使用-r选项,它将子目录连同其中的文件一起复制到另一个子目录下
$ cp -r test / Desktop/

跳转目录

cd是用来切换工作目录的命令:cd 路径名

$ cd /usr/bin

##在/usr/bin子目录中还可以使用“/”目录直接进入根目录
$ cd ../..
## 回到用户主目录
$ cd
## 也可以是
$ cd ~

查看文件

查看目录:ls

ls [option]....[file]...

  • 无参ls——列出当前目录下的所有文件和子目录(默认情况下,目录显示为蓝色;普通文件显示为黑色;可执行文件显示为草绿色;淡蓝色则表示这个文件是一个链接文件)

  • ls -F ——列出当前目录下的所有文件和子目录(-F选项会在每个目录后加上/,在可执行文件后加*,在链接文件后加上@。)

  • ls -a ——显示所有文件(包含隐藏文件)

  • ls -l ——用来查看文件的各种属性

    • 文件的权限标志。文件的链接个数。文件所有者的用户名。该用户所在的用户组组名。文件的大小。最后一次被修改时的日期。最后一次被修改时的时间。文件名。

ls 后加路径名——查看该子目录中的内容

查看普通文件:cat

cat命令用于查看文件内容(通常这是一个文本文件),后跟文件名作为参数。

cat可以跟多个文件名作为参数。

cat命令提供了-n选项,在每一行前显示行号。

文件内容查找:grep

在文件中寻找某些信息,可以使用grep命令。

grep [options] pattern [file...]

在文件day中查找包含un的行()

$ grep un day
Sunday
##grep有两个类型不同的参数。第一个是被搜索的模式(关键词),第二个是所搜索的文件。
$ grep un day weather
## 如果要查找如struct list这样的关键词,那么必须加单引号以把空格包含进去
grep 'struct list' stack.h

查看文件开头和结尾:head 和 tail

分别用于显示文件的开头和结尾。可以使用-n参数来指定显示的行数。

head命令的默认输出是包括了文件名的(放在==>和<==之间)。tail的用法和head相同。

查看部分内容:more和less

more命令:一页一页地显示文件内容。(more命令会在最后显示一个百分比,表示已显示内容占整个文件的比例。按下空格键向下翻动一页,按Enter键向下滚动一行。按Q键退出。)

less命令:

  • 使用光标键在文本文件中前后(甚至左右)滚屏。

  • 用行号或百分比作为书签浏览文件。

  • 实现复杂的检索、高亮显示等操作。

  • 兼容常用的字处理程序(如Emacs、Vim)的键盘操作。

  • 阅读到文件结束时less命令不会退出。

  • 屏幕底部的信息提示更容易控制使用,而且提供了更多的信息。

less在屏幕底部显示一个冒号“:”等待用户输入命令。如果想向下翻一页,可以按下空格键。如果想向上翻一页,按下B键。也可以用光标键向前、后甚至左右移动。如果要在文件中搜索某一个字符串,可以使用正斜杠“/”跟上想要查找的内容,less会把找到的第一个搜索目标高亮显示。要继续查找相同的内容,只要再次输入正斜杠“/”,并按下回车键就可以了。

使用带参数-M的less命令可以显示更多的文件信息(less在输出的底部显示了这个文件的名字、当前页码、总的页码及表示当前位置在整个文件中的位置百分比数值。最后按下Q键可以退出less程序并返回Shell提示符。)

LinuxC语言开发工具

CGG

GCC的编译流程分为4个步骤,分别为以下内容:·

  • 预处理(Pre-Processing)。

    • “-E”可以使编译器在预处理结束时就停止编译,选项“-o”是指定GCC输出的结果

    • gcc -E -o [目标文件] [编译文件]

    • 扩展名为“.i”的文件是经过预处理的C源程序。

    • “.h”文件不能进行编译

  • 编译(Compiling)。

  • 汇编(Assembling)。

  • 链接(Linking)。

基本语法

gcc [option | filename]

C语言学习笔记

基础和概念

C语言发展史:

1960 原型A语言->ALGOL语言

1963 CPL语言

1967 BCPL

1970 B语言

1973 C语言

C语言特点

  1. 基础性语言

  2. 语法简介,紧凑,方便,灵活(由于指针的存在)

  3. 运算符、数据结构丰富

  4. 结构化,模块化编程

  5. 移植性好,执行效率高(分不同层面来看,低级语言偏汇编语言一点)

  6. 允许直接对硬件操作 (比如FPGA,DSP)

C语言学习建议

  1. 概念的正确性

  2. 动手能力

  3. 阅读优秀的程序段

  4. 大量练习、面试题

C课程讲解思路

  1. 基本概念

  2. 数据类型,运算符和表达式

  3. 输入输出专题

  4. 流程控制

  5. 数组

  6. 指针

  7. 函数

  8. 构造类型

  9. 动态内存管理

  10. 调试工具和调试技巧(gdb(调试错误,对错误进行跟踪), make)

  11. 常用库函数

平台使用

64位的ubuntu,vim, gcc(make)

使用

$ vim hello.c 			## 创建一个hello.c文件

hello.c

#include <stdio.h>
#include <stdlib.h>
/*不同编译环境下,不同的main使用方式
	void main(void);
	void main(int argc, char **argv);//char *argv[]
	int main(int argc, char **argv);
	int main(void)
*/
int main(void)
{
	printf("Hello world!\n");
	
	exit(0);
}

shell 语句中 i=1;(如果有空格可能有误),但建议在c语句中多用空格和换行

## 退出并保存
在命令行模式下输入":wq"(保存并退出)或":q"(退出)

hello.c

编译器gcc:gcc -v可查看当前gcc的版本

编辑器vim:vim /etc/vimrc 配置文件(cd不建议修改etc下的vimrc文件,更建议拷贝到家目录下,修改拷贝过来的新文件)

$ vim /etc/vimrc			## 打开etc下的vimrc文件(会出现选项,注意看)
$ cp /etc/vimrc ~/.vimrc 	 ## 在~文件下新建一份.vimrc文件(打造自己的vimrc)
$ vim ~/.vimrc				## 打开.vimrc文件

[vim配置]  vim.md 

C源文件——预处理——编译——汇编——链接——可执行文件

 ## 预处理
$ gcc -E hello.c
## 将预处理产生的内容存储到.i文件中
$ gcc -E hello.c > hello.i 
## 编译,产生一个.s的汇编文件
$ gcc -S hello.i
## vim  hello.s 打开汇编文件
## 将s文件进行汇编产生.o文件(目标文件)
$ gcc -c hello.s 
## 进行链接产生可执行文件(指定名字为hello)
$ gcc hello.o -o hello  ##再输入ls会发现生成了一个绿色的hello
## 运行当前文件下的指定程序
$ ./hello
/   以上程序繁杂,可使用下方简略版方法   /
$ gcc hello.c
$ gcc hello.c -o hello
$./hello
/    使用make    /
$ make hello.c
##编译执行
$ gcc main.c
$ ./a.out

基本概念

  1. 对写程序的思路提出以下要求

    1. 头文件正确包含

    2. 以函数为单位编写程序(把一些功能变成小模块)

    3. 声明部分 + 实现部分

    4. return 0;是给他的父程序看的

    5. 多用空格空行

    6. 添加注释(// /* */ )(#if 0 ···· #endif)

    注释不能嵌套使用

  2. 算法:解决问题的方法(流程图、NS图、有限状态FSM)

  3. 程序:用某种语言实现算法

  4. 进程:

  5. 防止写越界,防止内存泄露,谁打开谁关闭,谁申请谁释放

数据类型,运算符和表达式

数据类型:(基本数据类型)

基本数据类型:

  • 数值类型:整型(短整型 short ,整型 int, 长整型 long)

浮点型(单精度型 float, 双精度型 double)

  • 字符类型char

类型符号关键字所占位数
整型(signed)int32
(signed)short16
(signed)long32
unsigned32
unsigned short16
unsigned long32
实型float32
double64
字符型char8
unsigned char8

所占字节数随机器硬件不同而不同

注意:

  1. 所占字节数

  2. 存储区别

  3. 不同类型的数据间进行转换

    1. 进制转换

      1. 什么都不写 -->十进制

      2. B开头 -- > 二进制

      3. 0开头 --> 八进制

      4. 0x -->十六进制

      5. C语言不识别2进制

        换算方法:8421法

    2. 补码形式

      1. 取反 + 1(负数)

      2. 本身(正数)

  4. 特殊性

    1. 布尔型 bool

    2. float类型

    3. char型是否有符号

    4. 不同形式的0值:0 , '0', "0", '\0'

常量与变量

常量:

在程序执行过程中值不会 发生变化的量

  1. 分类

    1. 整型常量:1,790,76,52

    2. 实型常量:3.14,5.26,1.9999

    3. 字符常量:由单引号引起来 的单个的字符转义字符:'\n',

      C标准规定的转义字符

      转义序列的两个作用:一是把普通字符转义成特殊字符,例如把字母n转义成换行符;

      二是把特殊字符转义成普通字符,例如\和"是特殊字符,转义后取它的字面值。

    4. 字符串常量:由双引号引起来的一个或多个字符组成的序列(空串):"", "a","abXYZ", "abc\n\021"

    5. 标识常量:#define,处理在程序的预处理阶段,占编译时间,特点:一改全改,缺点:不校验语法是否错误,只是单纯的宏体与宏名之间的替换

变量:

用来保存一些特定内容,并且在程序执行过程中值随时会发生变化的量

  1. 定义:[存储类型] 数据类型 标识符 = 值

  2. TYPE NAME = VALUE

  3. 标识符:由字母、数字、下划线组成且不能以数字开头的一个标识序列

    1. 写标识符尽量做到见名生义

  4. 数据类型:基本数据类型 + 构造类型

  5. 值:注意匹配

  6. 存储类型:auto static register extern(说明型)

    1. auto :默认,自动分配空间,自动回收空间

    2. register :(建议型)寄存器类型,只能用来定义局部变量,不能定义全局变量;大小有限制,只能定义32位大小的数据类型(double不可以)寄存器没有地址,所以一个寄存器的类型的变量无法打印出地址查看或使用

    3. static:静态型,自动初始化为0值或空值,并值其变量的值有继承性。另外,常用于修饰变量或者是函数

    4. extern:说明型,意味着不能改变 被说明的变量或空值

  7. 变量的生命周期和作用范围

    1. 全局变量和局部变量

      1. 全局变量:从声明位置开始,到程序结束

      2. 局部变量:从子程序位置开始,到所在的块程序运行结束

      3. 程序永远是从内部到外部的

    2. 局部变量和局部变量

运算符和表达式

  • 表达式与语句的区别:

    • i = 1 表达式,i = 1 ;语句

  • 运算符部分:

    • 每个运算符所需要的参与运算的操作数个数

    • 结合性

    • 优先级

    • 运算符的特殊用法

      • %,=与 ==,逻辑运算符的短路特性

    • 位运算的重要意义

      • 将操作数中第n位置1,其他位不变:num = num | 1 << n

      • 将操作数中第n位清0,其他位不变:num = num & ~ (1 << n);

      • 测试第n位:if(num & 1 << n )

      • 从一个指定宽度的数中取出其中的某几位

输入、输出

输入:input 输出:output -> I/O (标准IO,文件IO)

  • 格式化输入输出函数:scanf,printf

    int printf(const char *format,...)

    format:"% [修饰符] 格式字符"(修饰符可省)

    int scanf(const char *format, ...);

    format:抑制符*

    %s的使用是比较危险的,因为不知道存储空间大小

    scanf放在循环结构中要注意能否接受到正常有效的内容

    格式字符

    d,i十进制整数
    x,X十六进制无符号整数
    o八进制无符号整数
    u不带符号十进制整数
    c单一字符
    s字符串
    e,E指数形式浮点小数
    f小数形式浮点小数
    ge和f中比较短的一种
    %%百分号本身

    修饰字符

    m输出数据域宽,数据长度<m,左补空格,否则按实际输出
    .n对实数,指定小数点后位数(四舍五入);对字符串,指定实际输出位数
    -输出数据在域内左对齐(缺省右对齐)
    +指定在有符号数的正数前显示正号
    0输出数值时指定左面不使用的空位置自动填0
    #在八进制和十六进制数前显示前导0,0x
    1在d,o,x,u前,指定输出精度为long型;在e,f,g前,指定输出精度为double型
    //printf
        
    #include <stdio.h>
    #include <stdlib.h>
    
    /*
     *printf("%[修饰符]格式字符",输出表项);
     *
     **/
    int main()
    {
        char ch = 65;
        printf("%d\n",ch);
        
        exit(0);
    }
    
    //修饰符m
    int main()
    {
        int i = 123;
        printf("i = %d\n",i);//输出 i =  123
        
        exit(0);
    }
    
    //修饰符.n
    int main()
    {
        int i = 123;
        float f = 123.45678;//(更改为123.456)
        
        //printf("f = %f\n",f);//输出123.456779 (更改后输出为123.456001)
        printf("f = %8.1f\n",f);//输出为 f =   123.5
        exit(0);
    }
    
    //其他修饰符 大总结版
    #include <stdio.h>
    #include <stdlib.h>
    
    /*
     *printf("%[修饰符]格式字符",输出表项);
     *
     **/
    
    #define STRSIZE 32
    
    int main()
    {
        int i = 255;
        float = 123.456;
        char str[STRSIZE] = "helloworld";
        double dou = 123.456;
        long long l = 123456;
        char ch = 65;
        
     //   printf("dou = %lf\n",dou);
     //   printf("l = %lld\n",l);
     //   printf("i = %#o\n i=%#x\n",i,i);
     //   printf("f = %8.1f\n",f);
     //   printf("i= $2d\n",i);
     //   printf("%d\n",ch);
        
        exit(0);
    }
    

    make [filename]

    ./[filename]

printf("%s:%d",__FUNCTION__,__LINE__); //打印当前所在位置使用的函数和行号 

//记得加\n,不然会一直在缓冲区!!!

Ctrl + C打断运行语句

//scanf
#include <stdio.h>
#include <stdlib.h>

/*
 *int scanf (const char *format, 地址表);
 *
 **/

#define STRSIZE 32
int main()
{
        int i;
        float f;
        char ch, str[STRSIZE];
        printf("Please enter:\n");
        scanf("%d",&i);
       // scanf("%*c%c",&ch);
        getchar();
        scanf("%c",&ch);
        printf("i = %d, ch = %d\n",i,ch);

#if 0
        while(1)
        {
             ret = scanf("%d",&i);
             printf("ret = %d\n",ret);
             //scanf放在循环中很危险,校验scanf返回值的正确性
             if(ret != 1)
             {
                     printf("Enter error!\n");
                     break;
             }
                printf("i = %d\n",i);
        }
#endif
     //   scanf("%s",str); //不能输出空格后的字符
     //   printf("%s\n",str);

     //   scanf("%d%f",&i,&f);  //不能加\n
     //   printf("i = %d\n",i);
     //   printf("f = %f\n",f);
}
  • 字符输入输出函数:getchar, putchar

//getchar_putchar

#include <stdio.h>
#include <stdlib.h>

int main()
{
        int ch;

        ch = getchar();
        putchar(ch);
        exit(0);

}
  • 字符串输入输出函数:gets(!), puts

#include <stdio.h>
#include <stdlib.h>

#define STRSIZE 32

int main()
{
        char str[STRSIZE];
        gets(str);//容易越界,会自动加一个伪0,可以用fgets代替
        puts(str);

        exit(0);
}

gets:十分危险的函数,可以用fgets, getline来替代。

输入,输出练习题

  1. 一个水分子的质量大约为3.0e-23g,一夸脱水大约有 950克,编写一程序,要求从终端输入水的夸脱数,显示夸脱水中有多少个水分子

  2. 从终端输入三角形的三边长,求面积

  3. 输入a,b,c的值,求方程的根(ax^2 + bx + c = 0设 b*b - 4ac > 0)

#include <stdio.h>
#include <stdlib.h>
//把常量值设置为宏

#define WEIGHT 3.0e-23
#define KQ     950

static void water(void)
{
    float num;
    float sum;
    printf("Please input for num:");
    scanf("%f",&num);

    sum = num * KQ / WEIGHT ;
    printf("total is %e\n",sum);

    return ;
}

int main()
{
//    water();

        exit(0);
}

流程控制

顺序、选择、循环

NS图、流程图 工具Dia(有很多好处)

简单结构与复杂结构:自然流程

顺序:语句逐句执行

选择:出现了一种以上的情况

循环:在某个条件成立的情况下,重复执行某个动作

关键字:

选择:if-else switch-case

循环:while do-while for if-goto

辅助控制:continue break

if-else:

格式:

if(exp)
    cmd;
或
 if(exp)
     cmd1;
else
    cmd2;
#include <stdio.h>
#include <stdlib.h>

/*
 * score [90-100]   A
 *       [80-90)    B
 *       [70-80)    C
 *       [60-70)    D
 *       [0-60)     E
 *
 */

//闰年的判断:能被4整除但不能被100整除,或者能被400整除

int main()
{
    int year;
    scanf("%d",&year);
    if(((year % 4 ==0) && (year % 100 != 0)) || (year % 400 ==0))
            printf("%d is leap year",year);
    else
            printf("%d is not leap year",year);
#if 0
        int score ;
        printf("Enter a score :[0,100]:");
        scanf("%d",&score);

        if(score < 0 || score > 100)
        {
                fprintf(stderr,"Input error!\n");
                exit(1);
        }
        

        if(score > 90)
                puts("A");
        else if(score > 80)
                puts("B");
            else if(score > 70)
                     puts("C");
                else if(score > 60)
                         puts("D");
                    else 
                        puts("E");
#endif

/*        if(score <= 100 && score >=90)
                puts("A");
        if(score < 90 && score >=80)
                puts("B");
        if(score <80 && score >= 70)
                puts("C");
        if(score <70 && score >=60)
                puts("D");
        if(score <60 && score >=0)
                puts("E");
*/
#if 0
        int a = 1, b = 1, c = 2;
        if(a == b)
        {
                if(b == c)
                printf("a == b == c\n");
        }
        //else只找和它最近的if相匹配
        else
                printf("a != b\n");
#endif

#if 0
        int a = 9,b = 10;

        if(b++  < a)
                printf("1\n");
        else
                printf("0\n");
        printf("a = %d,b = %d",a,b);
        printf("%d\n",(++b < a, ++a, b++));
        printf("a = %d, b = %d\n",a,b);
#endif
        exit(0);
}

switch-case

语法格式:

switch(exp)
{
    case 常量或常量表达式:
        break;
    case 常量或常量表达式:
        break;
     ······
    default:
}

实例

#include <stdio.h>
#include <stdlib.h>

int main()
{
        int ch;
        ch = getchar();
        
        switch(ch)
        {
                case 'a':
                case 'A':
                        printf("Ant: a small insect that lives in group.\n");
                        break;
                case 'b':
                case 'B':
                        printf("Butterfly:A flying insect with a long thin body!\n");
                        break;
                case 'c':
                case 'C':
                        printf("Cobra: A highly dangerous snake.\n");
                        break;
                case 'd':
                case 'D':
                        printf("Donkey:A animal with short legs and long ears\n");
                        break;
                default:
                        printf("Input error!\n");
                        break;
        }




//default 很重要,使用循环语句时要懂得报错
#if 0
        int score;

        printf("Please enter:");
        scanf("%d",&score);

        if(score < 0 || score >100)
        {
                fprintf(stderr,"EINVAL");
                exit(1);
        }

        switch(score/10)
        {
                case 10:
                case 9:
                        puts("A");
                        break;
                case 8:
                        puts("B");
                        break;
                case 7:
                        puts("C");
                        break;
                case 6:
                        puts("D");
                        break;
                default:
                        puts("E");
                        break;
        }
#endif
}

循环:while,do-while,for,if-goto

while

while :循环体最少执行次数——0;
    
while(exp)
    loop;

do-while

do - while :最少执行次数——1;

do
{
    loop;
}while(exp);

for

for (最少执行次数0)
    for(exp1;exp2;exp3)
        loop;

if-goto(慎用)

goto 实现的是无条件跳转,且不能跨函数跳转

例子

#include <stdio.h>
#include <stdlib.h>

#define LEFT 1
#define RIGHT 100

int main()
{
        int i;
        int start,end =10;
        int sum = 0;

        i = LEFT;
    
//if-goto
    loop:
        sum += i;
        i++;

        if(i <= RIGHT)
                goto loop;

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

#if 0

        //for

        for( i =LEFT;i <= RIGHT;i++)
        {
                sum += i;
        }
        printf("sum = %d\n",sum);
#endif

#if 0
        printf("Please enter:");
        scanf("%d",&start);
        do
        {
                sum += start;
                start++;
        }while(start <= end);
        printf("start = %d\n",start);
        printf("sum = %d\n",sum);
#endif


#if 0
        //do-while

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

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

#if 0   
        //while();

        i = LEFT;

        while(i <= RIGHT)
        {        
                sum += i;
                i++;
        }
        printf("sum = %d\n",sum);
#endif
        exit(0);
}

死循环:

while(1);
for( ; ; );

//杀掉死循环
ctrl + c

辅助控制的关键字:break continue

while()
{
    ...
     
  continue;//跳出本次循环,看下一次循环,成立,继续执行,不成立,结束循环
 
  break;//跳出本层循环
    .......
}

流程控制例题

选择循环部分:

投资问题:A以10%的单利息投资了100美元,B以每年5%的复合利息投资了100美元、编写一程序,计算需要多少年B的投资总额才会超过A的,并且显示出到那个时刻两个人的各自的资产总额(单利息 = 0.10 * 原始存款,复合利息 = 0.05% * 当前存款)

int year;
        int A = 100 , B = 100;
        for(year = 1;B <= A;year++)
        {
                A += 100 * 0.10 ;
                B += B * 0.05 ;
                //printf("A = %d\tB= %d\n ",A,B);
        }
        printf("after %d years B over A\n",year);

从终端读入数据,直到输入0值为止,计算出其中的偶数个数和平均值和奇数的个数及平均值

  int num;
        int odd = 0,even = 0;
        while(scanf("%d",&num) == 1 && num != 0)
        {
                if(num % 2 != 0)
                {
                        odd ++;
                }
                else
                {
                        even ++;
                }
        }
        printf("odd num has %d even num has %d",odd,even);
}

从终端上输入若干字符,对其中的元音字母进行统计

#include <stdio.h>
#include <math.h>
#define ARRAY_NUM 100
int main(void)
{
	char c [ARRAY_NUM]={0};
	int count=0,i,k=0;
	gets(c);
	for(i=0;i<=ARRAY_NUM;i++)
	{
		if(c[i]==10)
		break;
		if(c[i]!=0)
		printf("%c",c[i]);
		if(c[i]=='a'||c[i]=='e'||c[i]=='i'||c[i]=='o'||c[i]=='u')
		{
			count++;
		}
	}
	printf(",%d",count);
} 

写出fibonacci数列的前40项(不能用数组实现)斐波那契数列(第1,2两个数为1,1。从第三个数开始,该数是其前面两个数之和。即该数列为1,1,2,3,5,8,13)

static void test4(void)
{
        int i = 1, o = 1;
        int sum;
        for(sum = 0;sum <= 20;sum++)
        {
              printf("%d\t%d\t",i,o);
                i = i + o;
                o = i + o;
        }
}

输出九九乘法表

static void test5(void)
{
     int i ,a ;
     int sum;
     for(i = 1, a = 1;i <= 9 ; i++)
     {
             sum = a * i;
             printf("%d * %d = %d\t",a,i,sum);
     }
     for(a = 2,i = 2;i <= 9;i++)
    {
            sum = a * i;
            printf("%d * %d = %d\t",a , i, sum);
    }
     for(a = 3,i = 3;i <= 9;i++)
    {
            sum = a * i;
            printf("%d * %d = %d\t",a , i, sum);
    }
     for(a = 4,i = 4;i <= 9;i++)
    {
            sum = a * i;
            printf("%d * %d = %d\t",a , i, sum);
    }
     for(a = 5,i = 5;i <= 9;i++)
    {
            sum = a * i;
            printf("%d * %d = %d\t",a , i, sum);
    }
     for(a = 6,i = 6;i <= 9;i++)
    {
            sum = a * i;
            printf("%d * %d = %d\t",a , i, sum);
    }
     for(a = 7,i = 7;i <= 9;i++)
    {
            sum = a * i;
            printf("%d * %d = %d\t",a , i, sum);
    }
     for(a = 8,i = 8;i <= 9;i++)
    {
            sum = a * i;
            printf("%d * %d = %d\t",a , i, sum);
    }
     for(a = 9,i = 9;i <= 9;i++)
    {
            sum = a * i;
            printf("%d * %d = %d\t",a , i, sum);
    }
     
}

//更简单的方法出现了
#include<stdio.h>
int main()
{
	int i,j,sum;
	for(i=1;i<=9;i++) 	 //  (1)i=1 i<=9 满足条件往下走 
	{
		for(j=1;j<=i;j++)	//(2)j=1 j<=i(1<=1) 满足条件 往下走 
		{
			printf("%d * %d = %d\t",i,j,i*j);//(3)输出 i'*'j= i*j   
		}                       //输出过后 返回for循环执行 j++,j此时大于i,不满条件 ,往下执行printf 
		printf("\n");      //i控制的是行数,第一行已经输出完毕,要换行,所以输出一个"\n" 
	}
	return 0;
 } 

百钱买百鸡:鸡翁一,值钱五;鸡母一,值钱三;三鸡雏,值钱一,百钱买百鸡,问鸡翁,鸡母,鸡雏各几何?

static void test6(void)
{
       int cock_num,hen_num,chicks_num,sum;
       for(cock_num = 1;cock_num <= 100;cock_num ++)
       {
               for(hen_num  = 1;hen_num <= 100;hen_num++)
               {
                       for(chicks_num = 1;chicks_num <= 300;chicks_num ++)
                      {
                               if((cock_num + hen_num + chicks_num == 100) && (cock_num * 5 + hen_num * 3 + chicks_num/3 == 100) && (chicks_num % 3 == 0))
                               {
                                       printf("cock's num, hen's num and chicks' num is %d\t%d\t%d\n",cock_num,hen_num,chicks_num);
                               }
                       }
               }
       }
}

求出1000以内的水仙花数:153 1+125+27 =153

static void test7(void)
{
        int a,b,c,i;
        for(i = 1; i<= 1000; i++)
        {
                a = i/100;
                b = i/10%10;
                c = i % 10;
                if(a * a * a + b * b * b + c * c * c == i)
                {
                        printf("%d\n",i);
                }
        }
}

求出1000以内的所有质数:2,3,5,7,11,13,17,19(只能被1和它本身整整除)

static void test8(void)
{
        int i,j,mark;
        for(i = 2 ;i <= 1000; i++)
        {
                mark = 1;
               for(j = 2; j < i ;j++)//for(j = 2; j <= i/2 ; j++)
               {
                       if(i % j == 0)
                       {
                               mark = 0;
                               break;
                       }
               }
               if(mark)
               {
                       printf("%d \t",i);
               }
        }
}

在终端上实现如下输出:

ABCDEF
BCDEF
CDEF
DEF
EF
F
static void test9(void)
{
        int line = 6,chars = 6;
        int i;
        char ch;
        for(i = 0;i < line; i++)
        {
                for(ch = 'A' + i; ch < 'A' + chars ; ch++)
                {
                        printf("%c",ch);
                }
                printf("\n");
        }
}

输出钻石型

  *
 * *
* * *
 * *
  *
static void test10(void)
{
        int line = 3;
        int i,k,j;
        for(i = 1; i < 4; i++)
        {
                for(j = 1;j <= 4 - i;j++)
                {
                        printf(" ");
                }
                for(k = 1; k <= 2*i-1; k++)
                {
                        printf("*");
                }
                printf("\n");
        }
        for(i = 1;i<=3;i++)
        {
                for(j = 1;  j <= i; j++)
                {
                        for(j = 1; j <= i; j++)
                        {
                                printf(" ");
                        }
                }
                for(k = 1; k <= 7 - 2 * i; k++)
                {
                        printf("*");
                }
                printf("\n");
        }
}

从终端输入N个数求和(以字母q/Q为终止)

static void test11(void)
{
        int a,sum = 0;
        printf("Please enter integer\n");
        while(scanf("%d",&a) == 1)
        {
                sum += a;
        }
        printf("%d",sum);
}

从半径为1开始,输出圆的面积,直到圆的面积>100为止

static void test12(void)
{
        float pi = 3.14;
        int radius;
        float area;
        for(radius = 1 ; area <= 100 ; radius++)
        {
                area = pi * radius * radius;
                if(area <= 100)
                    printf("when radius is %d the round's area is %f\n",radius , area);
            //也可以更换为
            //if(area > 100)
            //break;
        }
}

数组

特点:构造类型之一,连续存放

一维数组

定义:

指定【存储类型】(可省) 数据类型 标识符 【下标】(只能是整型的常量或整型的常量表达式)

初始化

  • 不初始化

  • 全部初始化

  • 部分初始化

    static

元素引用

数组名 【下标】

数组名

数组名是表示地址的常量,也是数组的起始位置。

数组越界

#include <stdio.h>
#include <stdlib.h>

#define M       3

int main()
{
        int i ;
        int arr[M];
    //static int arr[M] ;
    //int arr[M];不初始化
    //int arr[M] = {1,2,3}; 全部初始化
    //int arr[M] = {1};部分初始化
        
        printf("%ld\n",sizeof(arr));
        printf("arr = %p\n",arr);
        
        for(i = 0; i < M ; i++)
            scanf("%d",&arr[i]);

        for(i = 0; i < M; i++)
        printf("%p --> %d\n",&arr[i],arr[i]);
        exit(0);
}

练习题

fibonacci数列前十项

#include <stdio.h>
#include <stdlib.h>

static void fibonacci(void)
{
        int fib[10] = {1,1};
        int i;
        for(i = 2 ; i < 10; i++)
        {
            fib[i] = fib[i - 1] + fib[i - 2];
        }
        for(i = 0; i < 10; i++)
        {
                printf("%d ",fib[i]);
        }
        printf("\n");
        return ;
}
/*    在数组中逆序存放
        i = 0;
        j = sizeof(fib)/sizeof(fib[0]) - 1;
        
        while(i < j)
        {
                tmp = fib[i];
                fib[i] = fib[j];
                fib[j] = tmp;

                i++;
                j--;
        }

        for(i = 0; i <sizeof(fib)/sizeof(fib[0]);i++)
                printf("%d ",fib[i]);
        printf("\n");
*/
        
        return ;
}

int main()
{
        fibonacci();
        exit(0);
}

数据排序(冒泡法,选择法,快速排序)

//冒泡法
static void sort1(void)
{
        int i,j,tmp;
        int a[N] = {12,8,45,30,98,67,2,7,68,11};
        for(i =0; i< N;i++)
                printf("%d\t",a[i]);
        printf("\n");
        for(i = 0; i < N; i++)
        {
                for(j = 0; j <  N - 1 -i  ; j++)
                {
                        if(a[j]  > a[j+1])
                        {
                                tmp = a[j];
                                a[j] = a[j+1];
                                a[j + 1] = tmp;
                        }
                }
        }
        for(i =0; i< N;i++)
                printf("%d\t",a[i]);
        printf("\n");
}

//选择法
static void sort2(void)
{
        int i,j,k,tmp;
        int a[N] = {23,45,90,76,13,55,76,45,3,8};
        for(i = 0; i < sizeof(a)/sizeof(a[i]);i++)
                printf("%d\t",a[i]);
        printf("\n");
        for(i = 0; i < N + 1; i++)
        {
                k = i;
                for(j = i + 1;j < N;j++)
                {
                        if(a[j] < a[k])
                                k = j;
                }
                if(i != k)
                {
                        tmp = a[i];
                        a[i] = a[k];
                        a[k] =  tmp;
                }
        }
        for(i = 0; i < sizeof(a)/sizeof(a[i]);i++)
                printf("%d\t",a[i]);
        printf("\n");
}

进制转换

static void base_convert(void)
{
        int num,base;
        int n[128], i= 0;
        printf("Please enter the converted num:");
        scanf("%d",&num);
        printf("Please enter the base:");
        scanf("%d",&base);

        do
        {
                n[i] = num % base;
                num = num/base;
                i++;
        }while(num != 0);
        
        for(i -- ; i >= 0;i--)
        {
                if(n [i] >= 10)
                        printf("%c",n[i] -10+'A');
                else
                        printf("%d",n[i]);
        }
        printf("\n");
}

删除法求质数

static void primer(void)
{
        int i,j;
        char primer[1001] = {0};
        for(i = 2;  i<1001; i++)
        {
                if(primer[i]==0)
                {
                for(j = i * 2; j<1001;j += i)
                        primer[j] = -1;
                }
        }
        for(i = 2;i <1001; i++)
        {
                if(primer[i] == 0)
                        printf("%d\t",i);
        }
        printf("\n");
}

二维数组

定义

【存储类型】数据类型 标识符 【行下标】【列下标】

#define M       2
#define N       3

int main()
{
        //行号可以省略,列号不可省
        int a[M][N] = {1,3,4,6,7};
        //int a[M][N] = {{1,3},{4}};
        //int a[M][N] = {{1,2,3},{4,5,6}};
        int  i,j;
#if 0      
        for(i = 0; i < M; i++)
                for(j = 0; j < N; j++)
                        scanf("%d",&a[i][j]);
#endif
        printf("a = %p \n",a);
        for(i = 0 ; i < M; i++ )
        {
                for(j = 0; j < N; j++)
                {
                        printf("%p -- > %d\n",&a[i][j],a[i][j]);
                }
                printf("\n");
        }

        exit(0);
}

元素引用

数组名 【行标】【列标】

存储形式

顺序存储 ,按行存储

二维数组的深入理解

例题

如何让一个二维数组行列互换

#define M       2
#define N       3

static void change(void)
{
        int a[M][N]={1,2,3,4,5,6},b[N][M];
        int i,j;
        for(i = 0; i < M ; i ++)
        {
                for(j = 0; j < N ; j++)
                {
                        printf("%d ",a[i][j]);
                        b[j][i] = a[i][j];
                }
                printf("\n");
        }

        for(i=0; i<N;i++)
        {
                for(j=0;j<M;j++)
                        printf("%d ",b[i][j]);
                 printf("\n");
        }

}

在一个二维数组中求最大值及其所在位置

static void max(void)
{
        int a[M][N] = {43,4,23,89,9,7};
        int i,j;
        int max = a[0][0],row = 0,colum = 0;

        for(i = 0; i < M; i++)
        {
                for(j = 0;j < N;j++)
                {   
                        if(max < a[i][j])
                        {       
                        max = a[i][j];
                        row = i;
                        colum = j;
                        }
                 }   
        }
        printf("max:a[%d][%d] = %d\n",row,colum,max);
}

求各行与各列的和

static void sum(void)
{
        int a[5][4] = {{1,2,3},{4,5,6},{7,8,9},{10,11,12}};
        int i,j;

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

矩阵乘积

static void mul(void)
{
        int a[M][N] = {1,2,3,4,5,6};
        int b[N][K] = {1,0,0,1,1,0};
        int c[M][K] = {0};
        int i,j,k;

        for(i = 0; i < M;i++)
        {
                for(j = 0; j < K ; j++)
                {
                        for(k = 0; k < N;k++)
                        {   
                                c[i][j] += a[i][k] * b[k][j];
                        }
                }
        }
        for(i = 0; i < M ; i++)
        {
                for(j = 0; j < K; j++)
                        printf("%4d",c[i][j]);
                printf("\n");
        }
}

字符数组

定义,初始化,存储特点

【存储类型】 数据类型 标识符 【下标】...

单个字符初始化

字符串常量初始化

      char str[N] = {'a','b','c'};
      char str[N] = "a";
      char str[N];

输入输出

printf("%s",str);//无法识别分隔符

常用函数

strlen 以伪0为结束统计字符个数;
sizeof 统计字符个数了;
strcpy 
strncpy :防止越界现象;
strcat :追加字符
    
    #define  STRSIZE        32

int main()
{
        char str[STRSIZE] = "hello";
        char str1[STRSIZE] = "helloa";
       // printf("%d\n",strcmp(str,str1));
        printf("%d\n",strncmp(str,str1,5));

    /*
        strcat(str," ");
        strcat(str,"word!");

        strncat(str," ",STRSIZE);
        strncat(str,"word!",STRSIZE);
        puts();
*/

/*
       strcpy(str,"abcde");
       strncpy(str,"abcde",STRSIZE);
       puts();
*/

/*
        printf("%d\n",strlen(str));
        printf("%d\n",sizeof(str));
        puts();
 */
        exit(0);
}

练习题

统计单词

int  main()
{
        int i;
        char str[128];
        int count = 0,flag = 0;

        gets(str);

        for(i = 0; str[i] != '\0'; i++)
        {
                if(str[i] == ' ')
                        flag = 0;
                else
                        if(flag == 0)
                        {
                                count ++;
                                flag = 1;
                        }
        }

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


        exit(0);
}

多维数组

指针

变量与地址的关系

指针就是地址,存储内存地址(相当于一个房间号)

指针与指针变量

指针在64位系统中是8个字节,类型一定要相符

ptr = &bah;
val = *ptr;
//相当于val = bah;
//TYPE NAME = VALUE

int main()
{
        int i = 1;
        int *p = &i;
    //    float *q;
      //  double *d;
        //char *c;

#if 0
        printf("%d\n",sizeof(p));
        printf("%d\n",sizeof(q));
        printf("%d\n",sizeof(d));
        printf("%d\n",sizeof(c));
#endif

#if 0
        p = &i;

        printf("%d\n",sizeof(i));
        printf("%d\n",sizeof(p));


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

#endif
        exit(0);
}

直接访问与间接访问

空指针与野指针

int *p = NULL;//空指针

//野指针  -->  指针没有确定的指向 
int *p ;
printf("%d\n",*p);

空类型的指针

void *q = NULL; //void百搭的类型:不确定到底需要哪个数据类型的时候

定义与初始化的书写规则

int main()
{
        int i = 1;
        int *p = &i;
        int **q = &p;
    
    //i		*p		**q
    //&i	p		*q
        printf("i = %d\n",i);		//i = 1;
        printf("&i = %p\n",&i);		//&i = i所在的地址

        printf("p = %p\n",p);		//p = &i
        printf("&p = %d\n",&p);		//&p = p 所在的地址
        printf("*p = %d\n",*p);		//*p = i     

        printf("q = %p\n",q);		//q = &p
        printf("*q = %p\n",*q);		//*q = p = &i
        printf("**q = %d\n",**q);	//**q = *p = i

        exit(0);
}

指针运算

&  *  关系运算 ++ --

指针与数组

指针与一维数组

#include <stdio.h>
#include <stdlib.h>

//a[i]value: a[i] = *(a+i) = *(p+i) = p[i]
//&a[i]: &a[i] = a+i = p+i = &p[i]
int main()
{
        int a[] = {5,1,7,2,8,3};
        int y;
        int *p = &a[1];
        
        y = (*--p)++;
        printf("y = %d\n",y);
        printf("a[0]= %d\n",a[0]);


/*
        int *p = (int [3]){1,2,3};
        int i;

        for(i = 0; i < 3; i++)
                printf("%p -> %d\n",&p[i],p[i]);
*/

#if 0
        int a[3];
        int *p = a;
        int i;

        for(i = 0; i < sizeof(a)/sizeof(*a);i++)
                printf("%p -> %d\n",&a[i],a[i]);

        for(i = 0; i < sizeof(a)/sizeof(*a);i++)
                scanf("%d",p++);

        p = a;

        for(i = 0; i < sizeof(a)/sizeof(*a);i++,p++)
                printf("%p -> %d\n",p,*p);
#endif

#if 0
        int a[3] = {1,2,3};
        int *p = a;
        int i;

        p++;
        //p++;      -> p = p+1;
        //P+1;      

        printf("%p,%p\n",a,a+1);
        printf("%p,%p\n",p,p+1);

        //*a = *(a+0) = a[0];
        for(i = 0; i < sizeof(a)/sizeof(*a);i++)
                //printf("%p -> %d\n",p+i,*(p+i));
                //printf("%p -> %d\n",p+i,a[i]);
                printf("%p -> %d\n",a+i,a[i]);
        printf("\n");

#endif
        exit(0);
}

指针与二维数组

指针与字符数组

const与指针

指针数组与数组指针

数组指针:【存储类型】 数据类型 (*指针名【下标】) = 值

int (*p)[3]; -> type name ; -> int [3] *p

指针数组:【存储类型】数据类型 * 数组名 【长度】

int * arr[3]; -> TYPE NAME; -> int * [3]
#include <stdio.h>
#include <stdlib.h>

int main()
{

        int i,j,k;
        char  *name[5] = {"Follow me","Basic","Great","Fortran","Computer"};
        char *tmp;

        for(i = 0; i < 5-1; i++)
        {
                k = i;
                for(j = i + 1; j < 5; j++)
                {
                        if(strcmp(name[k],name[j])  > 0)
                                k = j;
                }
                if (k != i)
                {
                        tmp = name[i];
                        name[i] = name[k];
                        name[k] = tmp;
                }
        }

        for(i = 0; i < 5; i++)
        
                puts(name[i]);
        

        exit(0);
}

多级指针

函数

函数的定义

数据类型 函数名(【数据类型 形参名,数据类型 形参名 ......】)

#include <stdio.h>
#include <stdlib.h>

int main()
{
    printf("Hello!\n");
    return 0;
}
$ echo $ ? (查看返回值)
printf的返回值(输出的有效字符个数+回车)
int main(int argc, char *argv[])
    //argc 命令行中传递给程序的参数个数,包括程序的名称在内的所有参数的个数
    //argv[] 字符指针数组的起始位置
{
    int i;
    printf("argc = %d\n",argc);
    
    for(i = 0; i < argc ; i++)
        for(i = 0; argv[i] != NULL; i++)
            puts(argv[i]);
    return  0;
}
#include <stdio.h>
#include <stdlib.h>

//void printf_hello(void)//函数的声明 ,如果被调函数在主调函数下方则需要外加一行声明

void printf_hello(void)//被调函数
{
    printf("Hello world!\n");
    return ;
}

int main()//主调函数
{
    print_hello();
    
    return 0;
}

//如果被调函数写在了主调函数的下方,则会看不到被调函数

函数的传参

值传递

#include <stdio.h>
#include <stdlib.h>

int  print_value(int a,int b)//形式参数(形参)
{
        printf("%d %d\n",a,b);
        return 0;
}

int main()
{

        int i = 3,j = 5;//实际参数(实参)
        print_value(i,j);
        return 0;
}

地址传递

#include <stdio.h>
#include <stdlib.h>

void swap(int *p,int *q)
{
        int  tmp;

        tmp = *p;
        *p = *q;
        *q = tmp;
}

int main()
{
        int i = 3,j = 5;
        int tmp;

        swap(&i,&j);
        printf("i = %d\nj = %d\n",i,j);
    
        return 0;
}

全局变量

函数的调用

嵌套调用

//一连串的调用,最好将函数进行模块化

//三个数求最大数和最小数的差值
#include <stdio.h>
#include <stdlib.h>

int dist(int a,int b,int c)
{
        return max(a,b,c) - min(a,b,c);
}

max(int a,int b,int c)
{
        int  tmp;
        tmp = a > b ? a : b;
        return tmp > c ? tmp  : c;

}

min(int a,int b,int c)
{
        int tmp;
        tmp = a < b ? a : b;
        return tmp < c ? tmp : c;
}

int main()
{
        int a = 3, b = 5, c =10;
        int res;

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

        return 0;

}

递归调用

面试常考

使用小心

//存储结构,问题的处理,可抽象为一个公式时使用此种调用
//一个函数直接或间接的调用自身

//条件一层一层调用

#include <stdio.h>
#include <stdlib.h>

void c(void)
{
        printf("[%s]begin!\n",__FUNCTION__);
        printf("[%s]end!\n",__FUNCTION__);
}

void b(void)
{
        printf("[%s]begin!\n",__FUNCTION__);
        printf("[%s]call c()!\n",__FUNCTION__);
        c();
        printf("[%s]c() returned!\n",__FUNCTION__);
        printf("[%s]end!\n",__FUNCTION__);
        return 0;
}

void a(void)
{
        printf("[%s]begin!\n",__FUNCTION__);
        printf("[%s]call b()!\n",__FUNCTION__);
        b();
        printf("[%s]b() returned!\n",__FUNCTION__);
        printf("[%s]end!\n",__FUNCTION__);
        
}

int main()
{
        printf("[%s]begin!\n",__FUNCTION__);
        printf("[%s]call a()!\n",__FUNCTION__);
        a();
        printf("[%s]a() returned!\n",__FUNCTION__);
        printf("[%s]end!\n",__FUNCTION__);
        return 0;
}
//打印结果
[main]begin!
[main]call a()!
[a]begin!
[a]call b()!
[b]begin!
[b]call c()!
[c]begin!
[c]end!
[b]c() returned!
[b]end!
[a]b() returned!
[a]end!
[main]a() returned!
[main]end!

练习题

求一个数的阶乘

#if 0
fun(3) -> 3  *  fun(2)
    fun(2)  -> 2 * fun(1)
    fun(1) -> 1

n! = n * (n-1)!
    (n-1)! = (n-1) * (n-2)!
    ···

#endif

#include <stdio.h>
#include <stdlib.h>

int func(int n)
{
        if(n < 0)
                return -1;

        if(n == 0 || n == 1)
                return 1;

        return n *func(n-1);
}

int main()
{
        int n;
        int res;

        scanf("%d",&n);

        res =  func(n);
        printf("%d! = %d\n",n,res);

        return  0;
}

求斐波那契数列

#include <stdio.h>
#include <stdlib.h>

//1,1,2,3,5,8,13,21,34,55,89.....
//n = (n - 1)  + (n-2) 
//n-1 = (n-1-1) + (n -1-2)
//n-2 = (n-2-1) + (n -2-2)
//1 = 1;2 = 1;

int fib(int n)
{
        if(n < 1)
                return -1;
        if(n == 1 || n == 2)
                return 1;
        return fib(n-1) + fib(n-2);
}

int main()
{

        int n;
        int res;

        scanf("%d",&n);

        res = fib(n);
        printf("fib[%d] = %d\n",n,res);

        return 0;
}

汉诺塔盘

/*有三根柱子:它们分别称为起始柱、辅助柱和目标柱。
有一组圆盘:每个圆盘的大小都不相同,以整圆的形式叠成一个塔,放在起始柱上。
移动规则:
每次只能移动一个圆盘。
每次移动都必须将一个圆盘从塔顶移动到另一根柱子的塔顶。
不允许将一个较大的圆盘压在一个较小的圆盘上面。
*/  

#include <stdio.h>
#include <stdlib.h>

int hlt(int n)
{
    if(n < 1)
        return  -1;
    if(n == 1)
        return 1;
    return  2 * hlt (n-1) + 1;
}
    
int main()
{
    int n;
    int res;
    
    scanf("%d",&n);

    res = hlt(n);
    printf("hlt[%d] = %d\n",n,res);
    
    return 0;
}

函数与数组

#include <stdio.h>
#include <stdlib.h>

//void print_arr(int *p,int n)
void print_arr(int p[],int n)
{
        int i;
        printf("%s:%d\n",__FUNCTION__,sizeof(p));
 
        for(i = 0; i < n;i++)
                printf("%d",p[i]);
        printf("\n");
}

int main(int argc,char **argv)
{
        int a[] = {1,3,5,7,9};

        printf("%s:%d\n",__FUNCTION__,sizeof(a));
        print_arr(a,sizeof(a)/sizeof(*a));

        exit(0);
}
//逆序存放指针或数组
void func(int *p,int n)
{
        int i  = 0,j,m,tmp;

        m = (n-1)/2;
        
        for(; i <= m; i++)
        {
                j = n - 1 - i;
                tmp = p[i];
                p[i] = p[j];
                p[j] = tmp;

        }
}

int main(int argc,char **argv)
{
       int i;
        int a[] = {1,3,5,7,9};

        for(i=0; i < sizeof(a)/sizeof(*a);i++)
                printf("%d",a[i]);
        printf("\n");

        func(a,sizeof(a)/sizeof(*a));//逆序存放;

        for(i=0; i < sizeof(a)/sizeof(*a);i++)
                printf("%d",a[i]);
        printf("\n");

        exit(0);
}

二维数组

/*
*  int a[M][N] = {...};
*  int *p = *a;
*  int *q[N] = a;
*
*->  a[i][j]		*(a+i)+j	a[i]+j		p[i]	*p
*    q[i][j]		*q			q			p+3		q+2
*
*->	  int			int *		int *		int		int
*	  int			int *		int(*)[N]	int *	int (*)[N]
*/

#include <stdio.h>
#include <stdlib.h>

#define M       3
#define N       4

void print_arr(int *p,int n)
{
        int i;
        for(i = 0; i < n; i++)
        {
                printf("%d",p[i]);
        }
        printf("\n");
}

//void print_arr1(int (*p)[N],int m,int n)
void print_arr1(int p[][N],int m,int n)
{
        int  i,j;
        printf("sizeof(p) = %d\n",sizeof(p));
        for(i = 0; i < m; i ++)
        {
                for(j = 0; j < n; j++)
//                        printf("%4d",*(*(p+i)+j));
                        printf("%4d",p[i][j]);
                printf("\n");
        }
}

float average_score(int *p,int n)
{
        float sum = 0;
        int i;

        for(i = 0; i < n; i++)
                sum += p[i];
        return sum/n;
}

find_num(int (*p)[N], int num)
{
        int i;
        for(i = 0; i < N;i++)
            printf("%d", *(*(p+num)+i));
        printf("\n");
}

int main()
{
        int i,j;
        int a[M][N] = {1,2,3,4,5,6,7,8,9,10,11,12};
        float ave;
        int num = 0;

        //求十二个数的平均值,查看指定的某一个值

        ave = average_score(*a,M*N);
        printf("ave = %f\n",ave);

        find_num(a,num);

//        print_arr(&a[0][0],M*N);

//        printf("sizeof(a) = %d\n",sizeof(a));
//        print_arr1(a,M,N);

        exit(0);

}

字符数组

#include <stdio.h>
#include <stdlib.h>

char *mystrcpy(char *dest, const char *src)
{
        char *ret = dest;
        if(dest != NULL && src != NULL)
            while((*dest++ = *src++) != '\0');
        return ret;
}

char *mystrncpy(char *dest, const char *src, size_t n)
{
        int i;
        
        for(i = 0; i < n && (dest[i] = src[i]); i++);
        
        for(;i < n; i++)
            dest[i] = '\0';
        
        return dest;
}

int main()
{
        char str1[] = "helloworld";
        char str2[128];

//        mystrcpy(str2,str1);

        mystrncpy(str2,str1,5);
        puts(str2);

        exit(0);
}

函数与指针

指针函数

//返回值是指针 * 函数名 (形参)
//如:int * fun(int);
//某一个函数值为指针

int *find_num(int (*p)[N],int num)
{
        if(num > M-1)
                return NULL;
        return *(p + num);
}

int main()
{
        int i,j;
        int a[M][N] = {1,2,3,4,5,6,7,8,9,10,11,12};
        float ave;
        int num = 2;
        int *res;

        ave = average_score(*a,M*N);
        printf("ave = %f\n",ave);

        res = find_num(a,num);
        if(res != NULL)
        {
                for(i = 0; i < N; i++)
                        printf("%d",res[i]);
                printf("\n");
        }
        else
        {
                printf("Can not find!\n");
        }

        exit(0);

}

函数指针

//一个指针指向的是函数 (定义一个指针指向函数类型)
//定义形式  类型 (*指针名) (形参)
//如:int (*p)(int);

#include <stdio.h>
#include <stdlib.h>

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

int sub(int a,int b)
{
        return a-b;
}

int main()
{
        int a = 3,b = 5;
        int ret;
        int (*p)(int,int);
        int (*q)(int,int);

        p = add;
        q = sub;

//        ret = add(a,b);

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

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

        exit(0);
}

函数指针数组

//类型 (*数组名 【下标】) (形参)
//    如:int(*arr[N])(int);

#include <stdio.h>
#include <stdlib.h>

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

int sub(int a,int b)
{
        return a-b;
}

int main()
{
        int a = 3,b = 5;
        int ret,i;
        int (*funcp[2]) (int ,int);
    
        funcp[0] = add;
        funcp[1] = sub;

        for(i = 0; i < 2; i++)
        {
                ret = funcp[i](a,b);
                printf("%d\n",ret);
        }

        exit(0);
}

指向指针函数的函数指针数组

int  *(*funcp[N])(int)

构造类型

结构体

产生及意义

将不同的数据类型存放在一块相同的空间

类型描述

struct 结构体名
{
    //类型描述只是在描述里面有哪些类型的数字等,但不占空间
    数据类型 成员1;
    数据类型 成员2;
};  //分号很重要

//无头结构体
struct
{
        int i;
        char ch;
        float f;
}a = {,,},b = {, ,},c ,*p,*q;

嵌套定义

struct birthday_st
{
        int year;
        int month;
        int day;
};

struct student_st
{
        int id;
        char name[NAMESIZE];
        struct birthday_st birth;
        int math;
        int chinese;
};
//另一种写法
struct student_st
{
        int id;
        char name[NAMESIZE];
        struct birthday_st
		{
        	int year;
        	int month;
        	int day;
		};
        int math;
        int chinese;
};

定义变量

  • 变量,数组,指针

  • 初始化及成员引用

    • 成员引用:变量名.成员名

      • 指针 -> 成员名

      • (*指针).成员名

#include <stdio.h>
#include <stdlib.h>

#define NAMESIZE        40

//把结构体定义在函数外
struct simp_st
{
        int i;
        float f;
        char ch;
};

struct birthday_st
{
        int year;
        int month;
        int day;
};

struct student_st
{
        int id;
        char name[NAMESIZE];
        struct birthday_st birth;
        int math;
        int chinese;
};


int main()
{
        int i;
        //TYPE NAME = VALUE;
/*
        struct simp_st a = {123,456.789,'a'};
        a.i = 112233;
        printf("%d %f %c\n",a.i,a.f,a.ch);
*/

        struct student_st stu = {10011,"Alan",{2011,11,11},98,97};
        struct student_st *p = &stu;
        struct student_st arr[2] = {{10011,"Alan",{2011,11,11},98,97},{10012,"John",{2012,12,12},90,80}};

        p = &arr[0];
//        struct student_st = {.math =98, .chinese = 97};

//        printf("%d %s %d %d %d %d %d\n ",stu.id,stu.name,stu.birth.year,stu.birth.month,stu.birth.day,stu.math,stu.chinese);
        for(i=0;i<2;i++,p++)//p++ = p+1;
        {
            printf("%d %s %d %d %d %d %d\n",p->id,p->name,p->birth.year,p->birth.month,p->birth.day,p->math,p->chinese);
        }
        exit(0);
}

占用内存空间大小

struct simp_st
{
        int i;
        char ch;
        float f;
//        char ch1;
}__attribute__((packed));//不考虑地址对齐

int main()
{
        struct simp_st a;
        struct simp_st *p = &a;

        printf("sizeof(point) = %d\n",sizeof(p));
        printf("sizeof(struct) = %d\n",sizeof(a));
}

函数传参(值,地址)

        func(a);
//      func(a.i,a.ch,a.f);//传参的开销很大,占用空间很大;

        func(p);    //func(&a);
func(struct simp_st b)
{
        printf("%d\n",sizeof(b));
}

int main()
{
        //TYPE NAME = VALUE;
        struct simp_st a;
        struct simp_st *p = &a;

//        func(a)->func(a.i,a.ch,a.f);//传参的开销很大,占用空间很大;

        func(p);    //func(&a);

微型学生管理系统

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define NAMESIZE        32

struct student_st
{
        int id;
        char name[NAMESIZE];
        int math;
        int chinese;
};

void stu_set(struct student_st *p,const struct student_st *q)
{
        *p = *q;
}

void stu_show(struct student_st *p)
{
        printf("%d %s %d %d\n",p->id,p->name,p->math,p->chinese);
}

void stu_changename(struct student_st  *p,const char *newname)
{
        strcpy(p->name,newname);
}

void menu(void)
{
        printf("1 set\n2 change name\n3 show\n");
        printf("please enter the num:(q for quit):");
}

int main()
{
        struct student_st stu,tmp;
        char newname[NAMESIZE];
        int choice;
        int ret;

        do
        {
                menu();
                ret = scanf("%d",&choice);
                if(ret != 1)
                        break;

                switch(choice)
                {
                        case 1:
                                printf("Please enter for the stu[id name math chinese]:");
                                scanf("%d%s%d%d",&tmp.id,tmp.name,&tmp.math,&tmp.chinese);
                                stu_set(&stu,&tmp);
                                break;
                        case 2:
                                printf("please enter the name:");
                                scanf("%s",newname);
                                stu_changename(&stu, newname);
                                break;
                        case 3:
                                stu_show(&stu);
                                break;
                        default:
                                exit(1);

                }
                sleep(1);
        }while(1);

        exit(0);
}

共用体

产生及意义

可以提供多种选项,但同一时刻只能有一个选项产生

只有一个是有效的

类型描述

union 共用体名
{
    数据类型 成员名1;
    数据类型 成员名2;
    ·····
};

嵌套定义

union
{
        struct
        {
                uint16_t i;
                uint16_t j;
        }x;
        uint32_t y;
}a;

int main()
{
        a.y = 0x11223344;
        printf("%x\n",a.x.i + a.x.j);


//        uint32_t i = 0x11223344;
//        printf("%x\n",(i >> 16) + i & 0xFFFF);

        exit(0);
}

定义变量

(变量,数组,指针),初始化及成员引用

成员引用:

变量名.成员名

指针名->成员名

#include <stdio.h>
#include <stdlib.h>

union test_un
{
        int i;
        float f;
        char ch;
};

int main()
{
        union test_un a;
        union test_un *p = &a;
        union test_un arr[3];
  
        p->f = 345.678;
//        a.f = 345.678;

        printf("%d\n",sizeof(a));
//        printf("%f\n",a.f);
//        printf("%d\n",a.i);
        printf("%c\n",a.ch);

        exit(0);
}

占用内存大小

根据内部占用内存最大的成员大小所决定

函数传参(值,地址)

和结构体一样

位域

#include <stdio.h>
#include <stdlib.h>

union
{
        struct
        {
                char a:1;
                char b:2;
                char c:1;
        }x;
        char y;
}w;

int main()
{
        w.y = 6;
        printf("%d\n",w.x.b);
        exit(0);
}

枚举

有限的情况和数量

把会出现的n种状态罗列在一起

相当于多数量的宏

enum  标识符
{
    成员1;
    成员2;
    ....
};
#include <stdio.h>
#include <stdlib.h>

enum day
{
        MON = 1,
        TUS,
        THR,
        WES,
        FRI = 1,
        SAT,
        SUN
};

enum
{
        STATE_RUNNING = 1,
        STATE_CANCELED,
        STATE_OVER
};

struct job_st
{
        int id;
        int  state;
        time_t start,end;
};

int main()
{
        struct  job_st job1;
        //获取任务状态
        switch(job1.state)
        {
                case STATE_RUNNING:
                        break;
                case STATE_CANCELED:
                        break;
                case STATE_OVER:
                        break;
                default:
                        abort();

        }
        /*
        enum day a = FRI;
        a = SUN;
        printf("%d\n",a);
        */

        exit(0);
}

动态内存管理

四个函数

  • malloc

#include <stdio.h>
#include <stdlib.h>

int main()
{
        int *p;
        int i;
        int num = 5;
//变长数组实现
        p = malloc(sizeof(int) * num);

        for(i = 0; i <num ; i++)
                scanf("%d",&p[i]);
        for(i = 0; i < num; i++)
                printf("%d ",p[i]);
        printf("\n");

        exit(0);

}
#include <stdio.h>
#include <stdlib.h>

#if 0

void func(int **p,int  n)
{
        *p = malloc(n);
        if(*p == NULL)
                exit(1);
        return;
}
#else

void *func(int *p,int n)
{
        p = malloxc(n);
        if(p == NULL)
                exit(1);
        return p;
}

#endif

int main()
{
        int num = 100;
        int *p = NULL;

        p = func(p,num);
        free(p);

//        func(&p,num);
//        free(p);

        exit(0);
}
  • ralloc

  • realloc

    free

#include <stdio.h>
#include <stdlib.h>

int main()
{
        int *p = NULL;
        
        p = malloc(sizeof(int));
        if(p == NULL)
        {
                printf("malloc() error!\n");
                exit(1);
        }
        *p = 10;       
        printf("%p-->%d\n",*p,*p);

        free(p);//已经free后这块地址可能就已经分配给别人在使用了

        //free过后一定要立马把指针写为空
        p  = NULL;
        //这种错误非常危险
        *p = 123;
        printf("%p-->%d\n",*p,*p);

        exit(0);
}

动态内存管理

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define NAMEMAX     1024

struct student_st
{
        int id;
        char *name;
        int math;
        int chinese;
};

void stu_set(struct student_st *p,const struct student_st *q)
{
        p ->  id = q -> id;
//    	free(p->name);
        p -> name = malloc(strlen(q->name)+1);
        if(p->name == NULL)
        {
//            perror("malloc failed");//用于输出错误信息
                  exit(1);
        }
        
        strcpy(p -> name,q -> name);
        p->math = q -> math;
        p->chinese = q->chinese;
}

void stu_show(struct student_st *p)
{
        printf("%d %s %d %d\n",p->id,p->name,p->math,p->chinese);
}

void stu_changename(struct student_st  *p,const char *newname)
{
        free(p->name);
        p->name = malloc(strlen(newname)+1);
        strcpy(p->name,newname);
}

void menu(void)
{
        printf("1 set\n2 change name\n3 show\n");
        printf("please enter the num:(q for quit):");
}

int main()
{
        struct student_st stu,tmp;
        char newname[NAMEMAX];
        int choice;
        int ret;

        do
        {
                menu();
                ret = scanf("%d",&choice);
                if(ret != 1)
                        break;

                switch(choice)
                {
                        case 1:
                                tmp.name = malloc(NAMEMAX);
                                printf("Please enter for the stu[id name math chinese]:");
                                scanf("%d%s%d%d",&tmp.id,tmp.name,&tmp.math,&tmp.chinese);
                                stu_set(&stu,&tmp);
                                break;
                        case 2:
                                printf("please enter the name:");
                                scanf("%s",newname);
                                stu_changename(&stu, newname);
                                break;
                        case 3:
                                stu_show(&stu);
                                break;
                        default:
                                exit(1);

                }
                sleep(1);
        }while(1);

    //释放分配的内存
    	//free(stu.name);
    //free(tmp.name);//释放tmp.name的内存
    
        exit(0);
}

原则:谁申请谁释放,最好的办法让malloc和free放在一个 函数中

typedef

为已有的数据类型改名

typedef 已有的数据类型 新名字;

#include <stdio.h>
#include <stdlib.h>

typedef  int INT;

int  main()
{
        INT i = 100;
        printf("%d\n",i);
        exit(0);
}
#define INT int
typedef  int INT;
INT -i; --> int i;

#define  IP int*
typedef int *IP;

IP p,q ;  --> int *p,q;
IP p,q ; --> int *p,*q;

typedef int ARR[6];         int[6] -> ARR;
ARR  a; -->int a[6];

struct node_st
{
int i;
float f;
};
typedef struct  node_st NODE;
//更倾向于这种写法 
NODE a; -> struct node_st a;
NODE *p; --> struct node_st *p;

typedef struct node_st *NODEP
NODEP p; --> struct node_st *p;

typedef struct
{
int i;
float f;
}NODE,*NODEP;

typedef int FUNC(int);  ->  int(int)  FUNC;
FUNC  f;-->  int f(int);

typedef int  *FUNCP(int);

FUNCP p; --->  int *p(int);

typedef int *(*FUNCP)(int);
FUNCP p; --> int *(*p)(int);

make工程管理器

分清楚当前的依赖和被依赖关系

//main.c
    
#include <stdio.h>

#include "tool1.h"
#include "tool2.h"

int main()
{
        mytool1();
        mytool2();
        return 0;
}
//tool1.c
#include  <stdio.h>
#include "tool1.h"

void  mytool1()
{
        printf("tool1 print\n");
}
//tool2.c
#include  <stdio.h>
#include "tool2.h"

void  mytool2()
{
        printf("tool2 print\n");
}
//tool1.h
#ifndef TOOL1_H__
#define TOOL1_H__

void mytool1(void);

#endif

//tool2.h
#ifndef TOOL2_H__
#define TOOL2_H__

void mytool2(void);

#endif
//makefile
mytool: main.o tool1.o tool2.o
	gcc main.o tool1.o tool2.o -o mytool

main.o: main.c
	gcc -c main.c -Wall -g -o main.o

tool1.o: tool1.c
	gcc -c tool1.c -Wall -g -o tool1.o

tool2.o: tool2.c
	gcc -c tool2.c -Wall -g -o tool2.o


遇到的问题

总是出现"makefile:6: *** 缺失分隔符。 停止。"

解决方法:

查看自己的.vimrc文件

set expandtab
set softtabstop=4

含有这两行命令

set expandtab //会在vim插入制表符时使用空格代替
set softtabstop //设置制表符相当于4个空格,但因为开启了expandtab,导致制表符被替换为四个空格

而我原本的vim当中就含有

set tabstop=4 //一个制表符等于4个空格的宽度
set shiftwidth=4 //缩进层级的宽度为四个空格

所以删除之前的那两行代码后,makefile执行成功

如何查看自己的代码制表符或换行符被正确识别

cat -vet makefile

在终端中输入上述命令

^I --> 制表符

$ --> 换行符

//如输入上述命令后,终端显示为
mytool: main.o tool1.o tool2.o$
^Igcc main.o tool1.o tool2.o -o mytool$
$
main.o: main.c$
^Igcc -c main.c -Wall -g -o main.o$
$
tool1.o: tool1.c$
^Igcc -c tool1.c -Wall -g -o tool1.o$
$
tool2.o: tool2.c$
^Igcc -c tool2.c -Wall -g -o tool2.o$

推荐书籍

《GNU Make 使用手册(中译版)》

《跟我一起写 Makefile》 (PDF 重制版)作者: 陈皓

数据结构

线性:

  • 线性表

    • 顺序存储 arr

    • (有头还是无头) 链式存储 *

      • 单链表(面试易考)

        • 单项不循环

        • 单向循环链表

      • 双链表 (工作中常用)

        • 双向循环链表

        • 双向不循环链表

  • 栈(计算器的实现常用)

  • 队列

  • 存储形式

    • 树状存储

非线性:

  • 树(有向无环图)

    • 递归

推荐书籍

《编程之美》

《数据结构》严蔚敏

《算法导论》

顺序存储线性表

main.c

#include <stdio.h>
#include <stdlib.h>
#include "sqlist.h"

int main()
{
	int i,err;
        sqlist *list = NULL,*list1 = NULL;
        datatype arr[] = {12,23,34,45,56};
		datatype arr1[] = {89,90,78,67,56,45};

        list = sqlist_create();
//        sqlist_create1(&list);
        if(list == NULL)
        {
                fprintf(stderr,"sqlist_create() failed!\n");
                exit(1);
        }
		list1 = sqlist_create();
		if(list1 == NULL)
		{
			fprintf(stderr,"sqlist_create() failed!\n");
			exit(1);
		}


        for(i = 0; i<sizeof(arr)/sizeof(*arr);i++)
                if((err = sqlist_insert(list,0,&arr[i])) != 0)
                {
                        if(err == -1)
                                fprintf(stderr,"The arr is full.\n");
                        else if(err == -2)
                                fprintf(stderr,"the pos you want to insert is wrong.\n");
                        else
                                fprintf(stderr,"Error!\n");
                        exit(1);
                }

		sqlist_display(list);

		for(i = 0; i < sizeof(arr1)/sizeof(*arr1);i++)
			sqlist_insert(list1,0,&arr1[i]);
		sqlist_display(list1);

		sqlist_destroy(list);
		sqlist_destroy(list1);
		
    	sqlist_union(list,list1);
		sqlist_display(list);
    
#if 0
		sqlist_delete(list,1);
		/*if error*/
		sqlist_display(list);

        sqlist_destroy(list);
#endif
        exit(0);

}

sqlist.c

#include <stdio.h>
#include <stdlib.h>
#include "sqlist.h"

sqlist *sqlist_create()
{
        sqlist *me;
        me = malloc(sizeof(*me));
        if(me == NULL)
                return NULL;
        me -> last = -1;
        return me;
}
void sqlist_create1(sqlist **ptr)
{
        *ptr = malloc(sizeof(**ptr));
        if(*ptr == NULL)
                return ;
       
        (*ptr) -> last =-1;
        return ;
}
int sqlist_insert(sqlist *me,int i,datatype *data)
{
        int j;

        if(me->last == DATASIZE -1)
                return -1;
        if(i < 0 || i > me->last+1)
                return -2;

        for(j  = me->last; j >= i; --j)
                me->data[j+1] = me->data[j];
        me->data[i] = *data;
        me->last++;

        return 0;
}
int sqlist_delete(sqlist *me,int i)
{
	int  j;
	if(i < 0 || i > me->last)
		return -1;

	for(j = i+1;j <= me->last;j++)
		me->data[j-1] = me->data[j];

	me->last --;

	return 0;
}
int sqlist_find(sqlist *me,datatype *data)
{
	int i;
	if(sqlist_isempty(me) == 0)
		return -1;

	for(i = 0; i < me->last; i++)
		if(me->data[i] == *data)
			return i;
	return -2;
}
int sqlist_isempty(sqlist *me)
{
	if(me->last == -1)
		return 0;//空为0
	return -1;//非空为非0
}
int sqlist_setempty(sqlist *me)
{
	me->last = -1;
	return 0;
}
int sqlist_getnum(sqlist *me)
{
	return (me->last + 1);
}
void sqlist_display(sqlist *me)
{
	int i;
	if(me->last == -1)
		return ;

        for(i = 0; i<= me->last ;i++)
                printf("%d ",me->data[i]);
        printf("\n");
        return ;
}
int sqlist_destroy(sqlist *me)
{
	free(me);
	return 0;
}
int sqlist_union(sqlist *list1,sqlist *list2)
{
	//list1 -> 12 23 34 45 56
	//list2 -> 78 89 56 23 10

	//插入:尾部插入/首部插入

	int i = 0;
	for(i = 0; i <= list2->last;i++)
	{
		if(sqlist_find(list1,&list2->data[i]) < 0 )
		{
			sqlist_insert(list1,0,&list2->data[i]);
		}
	}
}

sqlist.h

#ifndef SQLIST_H__
#define SQLIST_H__

#define DATASIZE        1024
typedef int datatype;
typedef struct node_st
{
      datatype data[DATASIZE];
      int  last;
}sqlist;

sqlist *sqlist_create();
void sqlist_create1(sqlist **);

int sqlist_insert(sqlist *,int i,datatype *);

int sqlist_delete(sqlist *,int i);

int sqlist_find(sqlist *,datatype *);
int sqlist_isempty(sqlist *);
int sqlist_setempty(sqlist *);
int sqlist_getnum(sqlist *);

void sqlist_display(sqlist*);

int sqlist_destroy(sqlist *);
int sqlist_union(sqlist *,sqlist *);

#endif

makefile

all:main

main:main.o sqlist.o
	$(CC) $^ -o $@

clean:
	rm *.o main -rf

如果遇到段错误

在main.c输

printf("%d\n",__LINE__);

若能输出行号则无误,若不能输出则有误。

可以多处添加进行错误查找

链式存储

单向链表的实现

指针指向下一个数据的整体(包括数据域和指针域)

  • 有头单链表

  • 无头单链表

区别:是否存在头节点

  • 有头单链表

    • 只有一个指针,可访问性差,第一个节点永远不是有效节点

有头单链表

list.c

#include <stdio.h>
#include <stdlib.h>

#include "list.h"

list  *list_create()
{
	list *me;
	me = malloc(sizeof(*me));
	if(me == NULL)
		return NULL;
	me->next = NULL;
	return me;
}

int list_insert_at(list *me, int i, datatype *data)
{
	//don't move your "i"
	int j = 0;
	list *node = me,*newnode;

	if(i < 0)
		return -1;
		//return  -EINVAL;

	while(j < i && node != NULL)
	{
		node = node -> next;
		j++;
	}

	if(node)
	{
		newnode = malloc(sizeof(*newnode));
		if(newnode == NULL)
			return -2;
		newnode->data = *data;
//good habit:		newnode->next = NULL;

		newnode->next = node->next;
		node->next = newnode;
		return 0;
	}
	else
		return -3;

}

int list_order_insert(list *me,datatype *data)
{
	list *p = me,*q;

	while(p->next && p->next->data < *data)
		p = p->next;
	q = malloc(sizeof(*q));
	if(q == NULL)
		return -1;
	
	q->data = *data;
	q->next = p->next;
	p->next = q;

	return 0;
}

int list_delete_at(list *me,int i ,datatype *data)
{
	int j = 0;
	list *p = me,*q;

	*data = -1;

	if(i < 0)
		return -1;

	while(j < i && p)
	{
		p = p->next;
		j++;
	}

	if(p)
	{
		q = p->next;
		p->next = q->next;
		*data = q->data;
		free(q);
		q = NULL;
		return 0;
	}
	else
		return -2;
}

int list_delete(list *me,datatype *data)
{
	list *p = me,*q;

	while(p->next && p->next->data != *data)
		p = p->next;

	if(p->next == NULL)
		return -1;
	else
	{
		q = p->next;
		p->next = q->next;
		free(q);
		q = NULL;
	}
}

int list_isempty(list *me  )
{
	if(me->next == NULL)
		return 0;
	return 1;
}
void list_display(list *me)
{
	list *node = me->next;
	if(list_isempty(me) == 0)
		return ;
	while(node != NULL)
	{
		printf("%d  ",node -> data);
		node = node ->next;
	}
	printf("\n");
	return ;
}
void list_destroy(list *me)
{
	list *node,*next;

	for(node = me->next;node != NULL;node = next)
	{
		next = node->next;
		free(node);
	}
	free(me);
	return ;
}

list.h

#ifndef LIST_H__
#define LIST_H__

typedef int datatype;

typedef struct node_st
{
	datatype data;
	struct node_st *next;
}list;

list  *list_create();

int list_insert_at(list *, int i, datatype *);
int list_order_insert(list *,datatype *);

int list_delete_at(list *,int i ,datatype *);
int list_delete(list *,datatype *);

int list_isempty(list *);


void list_display(list *);
void list_destroy(list *);

#endif

main.c

#include <stdio.h>
#include <stdlib.h>

#include "list.h"

int main()
{
	list *l;
	int i;
	datatype arr[] = {12,9,23,2,34,6,45};
	
	l = list_create();
	if(l == NULL)
		exit(1);

	for(i = 0; i < sizeof(arr)/sizeof(*arr);i++)
	{
		if(list_order_insert(l,&arr[i]))
			exit(1);
	}

	list_display(l);
	
	int err;
	datatype value;
	err = list_delete_at(l,2,&value);
	if(err)
		exit(1);
	list_display(l);
	printf("delete:%d\n",value);


#if 0
	int value = 12;
	list_delete(l,&value);
	list_display(l);
#endif

	list_destroy(l);

	exit(0);
}

makefile

all:main

main:main.o list.o
	$(CC) $^ -o $@

clean:
	rm *.o main -rf
  • 无头节点

数组相当于一个指针常量,不能出现在等号的左边

one happy thing:I meet a 段错误 and but ai can't find what's wrong, hahaha~

then i tried to insert in the code printf("%d\n",__LINE__);,then even through I don't know what's thing happened but I repair the error :)

无头单链表

main.c

#include <stdio.h>
#include <stdlib.h>

#include "nohead.h"

int main()
{
	int i,ret;
	struct node_st *list = NULL; 
	struct score_st tmp;

	for(i = 0; i < 7; i ++)
	{
		tmp.id = i;
		snprintf(tmp.name,NAMESIZE,"stu%d",i);
		tmp.math = rand() % 100;
		tmp.chinese = rand() % 100;

		ret = list_insert(&list, &tmp);
		if(ret != 0)
			exit(1);
	}


	list_show(list);

	printf("\n");

	int id = 1;
	struct score_st *ptr;
	
	ptr = list_find(list,id);
	if(ptr == NULL)
		printf("Can not find!\n");
	else
		printf("%d %s %d %d\n",ptr->id,ptr->name,ptr->math,ptr->chinese);

//	list_delete(&list);
//	list_show(list);


	list_destroy(list);
	exit(0);
}

nohead.c

#include <stdio.h>
#include <stdlib.h>

#include "nohead.h"

int  list_insert(struct node_st **list,struct score_st *data)
{
	//head_insert
	struct node_st *new;

	new = malloc(sizeof(*new));
	if(new == NULL)
		return -1;
	
	new->data = *data;
	new->next = *list;
	*list = new;

	return 0;
}
void  list_show(struct node_st *list)
{
	struct node_st *cur;
	for(cur = list;cur != NULL;cur = cur ->next)
	{
		printf("%d %s %d %d\n",cur->data.id,cur->data.name,cur->data.math,cur->data.chinese);
	}
}

int list_delete(struct node_st **list)
{
	struct node_st *cur;
	if(*list == NULL)
		return -1;

	cur = *list;
	*list = (*list)->next;

	free(cur);
	return 0;
}

struct score_st * list_find(struct node_st *list,int id)
{
	struct node_st *cur;

	for(cur = list;cur != NULL;cur = cur ->next)
	{
		if(cur->data.id == id)
		{
			return &cur->data;
		}
	}

	return NULL;
}

void list_destroy(struct node_st *list)
{
	struct node_st *cur;
	if(list == NULL)
		return ;
	for(cur = list ;cur != NULL;cur = list)
	{
		list = cur->next;
		free(cur);
	}
}

nohead.h

#ifndef NOHEAD_H__
#define NOHEAD_H__

#define NAMESIZE	32

struct score_st
{
	int id;
	char name[NAMESIZE];
	int math;
	int chinese;
};

struct node_st
{
	struct score_st data;
	struct node_st *next;
};

int  list_insert(struct node_st **list,struct score_st *data);

void  list_show(struct node_st *);

int list_delete(struct node_st **);

struct score_st * list_find(struct node_st *,int id);

void list_destroy(struct node_st *);

#endif
有头无头单链表练习
有头

p1=5+2x+8x8+3x16

p2 = 6x + 16 x6 - 8x8

p = 5 +8x + 16x6+3x16

#include <stdio.h>
#include <stdlib.h>

struct node_st
{
	int coef;
	int exp;
	struct node_st *next;
};

struct node_st *poly_create(int a[][2],int n)
{
	int i;
	struct node_st *me;
	struct node_st *newnode,*cur;
	me = malloc(sizeof(*me));
	if(me == NULL)
		return NULL;
	me->next = NULL;

	cur = me;

	for(i = 0; i < n; i++)
	{
		newnode = malloc(sizeof(*newnode));
		if(newnode == NULL)
			return NULL;
		newnode->coef = a[i][0];
		newnode->exp = a[i][1];
		newnode->next = NULL;

		cur ->next = newnode;
		cur = newnode;
	}

	return me;
}

void poly_show(struct node_st *me)
{
	struct node_st *cur;
	for(cur = me->next;cur != NULL;cur = cur->next)
	{
		printf("(%d %d) ",cur->coef,cur->exp);
	}
	printf("\n");
}

void poly_union(struct node_st *p1,struct node_st *p2)
{
	struct node_st *p,*q,*r;
	//p -> p1,q -> p2
	p = p1->next;
	q = p2->next;
	r = p1;

	while(p && q)
	{
		if(p->exp < q ->exp)
		{
			r->next = p;
			r = p;
			p = p -> next;
		}
		else if(p ->exp > q->exp)
		{
			r ->next = q;
			r = q;
			q = q -> next;
		}
		else//p->exp = q->exp
		{
			p -> coef += q->coef;
			if(p->coef)
			{
				r->next = p;
				r = p;
			}
			p = p->next;
			q = q->next;
		}
	}
	
	if(p == NULL)
		r->next = q;
	else
		r->next = p;
}

int main()
{
	int a[][2]={{5,0},{2,1},{8,8},{3,16}};
	int b[][2]={{6,1},{16,6},{-8,8}};
	struct node_st *p1,*p2;
	
	//create
	p1 = poly_create(a,4);
	if(p1 == NULL)
		exit(1);
	p2 = poly_create(b,3);
	if(p2 == NULL)
		exit(1);

	poly_show(p1);
	poly_show(p2);

	poly_union(p1,p2);
	poly_show(p1);


	exit(0);
}

好高级啊·····,就这样就实现了 ?!

无头版

约瑟夫算法:(杀人游戏)/ n只猴子n-1只桃子

#include <stdio.h>
#include  <stdlib.h>

#define JOSE_NR		8

struct node_st
{
	int data;
	struct node_st *next;
};

struct node_st *jose_create(int n)
{
	struct node_st *me;
	struct node_st *newnode,*cur;
	int i = 1;

	me = malloc(sizeof(*me));
	if(me == NULL)
		return NULL;
	me->data = i;
	me->next = me;
	i++;

	cur = me;

	for(;i <= n; i++)
	{
		newnode = malloc(sizeof(*newnode));
		if(newnode == NULL)
			return NULL;
		newnode->data = i;
		newnode->next = me;

		cur -> next = newnode;
		cur = newnode;
	}

	return me;
}

void jose_show(struct node_st *me)
{
	struct node_st *list;
	for(list = me;list->next != me ;list = list->next)
	{
		printf("%d ",list->data);
	}
	printf("%d\n",list->data);
}

void jose_kill(struct node_st **me,int n)
{
	struct node_st *cur = *me,*node;
	int i = 1;

	while( cur != cur ->next)
	{
		while(i < n)
		{
			node = cur;
			cur = cur->next;
			i++;
		}

		printf("%d ",cur->data);
		node->next = cur ->next;
		free(cur);

		cur = node->next;
		i = 1;
   	}

	*me = cur;
	printf("\n");
}

int main()
{
	struct node_st *list;
	int n = 3;

	list = jose_create(JOSE_NR);
	if(list == NULL)
		exit(1);

	jose_show(list);

	jose_kill(&list,n);

	jose_show(list);


	exit(0);
}

双向循环链表

通用性很强

第一次没有设置边长(注释版本),第二次设置为变长

llist.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "llist.h"

LLIST *llist_create(int initsize)
{
	LLIST *new;
	
	new = malloc(sizeof(*new));
	if(new == NULL)
		return NULL;

	new->size = initsize;
//	new->head.data = NULL;
	new->head.prev = &new->head;
	new->head.next = &new->head;

	return new;
}

int llist_insert(LLIST *ptr,const void *data,int mode)
{
	struct llist_node_st *newnode;
//	newnode = malloc(sizeof(*newnode));
    newnode = malloc(sizeof(*newnode) + ptr -> size);
	if(newnode == NULL)
		return -1;

//	newnode->data = malloc(ptr->size);
//	if(newnode->data == NULL)
//		return -2;
	memcpy(newnode->data,data,ptr->size);
	if(mode == LLIST_FORWARD)
	{
		newnode -> prev = &ptr -> head;
		newnode -> next = ptr -> head.next;
	}
	else if(mode == LLIST_BACKWARD)
	{
		newnode -> prev =ptr -> head.prev;
		newnode -> next =&ptr -> head;
	}
	else		//error
	{
		return -3;
	}

	newnode -> prev -> next = newnode;
	newnode -> next -> prev = newnode;

	return 0;
}

static struct llist_node_st *find_(LLIST *ptr ,const void *key,llist_cmp *cmp)
{
	struct llist_node_st *cur;

	for(cur = ptr->head.next; cur != &ptr->head; cur = cur ->next)
	{
		if(cmp(key,cur->data)  == 0)
			break;
	}
	return cur;
}

void *llist_find(LLIST *ptr,const void *key,llist_cmp *cmp)
{
    struct llist_node_st *node;
    node = find_(ptr,key,cmp);
    if(node == &ptr->head)
        return  NULL;
    return node->data;
	//return find_(ptr,key,cmp)->data;
}

int llist_delete(LLIST *ptr,const void *key,llist_cmp *cmp)
{
	struct llist_node_st *node;

	node = find_(ptr,key,cmp);
	if(node == &ptr -> head)
		return -1;
	node->prev->next = node->next;
	node->next->prev = node->prev;
//	free(node->data);
	free(node);
	
	return 0;
}

int llist_fetch(LLIST *ptr,const void *key,llist_cmp *cmp,void *data)
{
	struct llist_node_st *node;

	node = find_(ptr,key,cmp);
	if(node == &ptr->head)
		return -1;
	node->prev->next = node->next;
	node->next->prev = node->prev;
	if(data != NULL)
		memcpy(data,node->data,ptr->size);
//	free(node->data);
	free(node);
	return 0;
}

void llist_travel(LLIST *ptr , llist_op *op)
{
	struct llist_node_st *cur;

	for(cur = ptr->head.next;cur != &ptr->head;cur = cur->next)
		op(cur->data);
	
}

void llist_destroy(LLIST *ptr)
{
	struct llist_node_st  *cur,*next;

	for(cur = ptr->head.next;cur != &ptr->head;cur = next)
	{
		next = cur ->next;
//		free(cur->data);
		free(cur);
	}
	free(ptr);
}

llist.h

#ifndef LLIST_H__
#define LLIST_H__

#define LLIST_FORWARD		1
#define LLIST_BACKWARD		2

typedef void llist_op(const void *);
typedef int llist_cmp(const void *,const void *);

struct llist_node_st
{
//	void *data;
	struct llist_node_st *prev;
	struct llist_node_st *next;
  	char data[1];  //c99支持data[0];
};

typedef struct 
{
	int size;
	struct llist_node_st head;
}LLIST;

LLIST *llist_create(int initsize);

int llist_insert(LLIST *,const void *data,int mode);

void *llist_find(LLIST *,const void *key,llist_cmp *);

int llist_delete(LLIST *,const void *key,llist_cmp *);

int llist_fetch(LLIST *,const void *key,llist_cmp *,void *data);

void llist_travel(LLIST *,llist_op *);

void llist_destroy(LLIST *);

#endif

main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include  "llist.h"

#define NAMESIZE 	32

struct score_st
{
	int id;
	char name[NAMESIZE];
	int math;
	int chinese;
};

static void print_s(const void *record)
{
	const struct score_st *r = record;

	printf("%d %s %d %d\n",r->id,r->name,r->math,r->chinese);
}

static int id_cmp(const void *key,const void *record)
{
	const int *k = key;
	const struct score_st *r = record;

	return (*k - r->id);
}

static int name_cmp(const void *key,const void *record)
{
	const char *k = key;
	const struct score_st *r = record;

	return strcmp(k,r->name);
}


int main()
{
	int i , ret;
	LLIST *handler;
	struct  score_st tmp;

	handler = llist_create(sizeof(struct score_st));
	if(handler  == NULL)
		exit(1);

	for(i = 0; i < 7; i++)
	{
		tmp.id = i;
		snprintf(tmp.name,NAMESIZE,"std%d",i);
		tmp.math = rand()%100;
		tmp.chinese = rand()%100;

		ret = llist_insert(handler,&tmp,LLIST_BACKWARD);
		if(ret)
			exit(1);
	}

	llist_travel(handler,print_s);

	printf("\n\n");

	char *del_name = "std6";
	ret = llist_delete(handler,del_name,name_cmp);
	if(ret)
		printf("llist_deleter failed!\n");
	llist_travel(handler,print_s);

#if 0
	int id = 30;
	struct score *data;

	data = llist_find(handler,&id,id_cmp);
	if(data == NULL)
		printf("Can not find!\n");
	else
		print_s(data);
#endif

	llist_destroy(handler);
	exit(0);
}

Makefile

all:llist
	
llist:llist.o main.o
	$(CC) $^ -o $@

clean:
	rm llist *.o -rf
面向对象的封装

llist.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "llist.h"

int llist_insert(LLIST *,const void *data,int mode);
void *llist_find(LLIST *,const void *key,llist_cmp *);
int llist_delete(LLIST *,const void *key,llist_cmp *);
int llist_fetch(LLIST *,const void *key,llist_cmp *,void *data);
void llist_travel(LLIST *,llist_op *);

LLIST *llist_create(int initsize)
{
	LLIST *new;
	
	new = malloc(sizeof(*new));
	if(new == NULL)
		return NULL;

	new->size = initsize;
	new->head.prev = &new->head;
	new->head.next = &new->head;

	new->insert = llist_insert;
	new->delete = llist_delete;
	new->find = llist_find;
	new->fetch = llist_fetch;
	new->travel = llist_travel;

	return new;
}

int llist_insert(LLIST *ptr,const void *data,int mode)
{
	struct llist_node_st *newnode;
	newnode = malloc(sizeof(*newnode) + ptr->size);
	if(newnode == NULL)
		return -1;

	memcpy(newnode->data,data,ptr->size);

	if(mode == LLIST_FORWARD)
	{
		newnode -> prev = &ptr -> head;
		newnode -> next = ptr -> head.next;
	}
	else if(mode == LLIST_BACKWARD)
	{
		newnode -> prev =ptr -> head.prev;
		newnode -> next =&ptr -> head;
	}
	else		//error
	{
		return -3;
	}

	newnode -> prev -> next = newnode;
	newnode -> next -> prev = newnode;

	return 0;
}

static struct llist_node_st *find_(LLIST *ptr ,const void *key,llist_cmp *cmp)
{
	struct llist_node_st *cur;

	for(cur = ptr->head.next; cur != &ptr->head; cur = cur ->next)
	{
		if(cmp(key,cur->data)  == 0)
			break;
	}
	return cur;
}

void *llist_find(LLIST *ptr,const void *key,llist_cmp *cmp)
{
	struct llist_node_st *node;
	node = find_(ptr,key,cmp);
	if(node == &ptr->head)
		return NULL;
	return node->data;
}

int llist_delete(LLIST *ptr,const void *key,llist_cmp *cmp)
{
	struct llist_node_st *node;

	node = find_(ptr,key,cmp);
	if(node == &ptr -> head)
		return -1;
	node->prev->next = node->next;
	node->next->prev = node->prev;
	free(node);
	
	return 0;
}

int llist_fetch(LLIST *ptr,const void *key,llist_cmp *cmp,void *data)
{
	struct llist_node_st *node;

	node = find_(ptr,key,cmp);
	if(node == &ptr->head)
		return -1;
	node->prev->next = node->next;
	node->next->prev = node->prev;
	if(data != NULL)
		memcpy(data,node->data,ptr->size);
	free(node);
	return 0;
}

void llist_travel(LLIST *ptr , llist_op *op)
{
	struct llist_node_st *cur;

	for(cur = ptr->head.next;cur != &ptr->head;cur = cur->next)
		op(cur->data);
}

void llist_destroy(LLIST *ptr)
{
	struct llist_node_st  *cur,*next;

	for(cur = ptr->head.next;cur != &ptr->head;cur= next)
	{
		next = cur ->next;
		free(cur);
	}
	free(ptr);
}



llist.h

#ifndef LLIST_H__
#define LLIST_H__

#define LLIST_FORWARD		1
#define LLIST_BACKWARD		2

typedef void llist_op(const void *);
typedef int llist_cmp(const void *,const void *);

struct llist_node_st
{	
	struct llist_node_st *prev;
	struct llist_node_st *next;
	char data[1];//only c99 can [0]

};

typedef struct llist_head
{
	int size;
	struct llist_node_st head;
	int (*insert)(struct llist_head *,const void *,int);
	void *(*find)(struct llist_head *,const void *,llist_cmp *);
	int (*delete)(struct llist_head *,const void *,llist_cmp *);
	int (*fetch)(struct llist_head *,const void *,llist_cmp *,void *);
	void (*travel)(struct llist_head *,llist_op *);
}LLIST;

LLIST *llist_create(int initsize);
void llist_destroy(LLIST *);

#endif

main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include  "llist.h"

#define NAMESIZE 	32

struct score_st
{
	int id;
	char name[NAMESIZE];
	int math;
	int chinese;
};

static void print_s(const void *record)
{
	const struct score_st *r = record;

	printf("%d %s %d %d\n",r->id,r->name,r->math,r->chinese);
}

static int id_cmp(const void *key,const void *record)
{
	const int *k = key;
	const struct score_st *r = record;

	return (*k - r->id);
}

static int name_cmp(const void *key,const void *record)
{
	const char *k = key;
	const struct score_st *r = record;

	return strcmp(k,r->name);
}


int main()
{
	int i , ret;
	LLIST *handler;
	struct  score_st tmp;

	handler = llist_create(sizeof(struct score_st));
	if(handler  == NULL)
		exit(1);

	for(i = 0; i < 7; i++)
	{
		tmp.id = i;
		snprintf(tmp.name,NAMESIZE,"std%d",i);
		tmp.math = rand()%100;
		tmp.chinese = rand()%100;

		ret = handler->insert(handler,&tmp,LLIST_BACKWARD);
		if(ret)
			exit(1);
	}
	handler->travel(handler,print_s);

#if 0
	printf("\n\n");

	char *del_name = "std6";
	ret = llist_delete(handler,del_name,name_cmp);
	if(ret)
		printf("llist_deleter failed!\n");
	llist_travel(handler,print_s);

	int id = 30;
	struct score *data;

	data = llist_find(handler,&id,id_cmp);
	if(data == NULL)
		printf("Can not find!\n");
	else
		print_s(data);
#endif

	llist_destroy(handler);
	exit(0);
}

内核双向链表

list.h

#ifndef LINUX_LIST_H__
#define LINUX_LIST_H__

struct list_head
{
	struct list_head *prev;
	struct list_head *next;
};

#define LIST_HEAD_INIT(name)	{&(name),&(name)}

#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name)

static inline void __list_add(struct list_head *new,struct list_head *prev,struct list_head *next)
{
	next->prev = new;
	new->next = next;
	new->prev = prev;
	prev->next = new;
}

static inline void list_add(struct list_head *new,struct list_head *head)
{
	__list_add(new,head,head->next);
}

#define __list_for_each(pos,head) \
	for (pos = (head)->next;pos != (head);pos = pos->next)

//ptr->cur;
//type->struct score_st;
//member->node

#define offsetof(TYPE,MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

#define container_of(ptr,type,member)\
	({	(type *)( (char *)ptr - offsetof(type,member) );})

#define list_entry(ptr,type,member) \
	container_of(ptr,type,member)

#endif

main.c

#include <stdio.h>
#include <stdlib.h>

#include "list.h"

#define NAMESIZE	32

struct score_st
{
	int id;
	char name[NAMESIZE];
	struct list_head node;
	int math;
	int chinese;
};

static void print_s(struct  score_st *d)
{
	printf("%d %s %d %d\n",d->id,d->name,d->math,d->chinese);
}

int main()
{
	int i;
	struct score_st *datap;
	struct list_head *cur;

	LIST_HEAD(head);

	for(i = 0; i < 7;i++)
	{
		datap = malloc(sizeof(*datap));
		if(datap == NULL)
			exit(1);

		datap->id = i;
		snprintf(datap->name,NAMESIZE,"stu%d",i);
		datap->math = rand()%100;
		datap->chinese = rand()%100;

		list_add(&datap->node,&head);

	}

	__list_for_each(cur,&head)
	{
		datap = list_entry(cur,struct score_st,node);
		print_s(datap);
	}

	__list_for_each(cur,&head)
	{
		datap =  list_entry(cur,struct score_st,node);
		if(datap->id == 15)
			break;
	}

	if(cur == &head)
		printf("Can not find!\n");
	else
		print_s(datap);

	exit(0);
}

顺序栈

main.c

#include <stdio.h>
#include <stdlib.h>

#include "sqstack.h"

int main()
{
	datatype arr[] = {19,23,0,45,67};
	sqstack *st;
	int i,ret;

	st = st_create();
	if(st == NULL)
		exit(1);
	for(i = 0;i<sizeof(arr)/sizeof(*arr);i++)
		st_push(st,&arr[i]);
	
	st_travel(st);

	datatype tmp;
	while(st_pop(st,&tmp) == 0)
	{
		printf("POP:%d\n",tmp);
	}

/*	
	datatype tmp = 1;
	ret = st_push(st,&tmp);
	if(ret != 0)
		printf("st_push failed.\n");
	else
		st_travel(st);

	st_destroy(st);
*/
	exit(0);
}

sqstack.c

#include <stdio.h>
#include <stdlib.h>

#include "sqstack.h"

sqstack *st_create(void)
{
	sqstack *st;
	st = malloc(sizeof(*st));
	if(st == NULL)
		return NULL;
	st->top = -1;
	return  st;
}

int st_isempty(sqstack *st)
{
	return  (st->top == -1);
}

int st_push(sqstack *st,datatype *data)
{
	if(st->top == MAXSIZE - 1)
		return -1;

	st->data[++st->top] = *data;
	return 0;
}

int st_pop(sqstack *st,datatype *data)
{
	if(st_isempty(st))
		return -1;
	*data = st -> data[st->top--];
	return 0;
}

int st_top(sqstack *st,datatype *data)
{
	if(st_isempty(st))
		return -1;
	*data = st->data[st->top];
	return 0;
}

void st_travel(sqstack *st)
{
	int i;

	if(st_isempty(st))
		return ;
	for(i = 0; i <= st->top; i++)
		printf("%d ",st->data[i]);
	printf("\n");
}

void st_destroy(sqstack *st)
{
	free(st);
}

sqstack.h

#ifndef SQSTACK_H__
#define SQSTACK_H__

#define MAXSIZE		5

typedef int datatype;

typedef struct node_st
{
	datatype data[MAXSIZE];
	int top;
}sqstack;

sqstack *st_create(void);

int st_isempty(sqstack *);

int st_push(sqstack *,datatype *);

int st_pop(sqstack *,datatype *);

int st_top(sqstack *,datatype *);

void st_travel(sqstack *);

void st_destroy(sqstack *);

#endif

空间太过固定是顺序存储的一大固有缺点

链式栈

对库进行二次封装

llist.h

#ifndef LLIST_H__
#define LLIST_H__

#define LLIST_FORWARD		1
#define LLIST_BACKWARD		2

typedef void llist_op(const void *);
typedef int llist_cmp(const void *,const void *);

struct llist_node_st
{
	struct llist_node_st *prev;
	struct llist_node_st *next;
  	char data[1];  
};

typedef struct 
{
	int size;
	struct llist_node_st head;
}LLIST;

LLIST *llist_create(int initsize);

int llist_insert(LLIST *,const void *data,int mode);

void *llist_find(LLIST *,const void *key,llist_cmp *);

int llist_delete(LLIST *,const void *key,llist_cmp *);

int llist_fetch(LLIST *,const void *key,llist_cmp *,void *data);

void llist_travel(LLIST *,llist_op *);

void llist_destroy(LLIST *);

#endif

llist.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "llist.h"

LLIST *llist_create(int initsize)
{
	LLIST *new;
	
	new = malloc(sizeof(*new));
	if(new == NULL)
		return NULL;

	new->size = initsize;
	new->head.prev = &new->head;
	new->head.next = &new->head;

	return new;
}

int llist_insert(LLIST *ptr,const void *data,int mode)
{
	struct llist_node_st *newnode;
    newnode = malloc(sizeof(*newnode) + ptr -> size);
	if(newnode == NULL)
		return -1;
    
	memcpy(newnode->data,data,ptr->size);
	if(mode == LLIST_FORWARD)
	{
		newnode -> prev = &ptr -> head;
		newnode -> next = ptr -> head.next;
	}
	else if(mode == LLIST_BACKWARD)
	{
		newnode -> prev =ptr -> head.prev;
		newnode -> next =&ptr -> head;
	}
	else	
	{
		return -3;
	}

	newnode -> prev -> next = newnode;
	newnode -> next -> prev = newnode;

	return 0;
}

static struct llist_node_st *find_(LLIST *ptr ,const void *key,llist_cmp *cmp)
{
	struct llist_node_st *cur;

	for(cur = ptr->head.next; cur != &ptr->head; cur = cur ->next)
	{
		if(cmp(key,cur->data)  == 0)
			break;
	}
	return cur;
}

void *llist_find(LLIST *ptr,const void *key,llist_cmp *cmp)
{
    struct llist_node_st *node;
    node = find_(ptr,key,cmp);
    if(node == &ptr->head)
        return  NULL;
    return node->data;
}

int llist_delete(LLIST *ptr,const void *key,llist_cmp *cmp)
{
	struct llist_node_st *node;

	node = find_(ptr,key,cmp);
	if(node == &ptr -> head)
		return -1;
	node->prev->next = node->next;
	node->next->prev = node->prev;
	free(node);
	
	return 0;
}

int llist_fetch(LLIST *ptr,const void *key,llist_cmp *cmp,void *data)
{
	struct llist_node_st *node;

	node = find_(ptr,key,cmp);
	if(node == &ptr->head)
		return -1;
	node->prev->next = node->next;
	node->next->prev = node->prev;
	if(data != NULL)
		memcpy(data,node->data,ptr->size);
	free(node);
	return 0;
}

void llist_travel(LLIST *ptr , llist_op *op)
{
	struct llist_node_st *cur;

	for(cur = ptr->head.next;cur != &ptr->head;cur = cur->next)
		op(cur->data);
	
}

void llist_destroy(LLIST *ptr)
{
	struct llist_node_st  *cur,*next;

	for(cur = ptr->head.next;cur != &ptr->head;cur = next)
	{
		next = cur ->next;
        free(cur);
	}
	free(ptr);
}

stack.c

#include  <stdio.h>

#include "stack.h"

LLIST *stack_create(int initsize)
{
	return llist_create(initsize);
}
int stack_push(STACK *ptr,const void *data)
{
	return llist_insert(ptr,data,LLIST_FORWARD);
}

static int always_match(const void *p1,const void *p2)
{
	return 0;
}

int stack_pop(STACK *ptr,void *data)
{
	return llist_fetch(ptr,(void *)0,always_match,data);
}

void stack_destroy(STACK *ptr)
{
	llist_destroy(ptr);
}

stack.h

#ifndef STACK_H__
#define STACK_H__

#include "llist.h"

typedef LLIST STACK;

STACK *stack_create(int);

int stack_push(STACK *,const void *data);

int stack_pop(STACK *,void *data);

void stack_destroy(STACK *);

#endif

main.c

#include <stdio.h>
#include <stdlib.h>

#include "stack.h"

#define NAMESIZE	32

struct score_st
{
	int id;
	char name[NAMESIZE];
	int math;
	int chinese;
};

static void print_s(void *record)
{
	struct score_st *r  = record;
	printf("%d %s %d %d\n",r->id,r->name,r->math,r->chinese);
}

int main()
{
	STACK *st;
	struct  score_st tmp;
	int i,ret;

	st = stack_create(sizeof(struct score_st));
	if(st == NULL)
		exit(1);
	for(i = 0; i < 7; i++)
	{
		tmp.id = i;
		snprintf(tmp.name,NAMESIZE,"stu%d",i);
		tmp.math = rand()%100;
		tmp.chinese = rand()%100;

		if(stack_push(st,&tmp))
			exit(1);
	}

	while(1)
	{
		ret = stack_pop(st,&tmp);
		if(ret == -1)
			break;
		print_s(&tmp);
	}
	stack_destroy(st);

	exit(0);
}

队列

顺序存储队列的实现

main.c

#include <stdio.h>
#include <stdlib.h>

#include "queue.h"

int main()
{
	queue *sq;
	datatype arr[] = {2,34,98,12};
	int i;
	int ret;

	sq = qu_create();
	if(sq == NULL)
		exit(1);

	for(i = 0;i < sizeof(arr)/sizeof(*arr); i++)
		qu_enqueue(sq,&arr[i]);

	qu_travel(sq);

#if 0
	datatype tmp = 100;
	ret = qu_enqueue(sq,&tmp);
	if(ret == -1)
		printf("queue is full!\n");
	else
		qu_travel(sq);
#endif

	datatype tmp;
	qu_dequeue(sq,&tmp);
	printf("DEQUEUE:%d\n",tmp);

	qu_travel(sq);

	qu_destroy(sq);

	exit(0);
}

queue.c

#include <stdio.h>
#include <stdlib.h>

#include "queue.h"

queue *qu_create()
{
	queue *sq;

	sq = malloc(sizeof(*sq));
	if(sq  ==  NULL)
		return NULL;

	sq->head = 0;
	sq->tail = 0;

	return sq;
}

int qu_isempty(queue *sq)
{
	return (sq->head == sq->tail);
}

int qu_enqueue(queue *sq,datatype *x)
{
	if((sq->tail + 1) % MAXSIZE == sq -> head)
		return -1;

	sq -> tail = (sq->tail + 1) % MAXSIZE;
	sq -> data[sq->tail] = *x;
	return 0;
}

int qu_dequeue(queue *sq,datatype *x)
{
	if(qu_isempty(sq))
		return -1;

	sq->head = (sq -> head + 1) % MAXSIZE;
	*x = sq->data[sq->head];

	return 0;
}

void qu_travel(queue *sq)
{
	int i;
	if(sq->head == sq->tail)
		return ;

	i  = (sq->head + 1) % MAXSIZE;
	while(i != sq->tail)
	{
		printf("%d ",sq->data[i]);
		i = (i + 1) % MAXSIZE;
	}
	printf("%d\n",sq->data[i]);
}

void qu_clear(queue *sq)
{
	sq->head = sq->tail;
	
}

void  qu_destroy(queue *sq)
{
	free(sq);
}

queue.h

#ifndef QUEUE_H__
#define QUEUE_H__

typedef int datatype;

#define MAXSIZE		5

typedef struct node_st
{
	datatype data[MAXSIZE];
	int head,tail;
}queue;

queue *qu_create();

int qu_isempty(queue *);

int qu_enqueue(queue *,datatype *);

int qu_dequeue(queue *,datatype *);

void qu_travel(queue *);

void qu_clear(queue *);

void  qu_destroy(queue *);

#endif

链式存储队列的实现

main.c

#include <stdio.h>
#include <stdlib.h>

#include "queue.h"

#define NAMESIZE	32

struct score_st
{
	int id;
	char name[NAMESIZE];
	int  math;
	int chinese;
};

static void print_s(void *record)
{
	struct score_st *r = record;
	printf("%d %s %d %d\n",r->id,r->name,r->math,r->chinese);
}

int main()
{
	QUEUE *qu;
	struct score_st tmp;
	int i,ret;

	qu = queue_create(sizeof(struct score_st));
	if(qu == NULL)
		exit(1);

	for(i = 0;i < 6; i ++)
	{
		tmp.id = i;
		snprintf(tmp.name,NAMESIZE,"stu%d",i);
		tmp.math = rand()%100;
		tmp.chinese = rand()%100;

		if(queue_en(qu,&tmp) !=  0)
			break;
	}

	while(1)
	{
		ret = queue_de(qu,&tmp);
		if(ret == -1)
			break;
		print_s(&tmp);
	}
	queue_destroy(qu);

	exit(0);
}

queue.c

#include "queue.h"

QUEUE *queue_create(int size)
{
	llist_create(size);
}

int queue_en(QUEUE *ptr,const void *data)
{
	return llist_insert(ptr,data,LLIST_BACKWARD);
}
static int always_match(const void *p1,const void *p2)
{
	return 0;
}

int queue_de(QUEUE *ptr,void *data)
{
	return llist_fetch(ptr,(void *)0,always_match,data);
}

void queue_destroy(QUEUE *ptr)
{
	llist_destroy(ptr);
}

queue.h

#ifndef QUEUE_H__
#define QUEUE_H__

#include "llist.h"

typedef LLIST QUEUE;

QUEUE *queue_create(int);

int queue_en(QUEUE *,const void *);

int queue_de(QUEUE *,void *);

void queue_destroy(QUEUE *);

#endif

llist.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "llist.h"

LLIST *llist_create(int initsize)
{
	LLIST *new;
	
	new = malloc(sizeof(*new));
	if(new == NULL)
		return NULL;

	new->size = initsize;
	new->head.prev = &new->head;
	new->head.next = &new->head;

	return new;
}

int llist_insert(LLIST *ptr,const void *data,int mode)
{
	struct llist_node_st *newnode;
    newnode = malloc(sizeof(*newnode) + ptr -> size);
	if(newnode == NULL)
		return -1;
    
	memcpy(newnode->data,data,ptr->size);
	if(mode == LLIST_FORWARD)
	{
		newnode -> prev = &ptr -> head;
		newnode -> next = ptr -> head.next;
	}
	else if(mode == LLIST_BACKWARD)
	{
		newnode -> prev =ptr -> head.prev;
		newnode -> next =&ptr -> head;
	}
	else	
	{
		return -3;
	}

	newnode -> prev -> next = newnode;
	newnode -> next -> prev = newnode;

	return 0;
}

static struct llist_node_st *find_(LLIST *ptr ,const void *key,llist_cmp *cmp)
{
	struct llist_node_st *cur;

	for(cur = ptr->head.next; cur != &ptr->head; cur = cur ->next)
	{
		if(cmp(key,cur->data)  == 0)
			break;
	}
	return cur;
}

void *llist_find(LLIST *ptr,const void *key,llist_cmp *cmp)
{
    struct llist_node_st *node;
    node = find_(ptr,key,cmp);
    if(node == &ptr->head)
        return  NULL;
    return node->data;
}

int llist_delete(LLIST *ptr,const void *key,llist_cmp *cmp)
{
	struct llist_node_st *node;

	node = find_(ptr,key,cmp);
	if(node == &ptr -> head)
		return -1;
	node->prev->next = node->next;
	node->next->prev = node->prev;
	free(node);
	
	return 0;
}

int llist_fetch(LLIST *ptr,const void *key,llist_cmp *cmp,void *data)
{
	struct llist_node_st *node;

	node = find_(ptr,key,cmp);
	if(node == &ptr->head)
		return -1;
	node->prev->next = node->next;
	node->next->prev = node->prev;
	if(data != NULL)
		memcpy(data,node->data,ptr->size);
	free(node);
	return 0;
}

void llist_travel(LLIST *ptr , llist_op *op)
{
	struct llist_node_st *cur;

	for(cur = ptr->head.next;cur != &ptr->head;cur = cur->next)
		op(cur->data);
	
}

void llist_destroy(LLIST *ptr)
{
	struct llist_node_st  *cur,*next;

	for(cur = ptr->head.next;cur != &ptr->head;cur = next)
	{
		next = cur ->next;
        free(cur);
	}
	free(ptr);
}

llist.h

#ifndef LLIST_H__
#define LLIST_H__

#define LLIST_FORWARD		1
#define LLIST_BACKWARD		2

typedef void llist_op(const void *);
typedef int llist_cmp(const void *,const void *);

struct llist_node_st
{
	struct llist_node_st *prev;
	struct llist_node_st *next;
  	char data[1];  
};

typedef struct 
{
	int size;
	struct llist_node_st head;
}LLIST;

LLIST *llist_create(int initsize);

int llist_insert(LLIST *,const void *data,int mode);

void *llist_find(LLIST *,const void *key,llist_cmp *);

int llist_delete(LLIST *,const void *key,llist_cmp *);

int llist_fetch(LLIST *,const void *key,llist_cmp *,void *data);

void llist_travel(LLIST *,llist_op *);

void llist_destroy(LLIST *);

#endif

Makefile

all:queue
	
queue:queue.o main.o llist.o
	$(CC) $^ -o $@

clean:
	rm -f queue *.o 

栈和队列的应用

计算器

main.c

#include <stdio.h>
#include <stdlib.h>

#include  "sqstack.h"

static void compute(sqstack *snum,datatype *op)
{
	datatype n1,n2,n;

	st_pop(snum,&n2);
	st_pop(snum,&n1);
	switch(*op)
	{
		case '+':
			n = n1 + n2;
			break;
		case '-':
			n = n1 - n2;
			break;
		case '*':
			n = n1 * n2;
			break;
		case '/':
			n = n1 / n2;
			break;
		default:
			exit(1);
	}
	st_push(snum,&n);
}

static void deal_bracket(sqstack *snum,sqstack *sop)
{
	datatype old_op;
	st_top(sop,&old_op);

	while(old_op != '(')
	{
		st_pop(sop,&old_op);
		compute(snum,&old_op);
		st_pop(sop,&old_op);
	}
	st_pop(sop,&old_op);
}

static int get_pri(int op)
{
	switch(op)
	{
		case'(':
			return 0;
		case '+':
		case '-':
			return 1;
		case '*':
		case '/':
			return 2;
	}
}

static void del_op(sqstack *snum,sqstack *sop,int op)
{
	datatype old_op;
	if(st_isempty(sop) || op == '(')
	{
		st_push(sop,&op);
		return ;
	}
	
	st_top(sop,&old_op);
	
	if(get_pri(op) > get_pri(old_op))
	{
		st_push(sop,&op);
		return ;
	}

	while(get_pri(op) <= get_pri(old_op))
	{
		st_pop(sop,&old_op);
		compute(snum,&old_op);
		if(st_isempty(sop))
			break;
		st_top(sop,&old_op);
	}
	st_push(sop,&op);
}

int main()
{
	datatype old_op;
	int i;
	char str[] = "(11+3)*2-5";
	sqstack *snum , *sop;
	int value = 0;
	int flag = 0;


	snum = st_create();
	if(snum == NULL)
		exit(1);

	sop = st_create();
	if(sop ==  NULL)
		exit(1);

	while(str[i] != '\0')
	{
		if(str[i] > '0' && str[i] < '9')
		{
			value = value * 10 + (str[i] - '0');
			flag = 1;
		}
		else //is a op
		{
			if(flag)
			{
				st_push(snum,&value);
				flag = 0;
				value = 0;
			}
			if(str[i] == ')')
			{
				deal_bracket(snum,sop);
			}
			else //		( + - * /
			{
				del_op(snum,sop,str[i]);
			}
		}

		i++;
	}

	if(flag)
		st_push(snum,&value);
	while(!st_isempty(sop))
	{
		st_pop(sop,&old_op);
		compute(snum,&old_op);
	}
	st_pop(snum,&old_op);
	printf("%d\n",old_op);

	st_destroy(snum);
	st_destroy(sop);

	exit(0);
}

Makefile

all:main
	
main:sqstack.o main.o
	$(CC) $^ -o $@

clean:
	rm -f main *.o 

sqstack.c

#include <stdio.h>
#include <stdlib.h>

#include "sqstack.h"

sqstack *st_create(void)
{
	sqstack *st;
	st = malloc(sizeof(*st));
	if(st == NULL)
		return NULL;
	st->top = -1;
	return  st;
}

int st_isempty(sqstack *st)
{
	return  (st->top == -1);
}

int st_push(sqstack *st,datatype *data)
{
	if(st->top == (MAXSIZE - 1))
		return -1;

	st->data[++st->top] = *data;
	return 0;
}

int st_pop(sqstack *st,datatype *data)
{
	if(st_isempty(st))
		return -1;
	*data = st -> data[st->top--];
	return 0;
}

int st_top(sqstack *st,datatype *data)
{
	if(st_isempty(st))
		return -1;
	*data = st->data[st->top];
	return 0;
}

void st_travel(sqstack *st)
{
	int i;

	if(st_isempty(st))
		return ;
	for(i = 0; i <= st->top; i++)
		printf("%d ",st->data[i]);
	printf("\n");
}

void st_destroy(sqstack *st)
{
	free(st);
}

sqstack.h

#ifndef SQSTACK_H__
#define SQSTACK_H__

#define MAXSIZE		32

typedef int datatype;

typedef struct node_st
{
	datatype data[MAXSIZE];
	int top;
}sqstack;

sqstack *st_create(void);

int st_isempty(sqstack *);

int st_push(sqstack *,datatype *);

int st_pop(sqstack *,datatype *);

int st_top(sqstack *,datatype *);

void st_travel(sqstack *);

void st_destroy(sqstack *);

#endif

求中算法

main.c

#include <stdio.h>
#include <stdlib.h>

#include "sqstack.h"
#include "queue.h"

#define  NR_BALL	27

static int check(queue *qu)
{
	int i = (qu->head+1)%MAXSIZE;
	while(i != qu->tail)
	{
		if(qu->data[i] > qu->data[(i+1)%MAXSIZE])
			return 0;
		i = (i + 1) %MAXSIZE;
	}

	return 1;
}

int  main()
{
	int  i;
	queue *qu;
	int t,value;
	int time = 0;

	sqstack *st_min,*st_fivemin,*st_hour;

	qu  = qu_create();
	if(qu == NULL)
		exit(1);

	st_min = st_create();
	if(st_min  == NULL)
		exit(1);
	st_fivemin = st_create();
	if(st_fivemin == NULL)
		exit(1);
	st_hour = st_create();
	if(st_hour == NULL)
		exit(1);

	for(i = 1;i <= NR_BALL; i++)
		qu_enqueue(qu,&i);

	qu_travel(qu);
	
	while(1)
	{
		qu_dequeue(qu,&t);
		time++;
	
		if(st_min->top != 3)
		{
			st_push(st_min,&t);
		}
		else
		{
			while(!st_isempty(st_min))
			{
				st_pop(st_min,&value);
				qu_enqueue(qu,&value);
			}
			if(st_fivemin -> top != 10)
				st_push(st_fivemin,&t);
			else
			{
				while(!st_isempty(st_fivemin))
				{
					st_pop(st_fivemin,&value);
					qu_enqueue(qu,&value);
				}
				if(st_hour -> top != 10)
					st_push(st_hour,&t);
				else
				{
					while(!st_isempty(st_hour))
					{
						st_pop(st_hour,&value);
						qu_enqueue(qu,&value);
					}
					qu_enqueue(qu,&t);
					
					if(check(qu))
						break;
				}
			}
		}
	}

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

	qu_destroy(qu);
	st_destroy(st_min);
	st_destroy(st_fivemin);
	st_destroy(st_hour);

	exit(0);
}

Makefile

CFLAGS+=-Wall

all:ball_clock
	
ball_clock:sqstack.o main.o queue.o
	$(CC) $^ -o $@ $(CFLAGS)

clean:
	rm -f ball_clock *.o 

queue.c

#include <stdio.h>
#include <stdlib.h>

#include "queue.h"

queue *qu_create()
{
	queue *sq;

	sq = malloc(sizeof(*sq));
	if(sq  ==  NULL)
		return NULL;

	sq->head = 0;
	sq->tail = 0;

	return sq;
}

int qu_isempty(queue *sq)
{
	return (sq->head == sq->tail);
}

int qu_enqueue(queue *sq,datatype *x)
{
	if((sq->tail + 1) % MAXSIZE == sq -> head)
		return -1;

	sq -> tail = (sq->tail + 1) % MAXSIZE;
	sq -> data[sq->tail] = *x;
	return 0;
}

int qu_dequeue(queue *sq,datatype *x)
{
	if(qu_isempty(sq))
		return -1;

	sq->head = (sq -> head + 1) % MAXSIZE;
	*x = sq->data[sq->head];

	return 0;
}

void qu_travel(queue *sq)
{
	int i;
	if(sq->head == sq->tail)
		return ;

	i  = (sq->head + 1) % MAXSIZE;
	while(i != sq->tail)
	{
		printf("%d ",sq->data[i]);
		i = (i + 1) % MAXSIZE;
	}
	printf("%d\n",sq->data[i]);
}

void qu_clear(queue *sq)
{
	sq->head = sq->tail;
	
}

void  qu_destroy(queue *sq)
{
	free(sq);
}

queue.h

#ifndef QUEUE_H__
#define QUEUE_H__

typedef int datatype;

#define MAXSIZE		32

typedef struct 
{
	datatype data[MAXSIZE];
	int head,tail;
}queue;

queue *qu_create();

int qu_isempty(queue *);

int qu_enqueue(queue *,datatype *);

int qu_dequeue(queue *,datatype *);

void qu_travel(queue *);

void qu_clear(queue *);

void  qu_destroy(queue *);

#endif

sqstack.c

#include <stdio.h>
#include <stdlib.h>

#include "sqstack.h"

sqstack *st_create(void)
{
	sqstack *st;
	st = malloc(sizeof(*st));
	if(st == NULL)
		return NULL;
	st->top = -1;
	return  st;
}

int st_isempty(sqstack *st)
{
	return  (st->top == -1);
}

int st_push(sqstack *st,type *data)
{
	if(st->top == SIZE - 1)
		return -1;

	st->data[++st->top] = *data;
	return 0;
}

int st_pop(sqstack *st,type *data)
{
	if(st_isempty(st))
		return -1;
	*data = st -> data[st->top--];
	return 0;
}

int st_top(sqstack *st,type *data)
{
	if(st_isempty(st))
		return -1;
	*data = st->data[st->top];
	return 0;
}

void st_travel(sqstack *st)
{
	int i;

	if(st_isempty(st))
		return ;
	for(i = 0; i <= st->top; i++)
		printf("%d ",st->data[i]);
	printf("\n");
}

void st_destroy(sqstack *st)
{
	free(st);
}

sqstack.h

#ifndef SQSTACK_H__
#define SQSTACK_H__

#define SIZE		32

typedef int type;

typedef struct node_st
{
	type data[SIZE];
	int top;
}sqstack;

sqstack *st_create(void);

int st_isempty(sqstack *);

int st_push(sqstack *,type *);

int st_pop(sqstack *,type *);

int st_top(sqstack *,type *);

void st_travel(sqstack *);

void st_destroy(sqstack *);

#endif

由于后半段视频黑屏了,修改了很长时间,进行了很多的测试,之后在网上对比代码时发现只是因为在sqstack.h中修改为#define SIZE 32,之后运行成功。good 😄

静态库和动态库

静态库

libxx.a(xx库名)

ar -cr libxx.a yyy.o

发布到

/usr/local/include

/usr/local/lib

gcc -L/usr/local/lib -o main main.o -lxx(-l参数必须放在最后 ,有依赖)

//以lib2为例

$ make
$ ldd ./llist
$ gcc -c llist.c //生成.o文件
$ ls
llist.c  llist.h  llist.o  main.c  Makefile
$ ar -cr libllist.a llist.o
$ ls
libllist.a  llist.c  llist.h  llist.o  main.c  Makefile
$ cp llist.h /usr/local/include/
$ cp libllist.a  /usr/local/lib/
$ gcc -o main main.c -lllist
$ ls
libllist.a  llist.c  llist.h  llist.o  main  main.c  Makefile
$ rm libllist.a llist.o
$ rm main -rf
$ gcc -o main main.c -lllist 
//可将main.c中#include "llist.h"改为<llist.h>
$ ldd ./main
	linux-vdso.so.1 (0x00007fff19ad2000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x000073cfbb400000)
	/lib64/ld-linux-x86-64.so.2 (0x000073cfbb6a9000)

动态库

libxx.so

gcc -shared -fpic -o libxx.so yyy.c

发布到

/usr/local/include

/usr/local/lib

在 /etc/ld.so.conf 中添加路径

/sbin/ldconfig重读 /etc/ld.so.conf

gcc -I/usr/local/include -L/usr/local/lib -o ... -lxx

ldd - print shared library dependencies

$ gcc -shared -fpic -o libllist.so llist.c
$ ls
libllist.so  llist.c  llist.h  main.c  Makefile
$ mv libllist.so /usr/local/lib/
$  ls
llist.c  llist.h  main.c  Makefile
$ vim /etc/ld.so.conf
//添加路径
	include /etc/ld.so.conf.d/*.conf
	/usr/local/lib/
$  /sbin/ldconfig
$  gcc -o main main.c -lllist
$ ls
llist.c  llist.h  main  main.c  Makefile
$ ldd ./main
	linux-vdso.so.1 (0x00007ffc0e785000)
	libllist.so => /usr/local/lib/libllist.so (0x00007bf505793000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007bf505400000)
	/lib64/ld-linux-x86-64.so.2 (0x00007bf5057af000)

非root用户发布

cp xx.so ~/lib

export LD_LIBRARY_PATH=~/lib

一些问题

  • gcc -L/usr/local/lib -o main main.o -lxx

如果不加-lxx会出现报错,比如

gcc -o main main.c -lstack
/usr/bin/ld: /usr/local/lib/libstack.so: undefined reference to `llist_create'
/usr/bin/ld: /usr/local/lib/libstack.so: undefined reference to `llist_fetch'
/usr/bin/ld: /usr/local/lib/libstack.so: undefined reference to `llist_destroy'
/usr/bin/ld: /usr/local/lib/libstack.so: undefined reference to `llist_insert'
collect2: error: ld returned 1 exit status

一定要在最后加上依赖关系

  • /sbin/ldconfig

在添加了新的库后(或者说对新的库进行封装后)需要加上这句话,不然会报错,如:

./main
./main: error while loading shared libraries: libstack.so: cannot open shared object file: No such file or directory

树状存储

  • 深度(层数)

  • 叶子

  • 孩子

  • 兄弟

  • 堂兄弟

  • 二叉树

    • 当前的树的节点当中,每个节点最多有两个孩子而且两个孩子必须区分哪个是左孩子哪个是右孩子

    • 满二叉树

      • 如果一颗深度为k的树上有2k-1个节点

    • 完全二叉树

      • 一棵树只有倒数两层出现存在不满足两个孩子的节点,而且存在的一定是左孩子

  • 存储

    • 顺序

    • 链式

  • 遍历

    • 按层遍历

    • 先序(根,左 ,右)

    • 中序(左,根,右)

    • 后序(左,右,根)

main.c

#include <stdio.h>
#include <stdlib.h>

#define NAMESIZE	32

struct score_st
{
	int id;
	char name[NAMESIZE];
	int math;
	int chinese;
};

struct node_st
{
	struct score_st data;
	struct node_st *l,*r;
};

void print_s(struct score_st *d)
{
	printf("%d %s %d %d\n",d->id,d->name,d->math,d->chinese);
}

int insert(struct node_st **root,struct score_st *data)
{
	struct node_st *node;

	if(*root == NULL)
	{
	   	node = malloc(sizeof(*node));
		if(node == NULL)
			return -1;
		node->data = *data;
		node->l = NULL;
		node->r = NULL;

		*root = node;
		return 0;
	}
	if(data -> id <= (*root)->data.id)
		return insert(&(*root)->l,data);
	return insert(&(*root)->r,data);
}

struct score_st *find(struct node_st *root,int id)
{
	if(root==NULL)
		return NULL;
	if(id == root->data.id)
		return &root->data;
	if(id < root->data.id)
		return find(root->l,id);
	else
		return find(root->r,id);
}

void draw_(struct node_st *root,int level)
{
	int i;
	if(root == NULL)
		return ;
	draw_(root->r,level+1);
	
	for(i = 0;i< level;i++)
	{
		printf("	");
	}
	print_s(&root->data);
	
	draw_(root->l,level+1);

}

void draw(struct node_st *root)
{
	draw_(root, 0);
}  


int main()
{
	int arr[] = {1,2,3,7,6,5,9,8,4};
	int i;
	struct node_st *tree = NULL;
	struct score_st tmp,*datap;

	for(i = 0; i < sizeof(arr)/sizeof(*arr);i++)
	{
		tmp.id = arr[i];
		snprintf(tmp.name,NAMESIZE,"stu%d",arr[i]);
		tmp.math = rand()%100;
		tmp.chinese = rand()%100;

		insert(&tree, &tmp);
	}

	draw(tree);

#if 0
	int tmpid = 2;
	datap = find(tree,tmpid);
	if(datap == NULL)
		printf("Can not find the id %d\n",tmpid);
	else
		print_s(datap);
#endif

	exit(0);
}

输出结果:

				9 stu9 90 59
					8 stu8 63 26
			7 stu7 86 92
				6 stu6 49 21
					5 stu5 62 27
						4 stu4 40 26
		3 stu3 93 35
	2 stu2 77 15
1 stu1 83 86

平衡二叉树

#include <stdio.h>
#include <stdlib.h>
#include <queue.h>

#define NAMESIZE	32

struct score_st
{
	int id;
	char name[NAMESIZE];
	int math;
	int chinese;
};

struct node_st
{
	struct score_st data;
	struct node_st *l,*r;
};

static struct node_st *tree = NULL;

void print_s(struct score_st *d)
{
	printf("%d %s %d %d\n",d->id,d->name,d->math,d->chinese);
}

int insert(struct node_st **root,struct score_st *data)
{
	struct node_st *node;

	if(*root == NULL)
	{
	   	node = malloc(sizeof(*node));
		if(node == NULL)
			return -1;
		node->data = *data;
		node->l = NULL;
		node->r = NULL;

		*root = node;
		return 0;
	}
	if(data -> id <= (*root)->data.id)
		return insert(&(*root)->l,data);
	return insert(&(*root)->r,data);
}

struct score_st *find(struct node_st *root,int id)
{
	if(root==NULL)
		return NULL;
	if(id == root->data.id)
		return &root->data;
	if(id < root->data.id)
		return find(root->l,id);
	else
		return find(root->r,id);
}

void draw_(struct node_st *root,int level)
{
	int i;
	if(root == NULL)
		return ;
	draw_(root->r,level+1);
	
	for(i = 0;i< level;i++)
	{
		printf("	");
	}
	print_s(&root->data);
	
	draw_(root->l,level+1);

}

void draw(struct node_st *root)
{
	draw_(root, 0);
	printf("\n\n");
	//getchar();
}  

static int get_num(struct node_st *root)
{
	if(root == NULL)
		return 0;
	return get_num(root->l) + 1 + get_num(root->r);
}

static struct node_st *find_min(struct node_st *root)
{
	if(root->l == NULL)
		return root;
	return find_min(root->l);

}

static void turn_left(struct node_st **root)
{
	struct node_st *cur =  *root;
	*root = cur->r;
	cur->r = NULL;

	find_min(*root)->l = cur;
//	draw(tree);
}

static struct node_st *find_max(struct node_st *root)
{
	if(root->r ==  NULL)
	{
		return root;
	}
	return find_max(root->r);
}

static void turn_right(struct node_st **root)
{
	struct node_st *cur = *root;
	*root = cur->l;
	cur->l = NULL;

	find_max(*root)->r = cur;
//	draw(tree);
}

void balance(struct node_st  **root)
{
	int sub;
	if(*root == NULL)
		return ;
	while(1)
	{
		sub = get_num((*root)->l) - get_num((*root)->r);
		if(sub  >= -1 && sub <= 1)
			break;
		if(sub <-1)
			turn_left(root);
		else
			turn_right(root);
	}

	balance(&(*root)->l);
	balance(&(*root)->r);
}

void delete(struct node_st **root,int id)
{
	struct node_st **node = root;
	struct node_st *cur = NULL;

	while(*node !=  NULL &&(*node)->data.id != id)
	{
		if(id  < (*node)->data.id)
			node = &(*node)->l;
		else
			node = &(*node)->r;
	}

	if(*node == NULL)
		return ;
	cur = *node;
	if(cur->l == NULL)
		*node = cur->r;
	else
	{
		*node = cur->l;
		find_max(cur->l)->r = cur->r;
	}
	free(cur);
}
#if 0
void travel(struct node_st *root)
{
	if(root == NULL)
		return ;
	//first
/*	
	print_s(&root->data);
	travel(root->l);
	travel(root->r);
*/

	//middle	
/*
	travel(root->l);
	print_s(&root->data);
	travel(root->r);
*/

	//after
	travel(root->l);
	travel(root->r);
	print_s(&root->data);

}
#else
	//level
void travel(struct node_st *root)
{
	int ret;
	QUEUE *qu;
	struct node_st *cur;

	qu = queue_create(sizeof(struct node_st *));
	if(qu == NULL)
		return ;

	queue_en(qu,&root);
	/*if error*/

	while(1)
	{
		ret = queue_de(qu,&cur);
		if(ret == -1)
			break;
		print_s(&cur->data);
		if(cur->l != NULL)
			queue_en(qu,&cur->l);
		if(cur->r != NULL)
			queue_en(qu,&cur->r);
	}
	queue_destroy(qu);
}

#endif
int main()
{
	int arr[] = {1,2,3,7,6,5,9,8,4};
	int i;
	struct node_st *tree = NULL;
	struct score_st tmp,*datap;

	for(i = 0; i < sizeof(arr)/sizeof(*arr);i++)
	{
		tmp.id = arr[i];
		snprintf(tmp.name,NAMESIZE,"stu%d",arr[i]);
		tmp.math = rand()%100;
		tmp.chinese = rand()%100;

		insert(&tree, &tmp);
	}

	draw(tree);
	balance(&tree);
	draw(tree);

	travel(tree);

#if 0
	int tmpid = 5;
	delete(&tree,tmpid);
	draw(tree);
#endif

#if 0
	int tmpid = 2;
	datap = find(tree,tmpid);
	if(datap == NULL)
		printf("Can not find the id %d\n",tmpid);
	else
		print_s(datap);
#endif

	exit(0);
}

树转换为广义表

save.c

#include <stdio.h>
#include <stdlib.h>

#define FNAME	"/tmp/out"

struct node_st
{
	char data;
	struct node_st *l,*r;
};

static struct node_st *tree = NULL;

int insert(struct node_st **root,int data)
{
	struct node_st *node;

	if(*root == NULL)
	{
	   	node = malloc(sizeof(*node));
		if(node == NULL)
			return -1;
		node->data = data;
		node->l = NULL;
		node->r = NULL;

		*root = node;
		return 0;
	}
	if(data<= (*root)->data)
		return insert(&(*root)->l,data);
	return insert(&(*root)->r,data);
}


void draw_(struct node_st *root,int level)
{
	int i;
	if(root == NULL)
		return ;
	draw_(root->r,level+1);
	
	for(i = 0;i< level;i++)
	{
		printf("	");
	}
	printf("%c\n",root->data);
	
	draw_(root->l,level+1);

}

void draw(struct node_st *root)
{
	draw_(root, 0);
	printf("\n\n");
}  

int save_(struct node_st *root ,FILE *fp)
{
	fputc('(',fp);
	/*if error*/

	if(root == NULL)
	{
		fputc(')',fp);
		return 0;
	}

	fputc(root->data,fp);
	/*if error */

	save_(root->l,fp);
	save_(root->r,fp);

	fputc(')',fp);
	/*if error*/     

	return 0;
}

int save(struct node_st *root,const char *path)
{
	FILE *fp;
	fp = fopen(path,"w");
	if(fp == NULL)
		return -1;

	save_(tree,fp);
	return 0;
}

int main()
{
	char arr[] = "cefadjbh";
	int i;

	for(i = 0; i < sizeof(arr)/sizeof(*arr)-1 ;i++)
	{
		insert(&tree, arr[i]);
	}

	draw(tree);

	save(tree,FNAME);
	exit(0);
}

load.c

#include <stdio.h>
#include <stdlib.h>

#define FNAME		"/tmp/out"

struct node_st
{
	char data;
	struct node_st *l,*r;
};

void draw_(struct node_st *root,int level)
{
	int i;
	if(root == NULL)
		return ;
	draw_(root->r,level+1);
	
	for(i = 0;i< level;i++)
	{
		printf("	");
	}
	printf("%c\n",root->data);
	
	draw_(root->l,level+1);

}

void draw(struct node_st *root)
{
	draw_(root, 0);
	printf("\n\n");
	//getchar();
}  

struct node_st *load_(FILE *fp)
{
	int c;
	struct node_st *root;

	c = fgetc(fp);
	/*if error*/

	if(c != '(')
	{
		fprintf(stderr,"fgetc():error.\n");
		exit(1);
	}

	c = fgetc(fp);
	if(c == ')')
		return NULL;
	root = malloc(sizeof(*root));
	if(root == NULL)
		exit(1);

	root->data = c;
	root->l = load_(fp);
	root->r = load_(fp);
	fgetc(fp);
	/*if error */

	return root;
}

struct node_st *load(const char *path)
{
	FILE *fp;
	struct node_st *root;

	fp = fopen(path,"r");
	if(fp == NULL)
		return NULL;
	
	root = load_(fp);
	fclose(fp);

	return root;
}

int main()
{
	struct node_st *root;

	root = load(FNAME);

	draw(root);
	
	exit(0);
}

搜索树retrieval

统计,大量字符串的统计。

没有遍历的需求

以空间换时间

查字典游戏

trie.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define DESC_SIZE	256
#define KEY_SIZE	256
#define BUFSIZE		512

#define FNAME		"log"

struct node_st
{
	struct node_st *ch[26];
	char desc[DESC_SIZE];
};

int get_word(FILE *fp,char *key,char *desc)
{
	int i,j;
	char buf[BUFSIZE];
	char *retp;

	retp = fgets(buf,BUFSIZE,fp);
	if(retp == NULL)
		return -1;

	for(i = 0;i < KEY_SIZE -1 && buf[i] != ':' ;i++)
		key[i] = buf[i];
	key[i] = '\0';

	i++;
	for(j = 0; j < DESC_SIZE -1 && buf[i] != '\0';j++,i++)
		desc[j] = buf[i];
	desc[j] = '\0';

	return 0;
}

struct node_st *newnode(void)
{
	int i;
	struct node_st *node;

	node = malloc(sizeof(*node));
	if(node == NULL)
		return NULL;

	node->desc[0] = '\0';
	
	for(i = 0; i <26 ; i++)
		node->ch[i] = NULL;
	
	return node;
}

int insert(struct node_st **root,char *key,char *desc)
{
	if(*root == NULL)
	{
		*root = newnode();
		if(*root == NULL)
			return -1;
	}

	if(*key == '\0')
	{
		strcpy((*root)->desc,desc);
		return 0;
	}

	return insert((*root)->ch+*key - 'a',key+1,desc);

}

char *find(struct node_st *root,char *key)
{
	if(root == NULL)
		return  NULL;
	if(*key ==  '\0')
		return root->desc;
	return find(root->ch[*key - 'a'],key + 1);
}


int main()
{
	struct node_st *tree = NULL;
	int ret;
	FILE *fp;
	char desc[DESC_SIZE] ={'\0'},key[KEY_SIZE] = {'\0'};
	char *datap;

	fp = fopen(FNAME,"r");
	if(fp ==  NULL)
	{
		fprintf(stderr,"fopen():error!\n");
		exit(1);
	}

	while(1)
	{
		ret = get_word(fp,key,desc);
		if(ret == -1)
			break;
		insert(&tree,key,desc);
	}

	datap = find(tree,"donkey");
	if(datap == NULL)
		printf("Can not find!\n");
	else
		puts(datap);

	fclose(fp);

	exit(0);
}

log

ant:a small insect that lives in group
butterfly: a flying insect with a long thin body
cobra:a highly dangerous snake
donkey:a animal with short legs and long ears

词频统计练习

trie.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define DESC_SIZE	256
#define KEY_SIZE	256
#define BUFSIZE		512

#define FNAME		"log"

struct node_st
{
	struct node_st *ch[26];
	char desc[DESC_SIZE];
};

int get_word(FILE *fp,char *key,char *desc)
{
	int i,j;
	char buf[BUFSIZE];
	char *retp;

	retp = fgets(buf,BUFSIZE,fp);
	if(retp == NULL)
		return -1;

	for(i = 0;i < KEY_SIZE -1 && buf[i] != ':' ;i++)
		key[i] = buf[i];
	key[i] = '\0';

	i++;
	for(j = 0; j < DESC_SIZE -1 && buf[i] != '\0';j++,i++)
		desc[j] = buf[i];
	desc[j] = '\0';

	return 0;
}

struct node_st *newnode(void)
{
	int i;
	struct node_st *node;

	node = malloc(sizeof(*node));
	if(node == NULL)
		return NULL;

	node->desc[0] = '\0';
	
	for(i = 0; i <26 ; i++)
		node->ch[i] = NULL;
	
	return node;
}

int insert(struct node_st **root,char *key,char *desc)
{
	if(*root == NULL)
	{
		*root = newnode();
		if(*root == NULL)
			return -1;
	}

	if(*key == '\0')
	{
		strcpy((*root)->desc,desc);
		return 0;
	}

	return insert((*root)->ch+*key - 'a',key+1,desc);

}

char *find(struct node_st *root,char *key)
{
	if(root == NULL)
		return  NULL;
	if(*key ==  '\0')
		return root->desc;
	return find(root->ch[*key - 'a'],key + 1);
}


int main()
{
	struct node_st *tree = NULL;
	int ret;
	FILE *fp;
	char desc[DESC_SIZE] ={'\0'},key[KEY_SIZE] = {'\0'};
	char *datap;

	fp = fopen(FNAME,"r");
	if(fp ==  NULL)
	{
		fprintf(stderr,"fopen():error!\n");
		exit(1);
	}

	while(1)
	{
		ret = get_word(fp,key,desc);
		if(ret == -1)
			break;
		insert(&tree,key,desc);
	}

	datap = find(tree,"donkey");
	if(datap == NULL)
		printf("Can not find!\n");
	else
		puts(datap);

	fclose(fp);

	exit(0);
}

log

ant:a small insect that lives in group
butterfly: a flying insect with a long thin body
cobra:a highly dangerous snake
donkey:a animal with short legs and long ears

俄罗斯方块

解决问题

  1. 图形库

    1. 图形工具

      1. ANSI_VT

        1. 长高比例

      2. framebuffer

        1. 像素为单位进行着色

        2. 将来可移植到板子上驱动

  2. 输入设备的设置

  3. 并发

LINUX使用心得

终端

终端快捷键

创建新的标签页:ctrl + shift + t

创建新的窗口:ctrl + shift + n

来回切换:art + 1/2/3

vim

vim 常用退出命令

:w            - 保存文件,不退出 vim
:w file  -将修改另外保存到 file 中,不退出 vim
:w!          -强制保存,不退出 vim
:wq          -保存文件,退出 vim
:wq!        -强制保存文件,退出 vim
:q            -不保存文件,退出 vim
:q!          -不保存文件,强制退出 vim
:e!          -放弃所有修改,从上次保存文件开始再编辑

vim美化

:colorscheme + space +tab		#更换主题
:set nospell				   #清除代码红色高亮

vim使用小技巧!

复制粘贴剪切

复制:V+ 选中的内容 + V

粘贴:P

新发现:使用ctrl + shift + v可以进行剪切 (操作时的新发现)之后再按P就可以进行粘贴了

缩进

对齐缩进:

  • 按住ctrl + v或者V,使用方向键选择要缩进的行,然后按下=

问题

联网问题

[Ubuntu 22.04 下联网问题、 ifconfig、net-tools不能用的问题]  https://blog.csdn.net/qq_62775411/article/details/129343467#:~:text=%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88%EF%BC%9A%20%E4%B8%80%E3%80%81%E8%A7%A3%E5%86%B3%E7%BD%91%E7%BB%9C%E9%97%AE%E9%A2%98%EF%BC%9A%E4%BF%AE%E6%94%B9%E7%BD%91%E7%BB%9C%E9%85%8D%E7%BD%AE%20step1%EF%BC%9A%E6%89%93%E5%BC%80%E8%99%9A%E6%8B%9F%E7%BD%91%E7%BB%9C%E7%BC%96%E8%BE%91%E5%99%A8,step2%3A%E6%89%93%E5%BC%80%E7%BD%91%E7%BB%9C%E8%AE%BE%E7%BD%AE%20step3%EF%BC%9A%E6%9C%80%E7%BB%88%E8%AE%BE%E7%BD%AE%20%E4%BA%8C%E3%80%81%E8%A7%A3%E5%86%B3ifconfig%E3%80%81net-tools%E9%97%AE%E9%A2%98%20%E4%B8%89%E3%80%81%E6%89%93%E5%BC%80%E7%BB%88%E7%AB%AF%E6%B5%8B%E8%AF%95 

  • 28
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值