├── README.md ├── Unit-1 ├── Lesson-1.md ├── Lesson-10.md ├── Lesson-11.md ├── Lesson-12.md ├── Lesson-13.md ├── Lesson-14.md ├── Lesson-15.md ├── Lesson-16.md ├── Lesson-17.md ├── Lesson-18.md ├── Lesson-19.md ├── Lesson-2.md ├── Lesson-20.md ├── Lesson-21.md ├── Lesson-22.md ├── Lesson-23.md ├── Lesson-24.md ├── Lesson-3.md ├── Lesson-4.md ├── Lesson-5.md ├── Lesson-6.md ├── Lesson-7.md ├── Lesson-8.md ├── Lesson-9.md └── README.md ├── Unit-2 ├── Lesson-25.md ├── Lesson-26.md ├── Lesson-27.md ├── Lesson-28.md ├── Lesson-29.md ├── Lesson-30.md ├── Lesson-31.md ├── Lesson-32.md ├── Lesson-33.md ├── Lesson-34.md ├── Lesson-35.md ├── Lesson-36.md ├── Lesson-37.md ├── Lesson-38.md ├── Lesson-39.md ├── Lesson-40.md ├── Lesson-41.md ├── Lesson-42.md ├── Lesson-43.md ├── Lesson-44.md ├── Lesson-45.md ├── Lesson-46.md ├── Lesson-47.md ├── Lesson-48.md └── README.md ├── Unit-3 ├── Lesson-49.md ├── Lesson-49 │ ├── Makefile │ ├── a.out │ ├── demo │ ├── out.txt │ ├── readfile.c │ ├── readfile.o │ ├── state.c │ └── test.c ├── README.md └── parser-tree.md ├── Unit-4 └── README.md ├── enrollment.md ├── images ├── .DS_Store ├── china-cities.png ├── dj-algorithm.png ├── heap-0-max-heapify.png ├── heap-1-build-max.png ├── heap-2-swap-max-to-last.png ├── heap-3-swap-max-to-next.png ├── heap-4-swap-to-first.png ├── heap-array.png ├── heap-max-heapify.png ├── heap-random.png ├── huffman-freq.png ├── huffman-tree.png ├── nitrous.jpg └── vector-graph.jpg └── slides ├── .gitignore ├── Lesson-1.pdf ├── Lesson-10.pdf ├── Lesson-11.pdf ├── Lesson-12.pdf ├── Lesson-13.pdf ├── Lesson-14.pdf ├── Lesson-2.pdf ├── Lesson-3.pdf ├── Lesson-4.pdf ├── Lesson-5.pdf ├── Lesson-6.pdf ├── Lesson-7.pdf ├── Lesson-8.pdf ├── Lesson-9.pdf ├── Makefile ├── README.md ├── main.tex ├── md2pdf.sh └── outline.tex /README.md: -------------------------------------------------------------------------------- 1 | 新概念C语言 2 | ============================= 3 | 4 | ## NCCL - New Concept C Language 5 | 6 | 这是一门适合C语言零基础,但对C编程有强烈兴趣,想探求其奥秘和精髓的学员阅读学习的课程。 7 | 8 | 起名为《新概念C语言》是希望借鉴《新概念英语》教材的写法,不着重强调语法和词汇(知识点),而是以范文和场景(应用)来构建课程(Lesson)。 9 | 10 | 全书分为 4个 Unit,每个 Unit 包含 24 个 Lesson,一共 96 个 Lesson。 11 | 12 | 其中每个 Lesson 对应一段可编译执行的典型代码,解决一个有趣的计算机问题,例如约瑟夫环。 13 | 14 | 这些代码范例的编写,作者将力求做到句法经典,内涵丰富,适合初学者模仿和扩展。 15 | 16 | 全书内容大纲如下: 17 | 18 | * [Unit 1 : C Foundmentals](https://github.com/limingth/NCCL/blob/master/Unit-1/README.md) 19 | 覆盖基本的C语法结构--包括变量,表达式,语句,函数,数组,结构体,位操作,指针等,学会使用状态机思想编程。 20 | 21 | * [Unit 2 : C Essentials](https://github.com/limingth/NCCL/blob/master/Unit-2/README.md) 22 | 覆盖常用的库函数、数据结构和算法--包括单向/循环链表,栈,队列,二叉树,堆和散列表等,掌握常用的排序查找算法和问题求解算法,学会使用递归思想编程,能够解决迷宫问题、表达式求值问题、最短路径问题等。 23 | 24 | * Unit 3 : C Classicals 25 | 覆盖经典的计算机问题解法--包括在各个计算机细分领域中经典的入门问题,例如压缩算法,网络协议栈,语法分析器等。 26 | 27 | * Unit 4 : C Compiler 28 | 用C语言实现一个类C语言的编译器,最后能够编译生成 ARM 开发板上的二进制驱动程序。 29 | 30 | 作者注: 目前 Unit 3/4 仍在规划中,希望能够有更多优秀的老师参与编写,请和我[联系](mailto:limingth@gmail.com) 31 | 32 | ## [Unit One](https://github.com/limingth/NCCL/blob/master/Unit-1/README.md) 33 | * Lesson 1 - What is the simplest C program? 最简单的C程序 34 | * Lesson 2 - Let's say hello to world 打印输出 35 | * Lesson 3 - Count how many fingers do you have? 循环打印 36 | * Lesson 4 - Judge a number odd or even 判断奇偶 37 | * Lesson 5 - Summarize all numbers from 1 to 100 从1加到100求和 38 | * Lesson 6 - Print 9*9 multiplication table 乘法表 39 | * Lesson 7 - Find the max prime number within 100 求100以内的最大素数 40 | * Lesson 8 - Find 9 in number 1 to 100 1到100有多少个9 41 | * Lesson 9 - Convert a number to a string 整型转字符串 42 | * Lesson 10 - Josephus ring 约瑟夫环 43 | * Lesson 11 - Calculate the distance between 2 points 求两个坐标点之间的距离 44 | * Lesson 12 - Does your machine use little-endian? 判断机器存储是否小尾端 45 | * Lesson 13 - Sorry, your car is restricted today 对不起,你的车今天限行 46 | * Lesson 14 - Is there a way out? 判断地图上某点是否有出路 47 | * Lesson 15 - Count bit 1 in a number 统计一个数二进制表示中1的个数 48 | * Lesson 16 - How to strcpy 字符串拷贝 49 | * Lesson 17 - Count words in an artitle 统计单词个数 50 | * Lesson 18 - My printf 实现 printf 51 | * Lesson 19 - Shell command parser 命令解释器 52 | * Lesson 20 - Preprocessor 预处理器实现 53 | * Lesson 21 - Lexical analysis 词法分析器实现 54 | * Lesson 22 - Guess what number in my hand 猜数游戏 55 | * Lesson 23 - Five-Chess game 五子棋大战 56 | * Lesson 24 - Build a simple Search Engenine 简单搜索引擎 57 | 58 | ## [Unit Two](https://github.com/limingth/NCCL/blob/master/Unit-2/README.md) 59 | * Lesson 25 - mycp (cp命令实现) 60 | * Lesson 26 - ELF Header Parser (ELF文件头分析器实现) 61 | * Lesson 27 - sed simple (简单流处理器实现和正则表达式) 62 | * Lesson 28 - math calculator (数学计算器实现) 63 | * Lesson 29 - more command (more命令实现) 64 | * Lesson 30 - sort (sort命令实现) 65 | * Lesson 31 - ll (ls -l命令实现) 66 | * Lesson 32 - MyBash 项目 67 | * Lesson 33 - 动态数组实现 68 | * Lesson 34 - 约瑟夫环问题 69 | * Lesson 35 - 表达式求值问题 70 | * Lesson 36 - 广度优先解决迷宫问题 71 | * Lesson 37 - 词频统计器 72 | * Lesson 38 - 堆排序问题 73 | * Lesson 39 - 构造符号表 74 | * Lesson 40 - MyDictionary 项目 75 | * Lesson 41 - BSearch 实现 76 | * Lesson 42 - QSort 实现 77 | * Lesson 43 - 深度优先解决迷宫问题 78 | * Lesson 44 - KMP 算法实现 79 | * Lesson 45 - 最长公共子序列(LCS)问题 80 | * Lesson 46 - Dijkstra 算法 81 | * Lesson 47 - Huffman Coding 算法 82 | * Lesson 48 - MyGPS 项目 83 | 84 | 85 | ## Unit Three 86 | * Lesson 49 87 | * Lesson 50 88 | * Lesson 51 89 | * Lesson 52 90 | * Lesson 53 91 | * Lesson 54 92 | * Lesson 55 93 | * Lesson 56 94 | * Lesson 57 95 | * Lesson 58 96 | * Lesson 59 97 | * Lesson 60 98 | * Lesson 61 99 | * Lesson 62 100 | * Lesson 63 101 | * Lesson 64 102 | * Lesson 65 103 | * Lesson 66 104 | * Lesson 67 105 | * Lesson 68 106 | * Lesson 69 107 | * Lesson 70 108 | * Lesson 71 109 | * Lesson 72 110 | 111 | ## Unit Four 112 | * Lesson 73 113 | * Lesson 74 114 | * Lesson 75 115 | * Lesson 76 116 | * Lesson 77 117 | * Lesson 78 118 | * Lesson 79 119 | * Lesson 80 120 | * Lesson 81 121 | * Lesson 82 122 | * Lesson 83 123 | * Lesson 84 124 | * Lesson 85 125 | * Lesson 86 126 | * Lesson 87 127 | * Lesson 88 128 | * Lesson 89 129 | * Lesson 90 130 | * Lesson 91 131 | * Lesson 92 132 | * Lesson 93 133 | * Lesson 94 134 | * Lesson 95 135 | * Lesson 96 136 | 137 | 138 | -------------------------------------------------------------------------------- /Unit-1/Lesson-1.md: -------------------------------------------------------------------------------- 1 | ## Lesson 1 What is the simplest C program? 最简单的C程序 2 | ### 代码 3 | int main(void) 4 | { 5 | return 0; 6 | } 7 | 8 | ### 知识点 9 | * 数据类型 int 10 | * 函数名 main 11 | * 参数(列表) void 12 | * 返回值 return 13 | 14 | ### C语言 BNF 范式分析 15 | 16 | int main(void) 17 | { 18 | return 0; 19 | } 20 | 21 | 类型声明 声明符 22 | int main(void) 23 | 24 | 复合语句: { 语句 } 25 | { return 0; } 26 | 27 | -------------> translation_unit 翻译单元 28 | 29 | translation_unit : external_decl 30 | 翻译单元 外部声明 31 | 32 | external_decl : function_definition 33 | 外部声明 函数定义 34 | 35 | function_definition : decl_specs declarator compound_stat 36 | 函数定义 声明说明符 声明符 复合语句 37 | 38 | decl_specs : type_spec 39 | 声明说明符 类型说明符 40 | 41 | type_spec : 'void' | 'char' | 'short' | 'int' | 'long' | 'float' 42 | 类型说明符 43 | 44 | -------------> void 类型声明 45 | 46 | declarator : direct_declarator 47 | 声明符 直接声明符 48 | 49 | direct_declarator : id 标识符 50 | 直接声明符 | '(' declarator ')' ' 声明符 ' 51 | | direct_declarator '[' const_exp ']' 直接声明符 [常量表达式] 52 | | direct_declarator '[' ']' 直接声明符 [] 53 | | direct_declarator '(' param_type_list ')' 直接声明符 (形式参数类型表) 54 | | direct_declarator '(' id_list ')' 直接声明符 (标识符表) 55 | | direct_declarator '(' ')' 直接声明符 () 56 | 57 | -------------> main( param_type_list ) 函数声明符 58 | 59 | param_type_list : param_list 形式参数表 60 | 形式参数类型表 | param_list ',' '...' 形式参数表, ... 61 | ; 62 | 63 | param_list : param_decl 形式参数声明 64 | 形式参数表 | param_list ',' param_decl 形式参数表, 形式参数声明 65 | 66 | param_decl : decl_specs declarator 声明说明符 声明符 67 | 形式参数声明 | decl_specs abstract_declarator 声明说明符 抽象声明符 68 | | decl_specs 声明说明符 69 | ; 70 | 71 | decl_specs : storage_class_spec decl_specs 存储类说明符 声明说明符 72 | 声明说明符 | storage_class_spec 存储类说明符 73 | | type_spec decl_specs 类型说明符 74 | | type_spec 类型说明符 75 | | type_qualifier decl_specs 类型限定符 声明说明符 76 | | type_qualifier 类型限定符 77 | ; 78 | 79 | --------------> void 参数类型列表 80 | 81 | compound_stat : '{' decl_list stat_list '}' { 声明表 语句表 } 82 | 复合语句 83 | 84 | --------------> { return 0; } 复合语句 85 | 86 | stat_list : stat 语句 87 | 语句表 | stat_list stat 语句表 语句 88 | 89 | stat : labeled_stat 带标号语句 90 | 语句 | exp_stat 表达式语句 91 | | compound_stat 复合语句 92 | | selection_stat 选择语句 93 | | iteration_stat 循环语句 94 | | jump_stat 跳转语句 95 | 96 | jump_stat : 'goto' id ';' goto 标识符; 97 | 跳转语句 | 'continue' ';' continue; 98 | | 'break' ';' break; 99 | | 'return' exp ';' return 表达式; 100 | | 'return' ';' return 101 | ; 102 | 103 | --------------> return 0; 跳转语句 104 | 105 | ### 扩展 106 | 107 | /* this is the simplest c program */ 108 | 109 | int global = 1; 110 | 111 | int main(void) 112 | { 113 | int local = 2; 114 | 115 | // we return these two varible' summary 116 | return local + global; 117 | } 118 | 119 | ### 知识点 120 | * 变量 variable 121 | - 局部变量 local 122 | - 全局变量 global 123 | * 运算符 operator 124 | - 双目运算符 +,-,*,/ 125 | - 赋值运算符 = 126 | * 注释 comment 127 | - 不能嵌套 /* */ 128 | - 能嵌套 // 129 | * 基本数据类型 130 | - 字符 char 131 | - 短整型 short 132 | - 浮点 float 133 | - 双精度浮点 double 134 | 135 | ### 课堂讨论 136 | * main 函数名是 C 语言的关键字吗? 137 | * 注释可以写在某一行代码的里面吗? 138 | * 全局变量和局部变量取名可以重名吗? 139 | * 所有代码可以写在一行里面吗? 140 | * 把源程序中的空格去掉可以吗? 141 | 142 | ### 课后练习 143 | * 修改代码,使得编译不通过,并举出常见的错误提示和出错原因,越多越好。 144 | 145 | ### 参考资料 146 | * B语言--C语言的前身 147 | - B语言 [http://zh.wikipedia.org/wiki/B语言](http://zh.wikipedia.org/wiki/B语言) 148 | - THE PROGRAMMING LANGUAGE B 149 | - A TUTORIAL INTRODUCTION TO THE LANGUAGE B 150 | - Users' Reference to B 151 | * C语言 152 | * C语言 [http://zh.wikipedia.org/wiki/C语言](http://zh.wikipedia.org/wiki/C语言) 153 | * C语言之父 Dennis Ritchie [http://zh.wikipedia.org/wiki/丹尼斯·里奇](http://zh.wikipedia.org/wiki/丹尼斯·里奇) 154 | * [The Development of the C Language](http://cm.bell-labs.com/who/dmr/chist.html) 155 | * C语言 BNF 范式 156 | 157 | ### 参考资料 158 | * BNF 范式 159 | - 160 | - [http://zh.wikipedia.org/wiki/巴科斯范式](http://zh.wikipedia.org/wiki/巴科斯范式) 161 | * glibc 库 162 | - 163 | - 164 | - 165 | * gcc 编译器 166 | - 167 | - 168 | 169 | ### 名人名言 170 | * Dennis Ritchie (C语言之父) 171 | - “Many of the improvements I introduced when developing C simply looked like a good thing to do.” 172 | 173 | -------------------------------------------------------------------------------- /Unit-1/Lesson-10.md: -------------------------------------------------------------------------------- 1 | ## Lesson 10 Josephus ring 约瑟夫环 2 | #include 3 | 4 | #define ALL_NUM 100 5 | #define COUNT_NUM 3 6 | #define OUT_NUM 3 7 | 8 | /* people id array such as (1,2,3,4,5,6) */ 9 | int people[ALL_NUM]; 10 | 11 | int main(void) 12 | { 13 | int left; /* left people number */ 14 | int pos; /* which pos */ 15 | int step; /* which step */ 16 | int i; 17 | 18 | int counter = 0; 19 | 20 | left = ALL_NUM; 21 | pos = 0; 22 | step = 0; 23 | 24 | /* init id as 1,2,3,4,5,6 */ 25 | for (i = 0; i < ALL_NUM; i++) 26 | people[i] = i + 1; 27 | 28 | /* if there is still people in queue */ 29 | while (left > 0) 30 | { 31 | /* pos++? step++? left--? */ 32 | if (people[pos] > 0) 33 | step++; 34 | 35 | if (step == OUT_NUM && people[pos] != 0) 36 | { 37 | printf("%d out \n", people[pos]); 38 | people[pos] = 0; 39 | left--; 40 | } 41 | 42 | #if 1 43 | pos = ++pos % ALL_NUM; 44 | step = step % COUNT_NUM; 45 | #else 46 | pos++; 47 | if (pos == ALL_NUM) 48 | pos = 0; 49 | 50 | if (step == COUNT_NUM) 51 | step = 0; 52 | #endif 53 | } 54 | 55 | return 0; 56 | } 57 | 58 | ### 语法知识点 59 | * 函数设计 function 60 | * 数据驱动编程 61 | 62 | ### 课堂讨论 63 | * pos 和 step 变量,每次赋值用 if 和 直接赋值,在执行效率有什么不同? 64 | * 在这个算法实现中,留在环里面的人越少,无效的比较次数越多,有什么办法可以优化算法? 65 | * 如何使用数组实现在课堂讨论中想到的优化算法。 66 | 67 | ### 课后练习 68 | * 增加一个变量,用来统计在以上算法执行过程中比较的次数。 69 | * 已知2012年1月1日是星期日,请打印出全年的月历。要求用到函数,数组和循环。 70 | * 用户输入10个数字,对它们进行排序,要求把所有奇数排前面,所有偶数排后面。 71 | 72 | ### 名人名言 73 | * Rob Pike (Go语言之父,和Ken Thompson一起设计了UTF-8编码格式,现Google首席工程师。) 74 | - “Data dominates. If you’ve chosen the right data structures and organized things well, the algorithms will almost always be self-evident. Data structures, not algorithms, are central to programming.” 75 | - “数据压倒一切。如果已经选择了正确的数据结构并且把一切都组织得井井有条,正确的算法也就不言自明。编程的核心是数据结构,而不是算法。” 76 | - “给我看流程图而不让我看(数据)表,我仍会茫然不解;如果给我看(数据)表,通常就不需要流程图了;数据表足够说明问题了。” 77 | -------------------------------------------------------------------------------- /Unit-1/Lesson-11.md: -------------------------------------------------------------------------------- 1 | ## Lesson 11 Calculate the distance between 2 points 求两个坐标点之间的距离 2 | #include 3 | #include 4 | 5 | struct point 6 | { 7 | int x; 8 | int y; 9 | }; 10 | 11 | typedef struct point point_t; 12 | 13 | double calc_distance(point_t p1, point_t p2) 14 | { 15 | int dx = p1.x - p2.x; 16 | int dy = p1.y - p2.y; 17 | 18 | return sqrt(dx * dx + dy * dy); 19 | } 20 | 21 | int main(int argc, char * argv[]) 22 | { 23 | double length; 24 | 25 | point_t p1; 26 | point_t p2 = {200, 100}; 27 | 28 | p1.x = 100; 29 | p1.y = 200; 30 | 31 | length = calc_distance(p1, p2); 32 | 33 | printf("length = %f\n", length); 34 | 35 | return 0; 36 | } 37 | 38 | ### 扩展用法 39 | struct a { 40 | int b; 41 | int c; 42 | }; 43 | 44 | struct a a1 = { 45 | .b = 1, 46 | .c = 2 47 | }; 48 | 49 | struct a a1 = { 50 | b : 1, 51 | c : 2 52 | }; 53 | 54 | struct a a1 = {1, 2}; 55 | 56 | ### 经典范例 57 | /* linux/drivers/char/raw.c */ 58 | static const struct file_operations raw_fops = { 59 | .read = do_sync_read, 60 | .aio_read = generic_file_aio_read, 61 | .write = do_sync_write, 62 | .aio_write = blkdev_aio_write, 63 | .fsync = blkdev_fsync, 64 | .open = raw_open, 65 | .release = raw_release, 66 | .unlocked_ioctl = raw_ioctl, 67 | .llseek = default_llseek, 68 | .owner = THIS_MODULE, 69 | }; 70 | 71 | static const struct file_operations raw_ctl_fops = { 72 | .unlocked_ioctl = raw_ctl_ioctl, 73 | #ifdef CONFIG_COMPAT 74 | .compat_ioctl = raw_ctl_compat_ioctl, 75 | #endif 76 | .open = raw_open, 77 | .owner = THIS_MODULE, 78 | .llseek = noop_llseek, 79 | }; 80 | 81 | 82 | ### 知识点 83 | * 结构体 struct 84 | - 结构体的初始化 85 | * 传结构体参数 86 | - 整体赋值(复制) 87 | * typedef 类型定义 88 | 89 | ### 课堂讨论 90 | * 在 calc_distance 调用时传入的 p1 ,和在 函数实现中出现的 p1 是不是同一个 p1? 91 | * 如果结构体的变量是一个字符数组,那么结构体的赋值,是否会进行一次字符串拷贝? 92 | 93 | ### 课后练习 94 | * 给定一个结构体 point_t 的数组,求出这一组点中,离原点距离最远的那个点。 95 | * 求出上面这一组点中,距离最远的2个点以及它们之间的距离。 96 | * 有5个学生,每个学生有3门课的成绩,用户输入以上数据,包括学号,姓名,三门课成绩(浮点数),请计算出每位学生的总分和平均成绩,并支持用户通过学号和姓名进行查询。 97 | 98 | ### 参考资料 99 | * C99 中关于结构体的初始化方法 100 | - 101 | -------------------------------------------------------------------------------- /Unit-1/Lesson-12.md: -------------------------------------------------------------------------------- 1 | ## Lesson 12 Does your machine use little-endian? 判断机器存储是否小尾端 2 | #include 3 | 4 | union u_tag 5 | { 6 | unsigned char c[4]; 7 | int i; 8 | double d; 9 | } u; 10 | 11 | #define printc( expr ) printf( #expr " = %c \n", expr ) 12 | #define printi( expr ) printf( #expr " = %d \n", expr ) 13 | #define printd( expr ) printf( #expr " = %f \n", expr ) 14 | #define printx( expr ) printf( #expr " = %x \n", expr ) 15 | 16 | int main( int argc, char * argv[] ) 17 | { 18 | printf( "hello, Cruel World! \n" ); 19 | 20 | printf( "sizeof u_tag = %d \n", sizeof(u) ); 21 | printf( "sizeof double = %d \n", sizeof(double) ); 22 | 23 | u.c[0] = '0'; 24 | printf( "u.c[0] = %c \n", u.c[0] ); 25 | printi( u.c[0] ); 26 | printi( u.c[1] ); 27 | printi( u.c[2] ); 28 | printi( u.c[3] ); 29 | printi( u.i ); 30 | printd( u.d ); 31 | 32 | u.i = 0x12345678; 33 | printf( "u.c[0] = %c \n", u.c[0] ); 34 | printx( u.c[0] ); 35 | printx( u.c[1] ); 36 | printx( u.c[2] ); 37 | printx( u.c[3] ); 38 | printx( u.i ); 39 | printd( u.d ); 40 | 41 | return 0; 42 | } 43 | 44 | ### 知识点 45 | * 联合 union 46 | * 字符数组类型 char buf[4] 47 | * 存储格式 big/little endian 48 | * 浮点数格式 (1.00 的存储方式 0x3f800000) 49 | 50 | ### 课堂讨论 51 | * 联合中能够包含结构体吗? 结构体中能够包含联合吗? 52 | * 列举出三种能够使用联合的场合。 53 | 54 | ### 课后练习 55 | * 请用联合定义一个 XModem 协议包。 56 | -------------------------------------------------------------------------------- /Unit-1/Lesson-13.md: -------------------------------------------------------------------------------- 1 | ## Lesson 13 Sorry, your car is restricted today 对不起,你的车今天限行 2 | #include 3 | #include 4 | 5 | enum 6 | { 7 | MONDAY=1, 8 | TUESDAY, 9 | WEDNESDAY, 10 | THURSDAY, 11 | FRIDAY, 12 | SATURDAY, 13 | SUNDAY 14 | }; 15 | 16 | int is_restricted(int num, int today) 17 | { 18 | int ret; 19 | 20 | switch (num) 21 | { 22 | case 0: 23 | case 5: 24 | ret = (today == MONDAY) ? 1 : 0; 25 | break; 26 | 27 | case 1: 28 | case 6: 29 | ret = (today == TUESDAY) ? 1 : 0; 30 | break; 31 | 32 | case 2: 33 | case 7: 34 | ret = (today == WEDNESDAY) ? 1 : 0; 35 | break; 36 | 37 | case 3: 38 | case 8: 39 | ret = (today == THURSDAY) ? 1 : 0; 40 | break; 41 | 42 | case 4: 43 | case 9: 44 | ret = (today == FRIDAY) ? 1 : 0; 45 | break; 46 | 47 | default: 48 | ret = 0; 49 | break; 50 | } 51 | 52 | return ret; 53 | } 54 | 55 | int main(int argc, char *argv[]) 56 | { 57 | char car_num_str[8] = "N2LG20"; 58 | int tail_num; 59 | int result; 60 | 61 | printf("Please input your car number : \n"); 62 | scanf("%s", car_num_str); 63 | 64 | printf("Your car number is <%s> \n", car_num_str); 65 | tail_num = car_num_str[strlen(car_num_str)-1] - '0'; 66 | 67 | printf("the tail number is %d\n", tail_num); 68 | printf("Today is %s\n", __DATE__); 69 | 70 | result = is_restricted(tail_num, MONDAY); 71 | printf("Total your car is %s \n", result? "restricted" : "permitted"); 72 | 73 | return 0; 74 | } 75 | 76 | ### 知识点 77 | * 枚举 enum 78 | * 分支语句 switch-case 79 | - break 用法 80 | - 格式的缩进和对齐 81 | * switch-case 的应用场合 82 | - 状态机编程 83 | - printf 函数实现 84 | 85 | ### 课堂讨论 86 | * 除了示例中的写法,如果不用 switch-case ,解决这个问题还有其他写法吗? 87 | * 如果考虑到每3个月换一次尾号限行制度,这个程序应该怎么改? 88 | 89 | ### 课后练习 90 | * 编写一个程序,统计各个数字,空白字符和其他所有字符出现的次数,以及行数。 91 | * 分析一条格式化打印语句中,打印整数%d,字符%c,字符串%s,地址%p 各自出现的次数。 92 | -------------------------------------------------------------------------------- /Unit-1/Lesson-14.md: -------------------------------------------------------------------------------- 1 | ## Lesson 14 Is there a way out? 判断地图上某点是否有出路 2 | #include 3 | #include 4 | #include 5 | 6 | /* define chessboard size */ 7 | #define ROW 10 8 | #define COL 10 9 | 10 | /* define chessboard using matrix */ 11 | int chessboard[ROW][COL] = { {0} }; 12 | 13 | void init(int board[ROW][COL]) 14 | { 15 | int i, j; 16 | 17 | srand(time(NULL)); 18 | 19 | for (i = 0; i < ROW; i++) 20 | for (j = 0; j < COL; j++) 21 | board[i][j] = rand() % 2; 22 | 23 | return; 24 | } 25 | 26 | /* display chessboard using printf */ 27 | void print(int board[ROW][COL]) 28 | { 29 | int i, j; 30 | 31 | printf("\n"); 32 | printf(" "); 33 | 34 | for (j = 0; j < COL; j++) 35 | printf(" %d", j); 36 | printf("\n"); 37 | 38 | printf(" -"); 39 | for (j = 0; j < COL; j++) 40 | printf(" -"); 41 | 42 | printf("\n"); 43 | for (i = 0; i < ROW; i++) { 44 | printf("%d| ", i); 45 | for (j = 0; j < COL; j++) { 46 | printf("%d ", board[i][j]); 47 | } 48 | printf("\n"); 49 | } 50 | 51 | printf("\n"); 52 | } 53 | 54 | /* test (x, y) is valid before put chess */ 55 | int onboard(int x, int y) 56 | { 57 | if (x >= ROW || x < 0) 58 | return 0; 59 | 60 | if (y >= COL || y < 0) 61 | return 0; 62 | 63 | return 1; 64 | } 65 | 66 | int check(int x, int y) 67 | { 68 | int i = 0; 69 | int counter = 1; 70 | int nx, ny; // next x y 71 | 72 | // up, down, left, right, 73 | int dirx[4] = { -1, 1, 0, 0 }; 74 | int diry[4] = { 0, 0, -1, 1 }; 75 | 76 | counter = 0; 77 | 78 | // 4 directions 79 | for (i = 0; i < 4; i++) 80 | { 81 | nx = x; 82 | ny = y; 83 | 84 | nx += dirx[i]; 85 | ny += diry[i]; 86 | 87 | // if (nx, ny) is out of board, then continue; 88 | if (!onboard(nx, ny)) 89 | continue; 90 | 91 | if (chessboard[nx][ny] == 0) 92 | { 93 | counter++; 94 | printf("there is %d direction (%d, %d) out!\n", counter, dirx[i], diry[i]); 95 | } 96 | } 97 | 98 | return counter; 99 | } 100 | 101 | int main(int argc, char *argv[]) 102 | { 103 | int x = 4, y = 4; 104 | int ways = 0; 105 | 106 | print(chessboard); 107 | init(chessboard); 108 | print(chessboard); 109 | 110 | printf("please input a point position: "); 111 | scanf("%d %d", &x, &y); 112 | printf("point(%d, %d)\n", x, y); 113 | 114 | ways = check(x, y); 115 | printf("Total is %d way out!\n", ways); 116 | 117 | return 0; 118 | } 119 | 120 | ### 知识点 121 | * 二维数组 a[][] 122 | * 随机函数 rand() 123 | 124 | ### 课堂讨论 125 | * dirx 和 diry 的数组在代码易读性上是否还有改进的空间? 126 | * 如果在方向判断上,要加上左上,左下,右上,右下这4个方向,如何修改? 127 | 128 | ### 课后练习 129 | * 请打印杨辉三角形的前10行。打印输出格式可以参考 http://baike.baidu.com/view/298289.htm 130 | -------------------------------------------------------------------------------- /Unit-1/Lesson-15.md: -------------------------------------------------------------------------------- 1 | ## Lesson 15 Count bit 1 in a number 统计一个数二进制表示中1的个数 2 | #include 3 | 4 | int count_bit_1(int n) 5 | { 6 | unsigned int i; 7 | int counter = 0; 8 | 9 | for(i = 0; i < sizeof(int) * 8; i++) 10 | { 11 | if((n >> i) & 0x01) 12 | counter++; 13 | } 14 | return counter; 15 | } 16 | 17 | int main(int argc, char *argv[]) 18 | { 19 | int num; 20 | 21 | printf("please input a number:"); 22 | scanf("%d", &num); 23 | printf("number in hex is 0x%x\n", n); 24 | 25 | printf("%d bit '1' in %d\n", count_bit_1(num), num); 26 | 27 | return 0; 28 | } 29 | 30 | 31 | ### 第2种算法--消去最左侧的1 32 | #include 33 | 34 | int count_bit_1(int n) 35 | { 36 | int counter; 37 | 38 | for (counter = 0; n; counter++) 39 | n &= n-1; 40 | 41 | return counter; 42 | } 43 | 44 | int main(int argc, char *argv[]) 45 | { 46 | int num; 47 | 48 | printf("please input a number:"); 49 | scanf("%d", &num); 50 | printf("number in hex is 0x%x\n", num); 51 | 52 | printf("%d bit '1' in %d\n", count_bit_1(num), num); 53 | 54 | return 0; 55 | } 56 | 57 | ### 第3种算法--二进制数内的加法 58 | #include 59 | 60 | //types and constants used in the functions below 61 | typedef unsigned int uint32; //assume this gives 32-bits 62 | const uint32 m1 = 0x55555555; //binary: 0101... 63 | const uint32 m2 = 0x33333333; //binary: 00110011.. 64 | const uint32 m4 = 0x0f0f0f0f; //binary: 4 zeros, 4 ones ... 65 | const uint32 m8 = 0x00ff00ff; //binary: 8 zeros, 8 ones ... 66 | const uint32 m16 = 0x0000ffff; //binary: 16 zeros, 16 ones ... 67 | const uint32 h01 = 0x01010101; //the sum of 256 to the power of 0,1,2,3... 68 | 69 | //This is a naive implementation, shown for comparison, 70 | //and to help in understanding the better functions. 71 | //It uses 24 arithmetic operations (shift, add, and). 72 | int count_bit_1(unsigned int x) 73 | { 74 | x = (x & m1 ) + ((x >> 1) & m1 ); //put count of each 2 bits into those 2 bits 75 | x = (x & m2 ) + ((x >> 2) & m2 ); //put count of each 4 bits into those 4 bits 76 | x = (x & m4 ) + ((x >> 4) & m4 ); //put count of each 8 bits into those 8 bits 77 | x = (x & m8 ) + ((x >> 8) & m8 ); //put count of each 16 bits into those 16 bits 78 | x = (x & m16) + ((x >> 16) & m16); //put count of each 32 bits into those 32 bits 79 | 80 | return x; 81 | } 82 | 83 | int main(int argc, char *argv[]) 84 | { 85 | int num; 86 | 87 | printf("please input a number:"); 88 | scanf("%d", &num); 89 | printf("number in hex is 0x%x\n", num); 90 | 91 | printf("%d bit '1' in %d\n", count_bit_1(num), num); 92 | 93 | return 0; 94 | } 95 | 96 | ### 知识点 97 | * 位操作 &, |, ~, ^ 98 | - 设置位 set bit 99 | a |= 1<<4; 100 | - 清除位 clear bit 101 | a &= ~(1<<4); 102 | - 测试位 test bit 103 | if (a & (1<<31)) 104 | - 设置位域 set bit-field 105 | a &= ~(0x7<<28); 106 | a |= 0x5<<28; 107 | - 获取位域 get bit-field 108 | if (((a>>28) & 0x7) == 0x5) 109 | * 常见操作 110 | - 不要把 &, | 混淆为 &&, || 111 | 1 & 1 == 1 && 1 112 | 1 & 2 == 0 但是 1 && 2 == ture 同理类似的 5 & 10 == 0 113 | - 取反操作用来构造数 114 | 0xFFFFFFFF == ~0x0 115 | 0xFFFFFFE0 == ~0x1F 116 | - 运算符&,^,| 的优先级比<,>关系运算符和判等运算符 == 要低 117 | 举例: 118 | int status = 0; 119 | if (status & 0x4000 == 0) // 条件成立,还是不成立? 120 | * 优化算法效率 121 | - n & n-1 妙用 122 | - 二进制数内的加法 123 | 124 | ### 课堂讨论 125 | * 与第1个算法相比,第2个算法有什么优点? 126 | * 第3个算法的时间复杂度是多少? 它背后的思想是什么? 127 | 128 | ### 课后练习 129 | * 请写出可以进行位操作的 set_bit, get_bit 接口 130 | - set_bit(int num, int pos, int v); 131 | - get_bit(int num, int pos); 132 | * 用位运算实现字符的大小写转换 (两种方法:异或,测试后修改) 133 | - 要求:输入大写的字符转为小写,输入小写的字符转为大写; 134 | * 用位运算实现对一个无符号整型的二进制打印,八进制打印,十六进制打印 135 | - 要求: 136 | int print_bin(int a); 137 | int print_oct(int a); 138 | int print_hex(int a); 139 | 140 | a = 31 141 | 二进制打印 0000 0000 ... 0001 1111 142 | 八进制打印 0 0 0 ... 0 3 7 143 | 十六进制打印 00 00 00 1F 144 | 145 | ## Bit-Field 位域操作 146 | #include 147 | 148 | struct flag 149 | { 150 | unsigned int is_keyword : 1; 151 | unsigned int is_extern : 1; 152 | unsigned int is_static : 1; 153 | unsigned int is_mid : 4; 154 | unsigned int is_high : 1; 155 | unsigned int is_highest : 30; 156 | } flags; 157 | 158 | int main( int argc, char * argv[] ) 159 | { 160 | printf( "hello, Cruel World! \n" ); 161 | 162 | flags.is_keyword = 1; 163 | flags.is_extern = 1; 164 | flags.is_high = 1; 165 | 166 | flags.is_mid = 2; 167 | 168 | printf( "flags = 0x%x \n", flags ); 169 | printf( "sizeof flags = 0x%x \n",sizeof(flags) ); 170 | 171 | return 0; 172 | } 173 | 174 | ### 扩展应用 175 | /* include/linux/tcp.h */ 176 | struct tcphdr { 177 | __be16 source; 178 | __be16 dest; 179 | __be32 seq; 180 | __be32 ack_seq; 181 | #if defined(__LITTLE_ENDIAN_BITFIELD) 182 | __u16 res1:4, 183 | doff:4, 184 | fin:1, 185 | syn:1, 186 | rst:1, 187 | psh:1, 188 | ack:1, 189 | urg:1, 190 | ece:1, 191 | cwr:1; 192 | #elif defined(__BIG_ENDIAN_BITFIELD) 193 | __u16 doff:4, 194 | res1:4, 195 | cwr:1, 196 | ece:1, 197 | urg:1, 198 | ack:1, 199 | psh:1, 200 | rst:1, 201 | syn:1, 202 | fin:1; 203 | #else 204 | #error "Adjust your defines" 205 | #endif 206 | __be16 window; 207 | __sum16 check; 208 | __be16 urg_ptr; 209 | }; 210 | 211 | ### 知识点 212 | * 位域 bit-field 213 | * 大端和小端 Big-Endian/Little-Endian 214 | 215 | ### 课堂讨论 216 | * 位域和之前学过的结构体,有何异同之处? 217 | * 位域在哪些场合下可以适用? 218 | - 码流结构 stream 219 | - 传输协议结构 protocal 220 | - 特殊功能寄存器设置 SFR 221 | 222 | ### 课后练习 223 | * 用位域操作实现随机生成无重复的10个数字,要求不允许使用数组 224 | - 提示:随机数用 rand() 函数,用一个整型数的bit0-bit9来记录已经产生的数字 225 | 226 | ### 名人名言 227 | * Donald Ervin Knuth 228 | - Premature optimization is the root of all evil. (过早优化是万恶之源) 229 | -------------------------------------------------------------------------------- /Unit-1/Lesson-16.md: -------------------------------------------------------------------------------- 1 | ## Lesson 16 How to strcpy 字符串拷贝 2 | #include 3 | #include 4 | 5 | #if 1 6 | char * my_strcpy(char * dst, const char * src) 7 | { 8 | assert(dst != NULL && src != NULL); 9 | 10 | char * ret = dst; 11 | 12 | while ((*dst++ = *src++) != '\0'); 13 | 14 | return ret; 15 | } 16 | #else 17 | char * my_strcpy(char * dst, const char * src) 18 | { 19 | char * ret = dst; 20 | 21 | while((*dst++ = *src++) != '\0'); 22 | 23 | return ret; 24 | } 25 | #endif 26 | 27 | int main(int argc, char *argv[]) 28 | { 29 | char d[32]; 30 | char s[32] = "Hello World"; 31 | 32 | printf("s = %s\n", s); 33 | 34 | // my_strcpy(d, s); 35 | printf("d = %s\n", my_strcpy(d, s)); 36 | 37 | return 0; 38 | } 39 | 40 | ### 算法优化1 - 减少对 dst 指针变量的存取次数 41 | #include 42 | 43 | char * my_strcpy(char * dst, const char * src) 44 | { 45 | assert(dst != NULL && src != NULL); 46 | 47 | char *s = (char *)src; 48 | int delt = dst - src; 49 | 50 | while ((s[delt] = *s++) != '\0'); 51 | 52 | return dst; 53 | } 54 | 55 | 出处: 林锐《高质量程序设计指南》 56 | 57 | ### 算法优化2 - 内联函数和内嵌汇编 58 | extern inline void * memcpy(void * dest,const void * src, int n) 59 | { 60 | __asm__("cld\n\t" 61 | "rep\n\t" 62 | "movsb" 63 | ::"c" (n),"S" (src),"D" (dest) 64 | :"cx","si","di"); 65 | return dest; 66 | } 67 | 68 | 出处: Linux 0.0.1 源码 69 | 70 | ### 算法优化3 - 基于 PAGE/WORD/BYTE 对齐拷贝 71 | #include 72 | #include 73 | #include 74 | 75 | #undef memcpy 76 | 77 | void * 78 | memcpy (dstpp, srcpp, len) 79 | void *dstpp; 80 | const void *srcpp; 81 | size_t len; 82 | { 83 | unsigned long int dstp = (long int) dstpp; 84 | unsigned long int srcp = (long int) srcpp; 85 | 86 | /** Copy from the beginning to the end. */ 87 | 88 | /** If there not too few bytes to copy, use word copy. */ 89 | if (len >= OP_T_THRES) 90 | { 91 | /** Copy just a few bytes to make DSTP aligned. */ 92 | len -= (-dstp) % OPSIZ; 93 | BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ); 94 | 95 | /** Copy whole pages from SRCP to DSTP by virtual address manipulation, 96 | as much as possible. */ 97 | 98 | PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len); 99 | 100 | /** Copy from SRCP to DSTP taking advantage of the known alignment of 101 | DSTP. Number of bytes remaining is put in the third argument, 102 | i.e. in LEN. This number may vary from machine to machine. */ 103 | 104 | WORD_COPY_FWD (dstp, srcp, len, len); 105 | 106 | /** Fall out and copy the tail. */ 107 | } 108 | 109 | /** There are just a few bytes to copy. Use byte memory operations. */ 110 | BYTE_COPY_FWD (dstp, srcp, len); 111 | 112 | return dstpp; 113 | } 114 | libc_hidden_builtin_def (memcpy) 115 | 116 | ### 算法优化4 - 基于4字节对齐的拷贝 117 | #define UNALIGNED(x,y) (((unsigned long)x & (sizeof (unsigned long)-1)) ^ ((unsigned long)y & (sizeof (unsigned long)-1))) 118 | #define STRALIGN(x) (((unsigned long)x&3)?4-((unsigned long)x&3):0) 119 | # define MKW(x) (x|x<<8|x<<16|x<<24) 120 | # define GFC(x) ((x)&0xff) 121 | # define INCSTR(x) do { x >>= 8; } while (0); 122 | 123 | char * 124 | strcpy (char *s1, const char *s2) 125 | { 126 | char *res = s1; 127 | #ifdef WANT_SMALL_STRING_ROUTINES 128 | while ((*s1++ = *s2++)); 129 | return (res); 130 | #else 131 | int tmp; 132 | unsigned long l; 133 | 134 | if (UNALIGNED(s1, s2)) { 135 | while ((*s1++ = *s2++)); 136 | return (res); 137 | } 138 | if ((tmp = STRALIGN(s1))) { 139 | while (tmp-- && (*s1++ = *s2++)); 140 | if (tmp != -1) return (res); 141 | } 142 | 143 | while (1) { 144 | l = *(const unsigned long *) s2; 145 | if (((l - MKW(0x1ul)) & ~l) & MKW(0x80ul)) { 146 | while ((*s1++ = GFC(l))) INCSTR(l); 147 | return (res); 148 | } 149 | *(unsigned long *) s1 = l; 150 | s2 += sizeof(unsigned long); 151 | s1 += sizeof(unsigned long); 152 | } 153 | #endif 154 | } 155 | 156 | 157 | 出处:glibc 库函数实现 158 | * 159 | * 160 | * 汇编实现--基本思路是实现好1,2,4,8…字节的硬代码,根据实际字节数做跳转,循环前根据cache line状态做prefetch 161 | 162 | 163 | 164 | ### 尚未看懂的优化实现 - 内核3.6.7代码实现 165 | * 166 | * 167 | 168 | 169 | ### 知识点 170 | * 指针 171 | - 字符指针 172 | * 字符指针 vs 字符数组 173 | 174 | 175 | ### 课堂讨论 176 | * 当拷贝函数参数 dst 和 src 内容重叠时应该怎么办呢? 177 | - 参考阅读 178 | * 考虑到内存数据总线是32位,每4字节进行读写内存时候的效率最高,程序应该怎么改? 179 | - 参考阅读 180 | - 181 | - libc代码分析 182 | * char s[32] = "Hello World"; 修改为 char * s = "Hello World"; 有何区别? 183 | - 思路提示: 从两者的存储分配,读写权限,初始化实现,执行时效率进行分析 184 | * 怎样写出一个标准规范的strcpy函数? 185 | - 编程风格 186 | - 出错处理 187 | - 算法效率(用于提高性能) 188 | 189 | ### 课后练习 190 | * 请用指针实现对一个数组的调整,要求奇数在左边,偶数在右边。 要求: 尽可能不占用额外的存储空间。 191 | * 请结合 strcpy 的实现,给出 strlen 的实现。要求:考虑内存对齐和算法执行效率。 192 | 193 | 194 | # 新浪微博大讨论 195 | ## @Tan_yb 196 | 对@亚嵌李明老师 说:老师我发现一个问题:内核和glibc的memcpy比我们自已写的性能高这么多。 197 | 198 | Tan_yb:参考http://t.cn/zjyVHFq 进行了优化http://t.cn/zjyVHFG memcpy执行效率果然快了很多,我发现定义的结构体size达到64个字节就应该是效率执行的最大化。 199 | 200 | ## @亚嵌李明老师 201 | glibc 里面对内存的读写考虑了对齐问题,一般是以字WORD对齐进行整块拷贝,效率应该能够提高4倍左右。另外也考虑了以页为单位进行整页拷贝。 详见 http://t.cn/zjyyuF5 http://t.cn/zjyyuFt 202 | 203 | 204 | ## @Stanley文威 205 | memcpy可是软件优化和CPU架构相结合的典型例子。WORD对齐,cacheline对齐,预取等等都在里面,我记得我有好几个同事优化memcpy优化了好久。属于计算机里的微雕艺术。//@翁恺BA5AG: 呵呵,昨天求计的C课正好讲到这个,要强迫他们养成凡事尽量使用现成代码的习惯 206 | 207 | 关于体系架构和软件优化,还有个故事。以前某天某公司的某个加速库就要发布了,大家发现性能降了20%,大家都抓狂了。这种加速库被优化了n年,各个边边角角被优化了好几遍,20%的性能下降简直是不可想像的,于是大家郁闷的加班找原因。 208 | 209 | 最后发现玄机在Makefile里,Makefile里最关键的一句就是$(CC) -o xxx.a a.o b.o c.o ... z.o, 一个工程师顺手把这行改成$(CC) -o xxx.a a.o c.o b.o ... z.o !?! 原来这样一行修改改变了某几个函数的内存位置,恰巧让他们占用了同几个I$的slot,于是I$ miss飙高,性能下降。(continue) 210 | 211 | 这时候大家才知道为了避免不必要的i$ miss,第一个写这个Makefile的姐姐花了很长时间来人肉调整object文件的次序。这可是全排列哦。这JJ当时已经离开公司了,只留下美丽的传说。。。。再后来我们好像在gcc里做了这种优化,再具体的细节我也忘了,你懂的 212 | 213 | 214 | ## @宋宝华Barry 215 | memcpy非常讲究,要充分考虑指令集,cacheline,word对齐等.可看arch/arm/lib/memcpy.S和copy_template.S//@翁恺BA5AG: //@Stanley文威: memcpy可是软件优化和CPU架构相结合的典型例子。WORD对齐,cacheline对齐,预取等等都在里面,我记得我有好几个同事优化memcpy优化了好久。属于计算机里的微雕艺术。 (11月21日 22:07) 216 | 217 | 宋宝华Barry:回复@Tan_yb: 方法错. memcpy没人拿C语言搞的,都是根据每个arch写汇编。你用C,就依赖于toolchain是否能转化为正确指令集。//@Tan_yb:参考http://t.cn/zjyVHFq 进行了优化http://t.cn/zjyVHFG memcpy执行效率果然快了很多,我发现定义的结构体size达到64个字节就应该是效率执行的最大化 218 | 219 | 宋宝华Barry:前一段很准确,后一段属误解。内核dma的memcpy发生于io与mem或者GPU等的mem与mem,不发生于典型memcpy,而且目的也不是cache miss更少,更不一定是加速。//@翁恺BA5AG: //@CSK_: x86上的memcpy库函数会使用SSE指令加速,arm上的会用NEON指令加速。内核态甚至会用DMA加速,同时cache miss也小 220 | 221 | 222 | ## @CSK_ 223 | x86上的memcpy库函数会使用SSE指令加速,arm上的会用NEON指令加速。内核态甚至会用DMA加速,同时cache miss也小//@翁恺BA5AG: 不同的CPU实现肯定不同,x86的和ARM不会一样 //@宋宝华Barry:memcpy非常讲究,要充分考虑指令集,cacheline,word对齐等.可看arch/arm/lib/memcpy.S和copy_template.S 224 | 225 | ## @蔡华林CHL 226 | 回复@亚嵌李明老师:可以找找cache miss和false sharing相关的文章看看,当你的程序有大量循环时一不小心就会遇上,可以通过vtune之类工具发现。现在cpu是很快,显得内存访问的latency越来越无法忍受了,貌似是几乎上百纳秒级别,一次内存装载到cache的时间够执行很多语句了 227 | 228 | 但是一般人写程序不会注意到这个问题吧,前段时间想改进hash join,每次算好哈希入口去访问都会引起一次cache miss,性能就只有遍历的1/10,于是想显式发预取指令,这样得弄个窗口处理当前项时预取下一项,由于之前设计问题缓存会增加额外的memcpy和组装开销,抵消掉大部分预取带来的好处… 229 | 230 | 我以前还专门被叫去研究过这个函数,在某些特殊情况下能做到自己写的更快,因为可以被inline掉,前提是对齐之类要注意,改写成word的赋值语句,还有些情况下应该使用gcc内置的builtin的memcpy或者vc的intrinsic,这样编译器也能帮省掉函数调用开销 231 | 232 | glibc 2.9有个500多行的memcpy汇编,这里有源码:http://t.cn/zjUwD43,不知道最新的代码有没有改过,我电脑上07年载的已经是这个版本了,基本思路应该就是实现好1,2,4,8…字节的硬代码,根据实际字节数做跳转,循环前根据cache line状态做prefetch 233 | 234 | ## @ChongHead 235 | X86的glibc memcpy大致有4k行汇编代码,性能差别不是一点点的,牛人作者在上海 //@CSK_: x86上的memcpy库函数会使用SSE指令加速,arm上的会用NEON指令加速。内核态甚至会用DMA加速,同时cache miss也小//@翁恺BA5AG: 不同的CPU实现肯定不同,x86的和ARM不会一样 //@宋宝华Barry:memcpy 236 | 237 | ## @曦图吴昊 238 | 我们以前做这种优化都是根据CPU的cycle设计算法的 //@CSK_:x86上的memcpy库函数会使用SSE指令加速,arm上的会用NEON指令加速。内核态甚至会用DMA加速,同时cache miss也小 //@翁恺BA5AG: 不同的CPU实现肯定不同,x86的和ARM不会一样 239 | 240 | ## @孙志岗Sunner 241 | 从memcpy到filecopy的优化,足够学到好大一箩筐了//@Stanley文威: memcpy可是软件优化和CPU架构相结合的典型例子。WORD对齐,cacheline对齐,预取等等都在里面,我记得我有好几个同事优化memcpy优化了好久。属于计算机里的微雕艺术。//@翁恺BA5AG: 要强迫他们养成凡事尽量使用现成代码的习惯 242 | 243 | -------------------------------------------------------------------------------- /Unit-1/Lesson-17.md: -------------------------------------------------------------------------------- 1 | ## Lesson 17 Count words in an artitle 统计单词个数 2 | #include 3 | 4 | int get_input_type(char c) 5 | { 6 | if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') 7 | return 1; 8 | 9 | return 0; 10 | } 11 | 12 | int main(void) 13 | { 14 | char * str = "Don't ask what your country can do for you, but ask what you can do for your country."; 15 | char c; 16 | 17 | int state = 0; // init state 18 | int input = 0; // 0: space 1: alpha 19 | int counter = 0; 20 | 21 | printf("hello, count how many words in string:\n"); 22 | printf("<%s>\n", str); 23 | 24 | while ((c = *str++) != '\0') 25 | { 26 | input = get_input_type(c); 27 | 28 | if (state == 0 && input == 1) 29 | state = 1; 30 | else if (state == 1 && input == 0) 31 | { 32 | counter++; 33 | state = 0; 34 | } 35 | } 36 | 37 | printf("find %d words.\n", counter); 38 | 39 | return 0; 40 | } 41 | 42 | ### 知识点 43 | * 字符串指针用法 44 | * 状态机编程 45 | * switch-case 用法 46 | 47 | ### 课堂讨论 48 | * 为何要设计出 get_input_type() 这个函数,这样做有什么好处? 49 | * 如果不引入 state 变量,则程序写出来可能会是什么样的结构?与之相比是简单了还是复杂了? 50 | * 如果把输入类型和当前状态以及下一个状态做成一张表,会是什么样子? 51 | 52 | ### 课后练习 53 | * 如果需要把发现的单词进行保存和输出,则程序可以怎样简化? 54 | * 如果该程序不用 if-else 改用 switch-case ,应该如何实现? 55 | * 如果该程序不是统计单词的个数,而是统计数字的个数,应该如何修改? 56 | 57 | -------------------------------------------------------------------------------- /Unit-1/Lesson-18.md: -------------------------------------------------------------------------------- 1 | ## Lesson 18 My printf 实现 printf 2 | #include 3 | 4 | void putchar_hex(char c) 5 | { 6 | const char * hex = "0123456789ABCDEF"; // good 7 | //char hex[] = "0123456789ABCDEF"; bad! 8 | 9 | putchar(hex[(c & 0xf0)>>4]); 10 | putchar(hex[(c & 0x0f)>>0]); 11 | //putchar(' '); 12 | } 13 | 14 | void putint_hex(int a) 15 | { 16 | putchar_hex( (a>>24) & 0xFF ); 17 | putchar_hex( (a>>16) & 0xFF ); 18 | putchar_hex( (a>>8) & 0xFF ); 19 | putchar_hex( (a>>0) & 0xFF ); 20 | } 21 | 22 | char * itoa(int num, char * buf) 23 | { 24 | int i = 0; 25 | int len = 0; 26 | 27 | do 28 | { 29 | buf[i++] = num % 10 + '0'; 30 | num /= 10; 31 | } while (num); 32 | buf[i] = '\0'; 33 | 34 | len = i; 35 | for (i = 0; i < len/2; i++) 36 | { 37 | char tmp; 38 | tmp = buf[i]; 39 | buf[i] = buf[len-i-1]; 40 | buf[len-i-1] = tmp; 41 | } 42 | 43 | return buf; 44 | } 45 | 46 | static int myputs(const char * s) 47 | { 48 | while (*s) 49 | putchar(*s++); 50 | 51 | return 0; 52 | } 53 | 54 | #if 0 55 | #include 56 | #else 57 | typedef int * va_list; 58 | #define va_start(ap, A) (ap = (int *)&(A) + 1) 59 | #define va_arg(ap, T) (*(T *)ap++) 60 | #define va_end(ap) ((void)0) 61 | #endif 62 | 63 | static char buf[100]; 64 | 65 | int myprintf(const char * format, ...) 66 | { 67 | char c; 68 | 69 | va_list ap; 70 | 71 | va_start(ap, format); 72 | 73 | while ((c = *format++) != '\0') 74 | { 75 | switch (c) 76 | { 77 | case '%': 78 | c = *format++; 79 | 80 | switch (c) 81 | { 82 | char ch; 83 | char * p; 84 | int a; 85 | 86 | case 'c': 87 | ch = va_arg(ap, int); 88 | putchar(ch); 89 | break; 90 | case 's': 91 | p = va_arg(ap, char *); 92 | myputs(p); 93 | break; 94 | case 'x': 95 | a = va_arg(ap, int); 96 | putint_hex(a); 97 | break; 98 | case 'd': 99 | a = va_arg(ap, int); 100 | itoa(a, buf); 101 | myputs(buf); 102 | break; 103 | default: 104 | break; 105 | } 106 | break; 107 | 108 | default: 109 | putchar(c); 110 | break; 111 | } 112 | } 113 | 114 | return 0; 115 | } 116 | 117 | int main(void) 118 | { 119 | myprintf("test: %c, %s, %d, 0x%x\n", 'A', "abcdef", 11, 0x23); 120 | 121 | return 0; 122 | } 123 | 124 | ### 语法知识点 125 | * printf 的函数原型 126 | * typedef 类型声明的用法 127 | * va_start, va_arg, va_end 3个宏的实现 128 | * switch-case 语句的嵌套用法 129 | * 指针的指针 用法 130 | 131 | ### 课堂讨论 132 | * printf 的原型,参数和返回值各是什么? 133 | * 为何用 %c 打印时,传入 my_va_arg 的参数是一个 int 类型? 134 | * 当前栈帧的位置是如何判别的? 它和哪些因素有关? 135 | 136 | ### 课后练习 137 | * 请实现一个可变长度参数的 max 函数,可以求出任意多传入参数中的最大值。 138 | 例如 max(3, 100, 200, 300) 返回 300; max(6, 10, 20, 30, 40, 50, 60) 返回 60 139 | * 请在 myprintf 的基础上,实现一个 mysprintf 函数。 140 | -------------------------------------------------------------------------------- /Unit-1/Lesson-19.md: -------------------------------------------------------------------------------- 1 | ## Lesson 19 Shell command parser 命令解释器 2 | #include 3 | #include 4 | 5 | int shell_parse(char * buf, char * argv[]) 6 | { 7 | int argc = 0; 8 | int state = 0; 9 | 10 | while (*buf) 11 | { 12 | if (*buf != ' ' && state == 0) 13 | { 14 | argv[argc++] = buf; 15 | state = 1; 16 | } 17 | 18 | 19 | if ((*buf == ' ') && state == 1) 20 | { 21 | *buf = '\0'; 22 | state = 0; 23 | } 24 | 25 | buf++; 26 | } 27 | 28 | return argc; 29 | } 30 | 31 | int do_cmd(int argc, char ** argv) 32 | { 33 | int i; 34 | 35 | printf("argc = %d\n", argc); 36 | 37 | for (i = 0; i < argc; i++) 38 | printf("argv[%d]: <%s>\n", i, argv[i]); 39 | 40 | return 0; 41 | } 42 | 43 | int do_add(int argc, char ** argv) 44 | { 45 | printf("help: this is a add function with %d args\n", argc - 1); 46 | 47 | return 0; 48 | } 49 | 50 | int do_sub(int argc, char ** argv) 51 | { 52 | printf("ls: this is a sub function with %d args\n", argc - 1); 53 | 54 | return 0; 55 | } 56 | 57 | int (*pf)(int argc, char ** argv); 58 | 59 | int main(void) 60 | { 61 | char buf[64]; 62 | int argc = 0; 63 | char * argv[10]; 64 | 65 | printf("$ "); 66 | fgets(buf, 64, stdin); 67 | buf[strlen(buf)-1] = '\0'; 68 | printf("<%s>\n", buf); 69 | 70 | argc = shell_parse(buf, argv); 71 | 72 | pf = do_cmd; 73 | if (strcmp(argv[0], "add") == 0) 74 | pf = do_add; 75 | 76 | if (strcmp(argv[0], "sub") == 0) 77 | pf = do_sub; 78 | 79 | pf(argc, argv); 80 | //callback(pf,argc, argv); 81 | 82 | return 0; 83 | } 84 | 85 | ### 语法知识点 86 | * 指针数组 87 | * 指向指针的指针 88 | * 函数指针 89 | 90 | ### 课堂讨论 91 | * gets, scanf 和 fgets 在使用中有什么区别?需要注意什么? 92 | * 函数指针类型,如果用 typedef 怎么声明? 93 | * 指针数组 char * argv[10] 和指向指针的指针 char ** argv 有何区别? 94 | 95 | ### 课后练习 96 | * 修改这个程序,使得它能够支持 add 和 sub 命令,可以实现整数的加法和减法。 97 | * 如果把最后的注释打开,通过 callback 函数来调用 pf 函数指针所指向的函数,请实现这个回调函数。 98 | * 分别实现整数和浮点数的加法函数 add_int() 和 add_float() ,在命令解释器利用 void * 函数指针来实现两种类型数的加法命令 add 99 | * 通过函数指针数组,可以实现命令解释器的命令自动匹配和执行,请实现这个想法。提示:采用结构体数组来实现。 100 | 101 | 102 | -------------------------------------------------------------------------------- /Unit-1/Lesson-2.md: -------------------------------------------------------------------------------- 1 | ## Lesson 2 Lets say hello to world 打印输出 2 | ### 代码 3 | #include 4 | 5 | int main(void) 6 | { 7 | printf("hello, world!\n"); 8 | return 0; 9 | } 10 | 11 | ### 知识点 12 | * 预处理符 # 13 | * 头文件 .h 14 | * 字符串常量 const string 15 | * 转义字符 \\n 16 | 17 | ### 扩展练习 18 | #include 19 | 20 | extern int __executable_start; 21 | extern int _start; 22 | 23 | extern char etext[]; 24 | extern char edata[]; 25 | 26 | int global = 100; 27 | 28 | int main(void) 29 | { 30 | printf("hello, everyone!\n"); 31 | 32 | printf("__executable_start= %p\n", &__executable_start); 33 | printf("_start = %p\n", &_start); 34 | printf("main = %p\n", main); 35 | printf("text segment end at %p\n\n", etext); 36 | 37 | printf("global at %p\n", &global); 38 | printf("data segment end at %p\n", edata); 39 | 40 | return 0; 41 | } 42 | 43 | ### 输出结果 44 | input: 無 45 | output: 46 | hello, everyone! 47 | __executable_start= 0x8048000 48 | _start = 0x8048450 49 | main = 0x8048530 50 | text segment end at 0x80486b8 51 | 52 | global at 0x804a01c 53 | data segment end at 0x804a020 54 | 55 | ### 知识点 56 | * 取地址符 & 57 | * 格式化输出 %d %x %p %c %s %% 58 | * 可变长度参数 ... 59 | * 外部变量 extern 60 | * 强制类型转换 (int) 61 | 62 | ### 课堂讨论 63 | * 包含头文件 stdio.h 就是包含我们所说的库函数吗? 64 | * %x 和 %p 在打印变量地址时,有何区别? 65 | * 如果printf的参数,多于或者少于 % 的个数,会怎么样? 66 | * 如果不包含 stdio.h 头文件,则会出错吗? 如何解决? 67 | * 全局变量和局部变量没有初始化值,则打印的结果会怎样? 68 | 69 | ### 课后练习 70 | * 修改代码,打印连续的3个全局变量和3个局部变量的地址,看看有何规律? 71 | * 修改代码,通过强制类型转换,打印一下 &global + 1 的值是多少? 72 | * 修改代码,看看如果把 global 定义为 char, short, float 类型会有什么不同? 73 | 74 | -------------------------------------------------------------------------------- /Unit-1/Lesson-20.md: -------------------------------------------------------------------------------- 1 | ## Lesson 20 Preprocessor 预处理器实现 2 | ### delcomment.c 3 | 4 | #include 5 | 6 | /* abcd */ 7 | // abcd 8 | 9 | int get_input_type(char c) 10 | { 11 | // deal with /* */ 12 | if (c == '/') 13 | return 1; 14 | 15 | if (c == '*') 16 | return 2; 17 | 18 | // deal with // 19 | if (c == '\n') 20 | return 3; 21 | 22 | // deal with '/' 23 | if (c == '\'') 24 | return 4; 25 | 26 | // deal with '\\' 27 | if (c == '\\') 28 | return 5; 29 | 30 | return 0; 31 | } 32 | 33 | #define debug(fmt, args...) fprintf(stderr, fmt, ##args) 34 | 35 | int main(void) 36 | { 37 | int state = 0; 38 | 39 | while (1) 40 | { 41 | char c; 42 | int input; 43 | 44 | c = getchar(); 45 | input = get_input_type(c); 46 | 47 | if (c == EOF) 48 | break; 49 | 50 | debug("%c", c); 51 | 52 | /* ABCD */ 53 | if (state == 0 && input == 1) // "/ 54 | { 55 | state = 1; 56 | } 57 | else 58 | if (state == 0 && input == 4) // "abc' 59 | { 60 | state = 5; 61 | putchar(c); 62 | } 63 | else 64 | if (state == 1 && input == 1) // "// 65 | { 66 | state = 4; 67 | } 68 | else 69 | if (state == 1 && input == 2) // "/* 70 | { 71 | state = 2; 72 | } 73 | else 74 | if (state == 2 && input == 0) // "/*abc 75 | { 76 | state = 2; 77 | } 78 | else 79 | if (state == 2 && input == 2) // "/*abc* 80 | { 81 | state = 3; 82 | } 83 | else 84 | if (state == 3 && input == 1) // "/*abc*/ 85 | { 86 | state = 0; 87 | } 88 | else 89 | if (state == 3 && input == 0) // "/*abc*abc 90 | { 91 | state = 2; 92 | } 93 | else 94 | if (state == 4 && input == 3) // "// abcd \n 95 | { 96 | state = 0; 97 | putchar(c); 98 | } 99 | else 100 | if (state == 5 && input == 4) // "abc'/' 101 | { 102 | state = 0; 103 | putchar(c); 104 | } 105 | else 106 | if (state == 5 && input == 5) // "abc'\/ 107 | { 108 | state = 6; 109 | putchar(c); 110 | } 111 | else 112 | if (state == 6 && input == 4) // "abc'\' 113 | { 114 | state = 5; 115 | putchar(c); 116 | } 117 | else 118 | if (state == 6 && input == 5) // "abc'vv 119 | { 120 | state = 5; 121 | putchar(c); 122 | } 123 | else 124 | if (state == 6 && input == 0) // "abc'\' 125 | { 126 | state = 5; 127 | putchar(c); 128 | } 129 | else 130 | if (state == 0 || state == 5) 131 | putchar(c); 132 | 133 | debug(" input=%d, /* abcd */ state=%d\n", input, state); 134 | } 135 | 136 | 137 | return 0; 138 | } 139 | 140 | ### 语法知识点 141 | * 二维数组 142 | * 函数指针 143 | * 二维函数指针数组 144 | * 结构体数组 145 | * debug 调试宏 146 | 147 | ### 课堂讨论 148 | * 用 if-else 的结构实现状态机有什么好处? 能否有 switch-case 来实现? 149 | * 请讨论有多少种判别注释的例外情况,考虑有单引号,双引号,转移字符,反斜杠等因素。 150 | 151 | ### 课后练习 152 | * 在C语言去注释的问题中,对于双引号字符串中的 /* */ 注释没有进行判别,请重新设计状态机实现之。 153 | * 在宏定义替换问题中,对于带参数的宏没有进行处理,请重新设计状态机实现之。 154 | * 在条件编译替换问题中,对于 #else 的情况没有判别,请重新设计状态机实现之。 155 | * 预处理问题中还有一个 #include 没有实现,请参考 #if/#endif 状态机的构造方法,自行实现之。 156 | 157 | 158 | 159 | -------------------------------------------------------------------------------- /Unit-1/Lesson-21.md: -------------------------------------------------------------------------------- 1 | ## Lesson 21 Lexical analysis 词法分析器实现 2 | 3 | #include 4 | #include "yy_nxt.c" 5 | #include "yy_accept.c" 6 | 7 | #define debug(fmt, args...) fprintf(stderr, fmt, ##args) 8 | 9 | int main(void) 10 | { 11 | int state = 1; 12 | char buf[64]; 13 | int i = 0; 14 | 15 | while (1) 16 | { 17 | char c; 18 | 19 | c = getchar(); 20 | if (c == EOF) 21 | break; 22 | 23 | buf[i++] = c; 24 | 25 | debug("\tstate = %d, ", state); 26 | 27 | state = yy_nxt[state][c]; 28 | 29 | debug("c = <%c>, new state = %d\n", c, state); 30 | 31 | if (state < 0) 32 | { 33 | int act = 0; 34 | 35 | state = -state; 36 | act = yy_accept[state]; 37 | buf[i-1] = '\0'; 38 | 39 | // 1: \n 21: space 40 | if (!(act == 1 || act == 21)) 41 | printf("Pattern %d found! <%s>\n", act, buf); 42 | i = 0; 43 | 44 | state = 1; 45 | ungetc(c, stdin); 46 | } 47 | } 48 | 49 | return 0; 50 | } 51 | 52 | 约减转换表格,原来二维的转换表to一维数组 base/default/check/next 53 | 54 | 55 | 56 | 57 | 58 | 59 | 注释flex生成代码 60 | 61 | 62 | input/output/puton 字符串匹配问题 63 | 64 | 65 | 66 | ### 语法知识点 67 | * 二维数组 68 | * 二维函数指针数组 69 | * 状态机编程之“机制和策略的分离” 70 | 71 | ### 课堂讨论 72 | * new_state 变量是否是必须的,如果去掉程序应该怎么改? 73 | 74 | ### 课后练习 75 | * 请根据第一节课介绍的 BNF 范式,对于词法分析器处理的结果,进行语法归约,看看是否满足C语法要求。 76 | 77 | 78 | -------------------------------------------------------------------------------- /Unit-1/Lesson-22.md: -------------------------------------------------------------------------------- 1 | ## Lesson 22 Guess number in my hand 猜数游戏 2 | 猜数游戏:电脑随机产生4位数,然后用户输入4位数,电脑告诉你是?A?B 3 | 请你最后猜出电脑的4位数是多少? 4 | (A表示位置和数字都对,B表示位置不对,数字对) 5 | 6 | * 语法知识点 7 | - 基本输入输出 8 | - 字符串转整数 9 | - 一维数组 10 | - while/for/if/else/break 11 | - 函数设计 12 | - 二层循环 13 | - 位操作 14 | -------------------------------------------------------------------------------- /Unit-1/Lesson-23.md: -------------------------------------------------------------------------------- 1 | ## Lesson 23 Five-Chess game 五子棋 2 | 棋子分为黑白两色,棋盘为15×15,棋子放置于棋盘线交叉点上。 3 | 两人对局,各执一色,轮流下一子,先将横、竖或斜线的5个或5个以上同色棋子连成不间断的一排者为胜。 4 | 5 | ### 语法知识点 6 | * 宏定义 #define 7 | * 二维数组 int chessboard[][] 8 | * 二重循环 for-for 9 | * printf 和 scanf 输入输出 10 | * 运算符 %, ++, 11 | * 方向表示 (dx, dy) 12 | * 函数设计 13 | 14 | ### 参考思路 15 | 16 | #step 1: 画棋盘 10 * 10, =0 17 | 复习 for 循环 (二重 for 循环) 18 | 复习 printf 打印 %d 的用法 19 | 20 | #step 2: 落子 =1, =2 21 | 复习 数组变量,复习 scanf 获取用户输入,&x &y 取地址符 22 | 23 | #step 3: 判断选手 who, step % 2 + 1 24 | 复习 ++ 自增运算符,复习 % 取余(模)运算符 25 | 26 | #step 4: 判断落子位置是否合理 is_valid && is_empty 27 | 复习 逻辑与,逻辑或,逻辑取反 28 | 29 | #step 5: 如何自动输入? 30 | 编辑一个 step.txt 文件,记录两个人的落子位置 31 | 运行时,使用重定向符 < 32 | 33 | 举例: ./fivechess < step.txt 34 | 35 | #step 6: 判断输赢 is_win 36 | 从 第 0 行开始,第 0 列 到 第 4 列 一共是 5 个位置 a, b, c, d, e 37 | 如果 a 位置的值 == who , 则 计数器加 1 : counter++ 38 | 对这 5 个位置 来一个 for 循环,依次判断, 39 | 40 | for (j = 0; j < 5; j++) 41 | chessboard[0][j] == who ? 42 | 43 | 44 | 如果for循环结束的时候,counter == 5 ,则说明 win 赢了,否则 则 return 0 ; 45 | 46 | 把上述功能实现为一个函数 check_right(int x, int y, int who); 47 | 完成判别向右方向是否有 5 子连珠的功能,从 x, y 这个位置向右看5个子,是否都是 who 这个人 48 | 49 | 然后对棋盘二维数组里面的每一个 x, y 位置,进行循环判断,如果其中有一个位置成功,则返回成功1 50 | 如果所有位置都判别完了,但没有返回1,则最后就返回失败 0 51 | 52 | 根据上面的办法,类似实现其他3个方向的操作: 向下,向右下,向左下 斜线方向 的判别 53 | check_down(int x, int y, int who); 54 | check_down_right(int x, int y, int who); 55 | check_down_left(int x, int y, int who); 56 | 57 | 如果对于二维棋盘的每一个点,按照 4 个方向都进行一次判别,其中有一个方向成功,则返回成功1 58 | 如果4个方向都没有成功,则取下一个点,再按照这4个方向进行判别,直到所有的点的所有的方向都判别完毕。 59 | 60 | ### 函数参考设计 61 | /* display chessboard using printf */ 62 | void print(int board[ROW][COL]) 63 | 64 | /* get user input */ 65 | int get(int *x, int *y) 66 | 67 | /* put chess in chessboard(x, y) with who 's chess*/ 68 | int put(int x, int y, int who) 69 | 70 | /* test (x, y) is valid before put chess */ 71 | int onboard(int x, int y) 72 | 73 | /* check if (x, y) is empty */ 74 | int empty(int x, int y) 75 | 76 | /* test (x, y) is valid before put chess, call onboard() and empty() */ 77 | int test(int x, int y) 78 | 79 | /* check if (x, y) has 5 chesses */ 80 | int check(int x, int y) 81 | 82 | /* check if someone wins */ 83 | int find(void) 84 | 85 | /* machine think a good place */ 86 | int think(int *x, int *y) 87 | 88 | 89 | ### 如何实现机器-机器之间比赛 90 | 1. 所有程序必须严格规定输入输出格式,输入是对方落子的位置 x y (用空格间隔),输出是自己计算的下一步位置 x2 y2 91 | 2. 所有打印棋盘的 printf 或者 debug 输出语句,可以采用宏定义方式输出到 stderr,也可以通过 ./log 程序进行过滤 92 | 3. 执行之前,必须先用 make p 创建 p1 p2 两个管道文件,然后开2个shell窗口,一个先执行 make t1 ,另一个再执行 make t2,就可以实现机器对战。 93 | 4. 执行的结果会保存在 log.txt 文件中,通过 ./replay 就可以实现回放复盘。 94 | 95 | -------------------------------------------------------------------------------- /Unit-1/Lesson-24.md: -------------------------------------------------------------------------------- 1 | ## Lesson 24 Hyperlink analysis 超链接分析器 2 | 给定一个 html 文件,找出其中所有的超链接 URL 3 | 4 | * 语法知识点 5 | - 指针 6 | - 指针数组 7 | - 字符串匹配算法,分析协议帧头帧尾 8 | - 输入输出重定向,获取文件内容 9 | -------------------------------------------------------------------------------- /Unit-1/Lesson-3.md: -------------------------------------------------------------------------------- 1 | ## Lesson 3 Count how many fingers do you have? 循环打印 2 | ### 代码 3 | #include 4 | 5 | int main(void) 6 | { 7 | int counter; 8 | 9 | printf("hello, NCCL!\n"); 10 | 11 | counter = 0; 12 | while (counter < 10) 13 | { 14 | counter++; 15 | printf("counter = %d\n", counter); 16 | } 17 | 18 | return 0; 19 | } 20 | 21 | ### do-while 用法 22 | #include 23 | 24 | int main(void) 25 | { 26 | int counter; 27 | 28 | printf("hello, NCCL!\n"); 29 | 30 | counter = 0; 31 | do 32 | { 33 | counter++; 34 | printf("counter = %d\n", counter); 35 | } while (counter < 10); 36 | 37 | return 0; 38 | } 39 | 40 | ### 第3种写法 41 | #include 42 | 43 | int main(void) 44 | { 45 | int counter; 46 | 47 | printf("hello, NCCL!\n"); 48 | 49 | counter = 1; 50 | while (counter <= 10) 51 | { 52 | printf("counter = %d\n", counter); 53 | counter++; 54 | } 55 | 56 | return 0; 57 | } 58 | 59 | 60 | ### 知识点 61 | * 局部变量 62 | * 循环语句 while 63 | * 关系运算符 <=, >= 64 | * 自增加运算符 ++ 65 | * 比较表达式求值 66 | 67 | 68 | ### 课堂讨论 69 | * 第1种和第2种写法,都能得到正确结果,哪种更好?为什么? 70 | * 第3种写法,运行也正确,为什么说它是不好的写法? 71 | * 把 counter++ 写到 printf 语句中,是否是好的写法? 72 | * counter 的初值为什么不在定义时就赋值,写在循环外面有什么好处? 73 | * 在 while 循环里面,可以定义变量吗? 变量名字可以重名吗? 74 | 75 | ### 课后练习 76 | * 将这个程序改为倒着从10数到0,应该怎么改最好? 77 | * 新增一个变量 sum,对从1加到10进行求和,打印出最后结果。 78 | * 使用 do-while 结构,实现上面2个要求。 79 | * __打印一个数字的个位,十位,百位... 直到最高位。__ 80 | 81 | ### 名人名言 82 | * Ken Thompson (Unix 之父) 83 | - “When in doubt, use brute force. ” 84 | - “如果局部变量太多,我倾向于拆分子程序。 85 | 另一个办法是看代码行是否存在太多缩进,我几乎从来不看代码长度。” 86 | 87 | -------------------------------------------------------------------------------- /Unit-1/Lesson-4.md: -------------------------------------------------------------------------------- 1 | ## Lesson 4 Judge a number odd or even 判断奇偶 2 | ### 代码 3 | #include 4 | 5 | int main(void) 6 | { 7 | int num; 8 | 9 | printf("please input a number: "); 10 | scanf("%d", &num); 11 | 12 | if (num % 2 == 0) 13 | printf("number %d is even\n", num); 14 | else 15 | printf("number %d is odd\n", num); 16 | 17 | return 0; 18 | } 19 | 20 | ### 知识点 21 | * 条件语句 if/else 22 | * 格式化输入 scanf 23 | * 关系运算符 == 24 | * 标准输入函数 scanf 25 | * 取地址符 & 26 | * 取模运算符 % 27 | 28 | ### 课堂讨论 29 | * 局部变量 num 如果没有初始化值,那么默认的值是不是0? 30 | * scanf 函数的第2个参数,如果不用 & ,会有什么后果? 31 | * 这个程序运行多次,打印出的 num 变量的地址是否相同? 32 | * 如果要让用户连续输入多个数字直到0表示结束,程序应该怎么改? 33 | * 想一想为什么 printf 打印不需要用 &num,而 scanf 需要 & 34 | 35 | ### 课后练习 36 | * 猜数字比大小游戏 37 | 由计算机请求用户A输入一个数字,然后由用户B来猜这个数字, 38 | B输入猜的数字之后,程序告诉用户B是大还是小,直到最后用户B猜对为止。 39 | * 随机猜数 40 | 将上面这个程序中通过用户A输入数字,改为由计算机随机产生数字 41 | - 提示: 使用 rand() 函数 42 | -------------------------------------------------------------------------------- /Unit-1/Lesson-5.md: -------------------------------------------------------------------------------- 1 | ## Lesson 5 Summarize all numbers from 1 to 100 从1加到100求和 2 | ### 代码 3 | #include 4 | 5 | int main(void) 6 | { 7 | int sum = 0; 8 | 9 | for (int i = 0; i <= 100; i++) 10 | { 11 | sum += i; 12 | } 13 | 14 | printf("sum = %d\n", sum); 15 | 16 | return 0; 17 | } 18 | 19 | 20 | ### 知识点 21 | * 循环语句 for 22 | * 自动变量 i 23 | * 赋值运算符 += 24 | 25 | ### 扩展参考 26 | #ifdef DEBUG 27 | #define PRINTD printf 28 | #else 29 | #define PRINTD(format, args...) ((void)0) 30 | #endif 31 | 32 | #ifdef DBG_MSG 33 | #define DEBUG_PRINTF(format,args...) \ 34 | do { fprintf(stderr,"%s(%d):" format, __FUNCTION__, __LINE__,##args); } while (0) 35 | #else 36 | #define DEBUG_PRINTF(format,args...) 37 | #endif 38 | 39 | [LinkedIn 上的讨论](http://www.linkedin.com/groupItem?view=&srchtype=discussedNews&gid=87910&item=182474373&type=member&trk=eml-anet_dig-b-pop_ttl-hdp&ut=3tEjHOeHiH0lw1) 40 | 41 | ### 课堂讨论 42 | * 在 for 循环内部修改循环变量 i 的值,可以吗? 43 | * 循环跳出的时候,i++ 是否还会执行? 最终 i 的值是多少? 44 | * 与 while 循环相比,for 循环适用于哪些场合? 45 | 46 | ### 课后练习 47 | * 用户输入5个数,计算它们的平均数,并打印。 48 | * 用户输入5个数,将其中最大的数找出来,并打印。 49 | * 已知11月1日是星期四,请打印出11月份的月历。 50 | 51 | 52 | ### 名人名言 53 | * Edsger W. Dijkstra (结构程序设计之父) 54 | - “If debugging is the process of removing bugs, 55 | then programming must be the process of putting them in.” 56 | - “有效的程序员不应该浪费很多时间用于程序调试, 57 | 他们应该一开始就不要把故障引入。” 58 | 59 | * 著名的 “Go To Letter” 60 | - Dijkstra在信中建议:“Go To语句太容易把程序弄乱, 61 | 应从一切高级语言中去掉; 62 | 只用三种基本控制结构就可以写各种程序, 63 | 这样的程序可以由上而下阅读而不会返回”。 64 | -------------------------------------------------------------------------------- /Unit-1/Lesson-6.md: -------------------------------------------------------------------------------- 1 | ## Lesson 6 Print 9*9 multiplication table 乘法表 2 | ### 代码 3 | #include 4 | 5 | int main(void) 6 | { 7 | int i, j; 8 | 9 | for (i = 1; i < 10; i++) 10 | { 11 | for (j = 1; j <= i; j++) 12 | { 13 | printf("%d*%d=%d\t", j, i, i * j); 14 | } 15 | printf("\n"); 16 | } 17 | 18 | return 0; 19 | } 20 | 21 | Output: 22 | 23 | 1*1=1 24 | 1*2=2 2*2=4 25 | 1*3=3 2*3=6 3*3=9 26 | 1*4=4 2*4=8 3*4=12 4*4=16 27 | 1*5=5 2*5=10 3*5=15 4*5=20 5*5=25 28 | 1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36 29 | 1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49 30 | 1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64 31 | 1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81 32 | 33 | ### 知识点 34 | * 嵌套循环语句 for-for 35 | * 二层逻辑嵌套 36 | 37 | ### 扩展 38 | #include 39 | 40 | int main(void) 41 | { 42 | int i, j; 43 | 44 | for (i = 1; i < 10; i++) 45 | { 46 | for (j = 1; j < 10; j++) 47 | { 48 | if (j > i) 49 | break; 50 | 51 | printf("%d*%d=%d\t", j, i, i * j); 52 | } 53 | printf("\n"); 54 | } 55 | 56 | return 0; 57 | } 58 | 59 | ### 知识点 60 | * break 用法 61 | * continue 用法 62 | 63 | ### 课堂讨论 64 | * 列举出5种场合,可以用 for-for 两重循环来解决的? 65 | * 示例中的 { } 是必须的吗,如果去掉内层或外层的 { } ,会有什么问题? 66 | * 如果用 while-while 两重循环来编写这个程序,如何实现? 67 | 68 | ### 课后练习 69 | * 打印1个5*5的棋盘(0表示空,1表示有子),用户输入1个位置(例如 2 3),重新打印棋盘。 70 | * 一个数各个约数(真约数)的和等于它本身的自然数叫做完全数(Perfect number)。 71 | (例如:6 = 1 + 2 + 3) 请找出1-1000以内的完全数。 72 | * 一个 n 位数 ( n≥3 ) 每个位上的数字的 n 次幂之和等于它本身的数叫做水仙花数。 73 | (例如:1^3 + 5^3 + 3^3 = 153) 请找出 n = 3 的水仙花数。 74 | -------------------------------------------------------------------------------- /Unit-1/Lesson-7.md: -------------------------------------------------------------------------------- 1 | ## Lesson 7 Find the max prime number within 100 求100以内的最大素数 2 | ### 代码 3 | #include 4 | #include 5 | 6 | int main(void) 7 | { 8 | int i, j; 9 | int max = 0; 10 | 11 | for (i = 1; i <= 100; i++) 12 | { 13 | int tmp; 14 | 15 | tmp = (int)sqrt(i); 16 | 17 | for (j = 2; j <= tmp; j++) 18 | { 19 | if (i % j == 0) 20 | break; 21 | } 22 | 23 | if (j == tmp + 1) 24 | max = i; 25 | } 26 | 27 | printf("max = %d\n", max); 28 | 29 | return 0; 30 | } 31 | 32 | ### 知识点 33 | * 数学头文件 math.h 34 | * 数学库函数 sqrt 35 | * 强制类型转换 (int) 36 | * 三层逻辑嵌套 37 | 38 | ### 课堂讨论 39 | * 示例中的 j == tmp + 1 能否改为 j == tmp? 为什么? 40 | * sqrt 是数学库中的函数,其他还有哪些也是数学库的函数? 41 | * 如果没有数学库,这个程序应该如何编写效率才能最高? 42 | 43 | ### 课后练习 44 | * 5*5 的棋盘,用户输入两个位置坐标,统计这两个位置之间有多少个子?(按从左向右的顺序数) 45 | 0 0 0 0 0 46 | 0 1 0 0 0 47 | 0 0 0 1 0 48 | 0 0 0 0 0 49 | 0 0 0 0 0 50 | 以左图为例,(1, 1) 到 (2, 3) 之间有6个子。 51 | * 在上图所示的棋盘中,用户任意输入一个位置,放置国际象棋中的皇后,请输出所有皇后能够吃到的位置。 52 | 53 | ### 名人名言 54 | * Donald Ervin Knuth (现代计算机科学的鼻祖, 经典巨著《计算机程序设计的艺术》的作者) 55 | - “There’s always more to learn, and there are always better ways to do what you’ve done before.” 56 | 57 | -------------------------------------------------------------------------------- /Unit-1/Lesson-8.md: -------------------------------------------------------------------------------- 1 | ## Lesson 8 Find 9 in number 1 to 100 1到100有多少个9 2 | /* 3 | * main.c - find how many digit 9 from 1 to 100 4 | * 5 | * Copyright (C) AKAE - li ming 6 | * 7 | */ 8 | #include 9 | 10 | /* 11 | * find - calculate how many digit in num 12 | * @num: the number we want to find 13 | * @digit: the digit we search in num 14 | * 15 | * Return value: how many digit in this num 16 | * 17 | */ 18 | int find(int num, int digit) 19 | { 20 | int counter = 0; /* the result of how many digit in num */ 21 | 22 | do { 23 | /* get the last digit of num */ 24 | if (num % 10 == digit) 25 | counter++; 26 | 27 | /* get rid of the last digit */ 28 | num = num / 10; 29 | } while (num != 0); 30 | 31 | return counter; 32 | } 33 | 34 | int main(void) 35 | { 36 | int begin = 1; /* the begin number */ 37 | int end = 100; /* the end number */ 38 | int i = 0; 39 | int sum = 0; /* the result of sumary */ 40 | 41 | /* calculate how many 9 in 1 to 100 */ 42 | for (i = begin; i <= end; i++) { 43 | sum += find(i, 9); 44 | } 45 | 46 | printf("sum = %d \n", sum); 47 | 48 | return 0; 49 | } 50 | 51 | ### 知识点 52 | * 函数 Function 53 | * 形参和实参 54 | * 函数返回值 55 | * 逻辑分解 56 | * 注释的写法 57 | 58 | ### 课堂讨论 59 | * 示例中的 0, 100 为何要用 begin, end 来定义,直接写在 for 循环中可以吗? 60 | * find 中的 do-while 改成 while 可以吗? 61 | * 为什么不写一个函数,直接就能计算出1-100中的9的个数? 62 | 63 | ### 课后练习 64 | * 求1-100以内最大的素数,要求用设计一个函数实现。 65 | * 用户输入两个数字,按从个位对齐的方式,找出这2个数在相同位置处数字也相同的个数。 66 | 例如:123 和 5173 这2个数字,位置相同数字也相同的个数是 2 67 | 68 | ### 名人名言 69 | * Brian W.Kernighan (C Programming Language 一书合作者) 70 | - ”I don't think that I have any special insight, but it has always seemed to me best to do something that you really enjoy doing. If you have a job that is fun, where you are eager to start in the morning and hate to quit in the evening, that's what you want.“ 71 | - 我不认为自己有任何特别的远见,但是对于我来说做自己喜欢的事情似乎是最好的。如果你有一份有趣的工作,在早上你非常渴望开始做,并且在傍晚的时候你又不愿停下来,那这就是你想要的。 72 | 73 | -------------------------------------------------------------------------------- /Unit-1/Lesson-9.md: -------------------------------------------------------------------------------- 1 | ## Lesson 9 Convert a number to a string 整型转字符串 2 | #include 3 | 4 | void itoa(int num, char buf[]) 5 | { 6 | int i = 0; 7 | int j = 0; 8 | 9 | do 10 | { 11 | buf[i++] = num % 10 + '0'; 12 | num /= 10; 13 | } while (num); 14 | buf[i] = '\0'; 15 | 16 | for (j = 0, i--; j < i; j++, i--) 17 | { 18 | char tmp; 19 | 20 | tmp = buf[i]; 21 | buf[i] = buf[j]; 22 | buf[j] = tmp; 23 | } 24 | 25 | return; 26 | } 27 | 28 | int main(void) 29 | { 30 | int num; 31 | char buf[100]; 32 | 33 | printf("Please input a number: "); 34 | scanf("%d", &num); 35 | 36 | itoa(num, buf); 37 | 38 | printf("number string = %s\n", buf); 39 | 40 | return 0; 41 | } 42 | 43 | ### 知识点 44 | * 数组 array 45 | * 函数式的宏定义 46 | * 进制表示 oct, dec, hex 47 | * 三元表达式 a > b ? a : b 48 | * 字符串逆序 reverse() 49 | * 字符串库函数 itoa 50 | 51 | ### 课堂讨论 52 | * do-while 的循环可以用 while 循环替换吗? 为什么? 53 | * 如果要将输入数字,按照16进制,或者2进制转换成字符串,如何修改? 54 | * 为了交换两个字节的内容,示例中引入了一个 tmp 变量,这个是必须的吗? 55 | * 在 itoa 中用到了字符串的逆序操作,请实现一个函数来完成这个操作。 56 | 57 | ### 课后练习 58 | * 用户任意输入一个字符串,判断这个字符串是否为“回文”(回文即按正反顺序读都一样)。例如 “abcba” 就是回文。 59 | * 使用字符数组实现基于数字字符串的加减法。例如"123" + "45" = "168" , "456"-"13"="443"。 60 | * 编写一个去字符串多余空格的的程序,将连续的多个空格用一个空格代替。例如输入"abc___ab_a__c",输出"abc ab a c"。 61 | 62 | -------------------------------------------------------------------------------- /Unit-1/README.md: -------------------------------------------------------------------------------- 1 | NCCL - New Concept C Language 2 | ============================= 3 | 4 | ### 《新概念C语言》Unit 1 视频学习课件 5 | * 全套42集免费视频课程已经发布在百度云 6 | * 下载地址 7 | * 通过百度云盘可以下载,也可以在线观看视频(手机安装百度云也可以在线观看) 8 | * 视频中所有用到的范例C程序[代码下载](https://github.com/limingth/NCCL.codes) 9 | 10 | * 《C语言中文网》也提供了视频下载链接 11 | - 视频下载地址 12 | 13 | * 使用播布客网站视频播放器本地观看视频,更清晰更流畅。 14 | - 播布客[视频播放器下载](http://www.boobooke.com/download/MBoo2015.zip) 15 | - [播布客视频压缩包百度云盘下载](http://pan.baidu.com/s/1sjp10dv) 16 | 17 | * 《新概念C语言课程概述》(第0集) 在线观看 18 | 19 | * 《C程序设计语言(第2版-新版)》多贝网络公开课在线观看 20 | - 参考用书《K&R》[下载链接](https://www.dropbox.com/s/qer3va6rtq8o1dj/C%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E8%AF%AD%E8%A8%80%EF%BC%88%E7%AC%AC2%E7%89%88%C2%B7%E6%96%B0%E7%89%88%EF%BC%89.pdf) 21 | 22 | ### 一对一远程视频辅导 23 | * 新概念C语言 Unit 1 和 [Unit 2](../Unit-2/README.md) 开始提供一对一编程辅导课程,学习时间2-3个月。 24 | - 个性化辅导,根据个人接受程度,灵活安排上课时间 25 | - 报名学习请咨询 QQ: 2372614758 (毛豆网李明老师) 26 | 27 | * 提前安装学习环境 28 | - [下载安装 Google Chrome 浏览器](http://www.google.com/intl/zh-CN/chrome/) 29 | - [注册 Gmail 帐号](https://accounts.google.com/SignUp?service=mail&continue=https%3A%2F%2Fmail.google.com%2Fmail%2F<mpl=default&hl=zh-CN) 30 | - [美国地区的学员请安装 Google Hangout 环聊](https://www.google.com/tools/dlpage/hangoutplugin?) 31 | - [国内地区不能翻墙的学员请下载注册 Skype 帐号](http://www.skype.com/zh-Hans/download-skype/skype-for-computer/) 32 | 33 | 34 | ### 开发环境选择 35 | * 推荐安装 Ubuntu Linux,并安装以下包 36 | - sudo apt-get install manpages-dev gcc make libc6-dev 37 | 38 | * 对于从来没有安装过 Ubuntu(包括虚拟机) 的初学者,最好的选择是 39 | - 直接通过 [nitrous.io](http://www.nitrous.io) 网站来学习 Linux C 编程 40 | - 好处就是可以通过浏览器来获得 Linux 编程环境,无需安装Ubuntu操作系统,节省时间 41 | - 更有用的是只要能够上网的地方,就能获得C编程的环境,无需带虚拟机或双操作系统到处跑 42 | 43 | * 如果希望能够在 Windows 上使用 Gcc 开发工具,可以安装 MinGW,参考安装流程 44 | - http://blog.csdn.net/firefoxbug/article/details/6724876 45 | 46 | * 如果需要安装 VC6.0 ,可以到这里下载 47 | 48 | * nitrous 浏览器登录界面如下 49 | 50 | ![nitrous.io](../images/nitrous.jpg) 51 | 52 | ### Mac 苹果笔记本环境安装 53 | * Mac 上运行播布客软件,可以采用 WINE 的解决方案。 54 | - 55 | 56 | * 具体步骤如下 57 | - 到 [http://brew.sh](http://brew.sh) 下载安装 brew ,也可以直接运行下面的命令 58 | - ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)" 59 | - brew doctor 将检查到的 warning 问题排除 60 | - brew install wine --devel 61 | - https://xquartz.macosforge.org/landing/ 下载 XQuartz-2.7.5.dmg 并安装Mac OS下的 X Window System 62 | - http://linfan.info/blog/2012/02/25/homebrew-installation-and-usage/ 63 | 64 | 65 | # Unit One 66 | Unit 1 是《新概念C语言》系列课程的第一部分,共有24个Lesson,包含以下4个层次的学习内容: 67 | 68 | 1. Beginning Lessons (Lesson 1-7) 69 | 以变量为核心,运用循环语句和条件分支,讲解C程序的基本结构。 70 | 71 | 2. Intermediate Lessons (Lesson 8-14) 72 | 以数组为核心,分析常用数据结构(字符串,结构体,联合),讲解C程序的函数设计。 73 | 74 | 3. Advanced Lessons (Lesson 15-21) 75 | 以指针为核心,结合二维数组,位操作和函数指针,讲解C程序的状态机编程思想。 76 | 77 | 4. Homework Projects (Lesson 22-24) 78 | 以任务为核心,通过趣味题,综合使用学习过的知识和技能,实现项目需求功能。 79 | 80 | # Beginning Lessons 81 | 82 | ## Lesson 1 [What is the simplest C program?](Lesson-1.md) 最简单的C程序 83 | * C 语言 Language 84 | - 高级语言 High-level Programming Language 85 | - 汇编语言 Assembly Language 86 | - 机器指令 Instructions 87 | * 编译器 Compiler 88 | - 汇编器 Assembler 89 | * 操作系统 OS 90 | - 加载器 Loader 91 | - 加载地址和执行地址 Load_Addr & Exec_Addr 92 | * 程序的执行 Program Execution 93 | - 进程的概念 Process 94 | - 执行流程 Execution Sequence 95 | 96 | ## Lesson 2 [Let's say hello to world](Lesson-2.md) 打印输出 97 | * 库函数 Library 98 | - libc & glibc 99 | - 系统调用 System Call 100 | - 库封装了系统调用 101 | * 链接器 Linker 102 | - 链接脚本 Link Script 103 | - 程序入口 Entry 104 | - 链接脚本决定了程序的执行地址 105 | * 程序的编译过程 Program compiling procedure 106 | - 预处理 Preprocessing cpp (.c -> .i) 107 | - 编译 Compilation cc1 (.i -> .s) 108 | - 汇编 Assembly as (.s -> .o) 109 | - 链接 Linking collect2 (.o -> .elf) 110 | * 虚拟地址 Vitual Memory Address 111 | - 进程独立的地址空间 112 | - 内存管理单元 MMU 113 | 114 | ## Lesson 3 [Count how many fingers do you have?](Lesson-3.md) 循环打印 115 | * while 循环 和 do-while 用法 116 | - 比较和跳转指令 Compare and Jump Instruction 117 | - do-while 比 while 有时更有用 118 | * 变量的初始化 Variable Initialization 119 | - 变量的存储布局 Data & BSS Section 120 | - 变量的取名规范 Naming 121 | * 相对跳转 Relative Jump 122 | - 位置无关代码 PIC (Position Independent Code) 123 | 124 | ## Lesson 4 [Judge a number odd or even](Lesson-4.md) 判断奇偶 125 | * 条件分支 Condition 126 | - 表达式求值 Expression Value 127 | * 编码风格 Coding Style 128 | - 标识符命名 symbol naming 129 | - 代码缩进 (如果你知道自己在做什么,三层就足够了) 130 | * 函数的传值和传址 Parameter's value and address 131 | - 程序二进制接口规范 ABI (Application Binary Interface) 132 | 133 | ## Lesson 5 [Summarize all numbers from 1 to 100](Lesson-5.md) 从1加到100求和 134 | * for 循环 135 | - 两种循环用法比较 136 | * 自动变量 auto variable 137 | - C 语言的发展变迁 Old Style C/C89/C99/GNU C 138 | * 预处理过程 Pre-compile 139 | - 条件编译 140 | - \# 和 \#\# 的用法 141 | * DEBUG 调试宏 142 | - \_\_func\_\_, \_\_FUNCTION\_\_ 143 | - \_\_LINE\_\_ 144 | - args... 和 \#\#args 的用法 145 | 146 | ## Lesson 6 [Print 9\*9 multiplication table](Lesson-6.md) 乘法表 147 | * 循环嵌套 148 | - 两重循环的典型用法 149 | - break 和 continue 150 | * 程序的调试 151 | - 编译时和运行时错误 152 | * 函数栈 Function Stack 153 | - 栈帧 Stack Frame 154 | 155 | ## Lesson 7 [Find the max prime number within 100](Lesson-7.md) 求100以内的最大素数 156 | * 循环中的条件分支 157 | - break 和 goto 用法 158 | * 数学库函数 math library 159 | - 静态链接和动态链接 static & dynamic linkage 160 | * 算法效率 161 | - 算法的时间复杂度分析 O(n) 162 | * 结构程序设计 163 | - 三种基本控制结构就可以写各种程序 164 | 165 | # Intermediate Lessons 166 | ## Lesson 8 [Find 9 in number 1 to 100](Lesson-8.md) 1到100有多少个9 167 | ### 基本概念讲解 168 | * 函数 Function 169 | - 函数的入口和出口 170 | * 分解和分层 stratify 171 | - 小即是美 172 | * 过程抽象和接口设计 Procedure Abstract 173 | - 可复用的代码 Reuse 174 | - 接口小巧、简洁和正交 175 | 176 | ## Lesson 9 [Convert a number to a string](Lesson-9.md) 整型转字符串 177 | ### 基本概念讲解 178 | * 字符数组 String and Character Array 179 | - 字符编码 ASCII 码表 180 | * 字符串逆序 String Reverse 181 | - 函数式宏定义 Function-like Macro 182 | 183 | ## Lesson 10 [Josephus ring](Lesson-10.md) 约瑟夫环 184 | ### 基本概念讲解 185 | * 整型数组 Array 186 | - 数组的初始化 187 | * 数据结构和算法 DS & AL 188 | - 数据驱动编程 Data-Driven 189 | - 数据压倒一切,编程的核心是数据结构,而不是算法 190 | * 链表思想 Link List 191 | - 算法优化 Optimization 192 | 193 | ## Lesson 11 [Calculate the distance between 2 points](Lesson-11.md) 求两个坐标点之间的距离 194 | ### 基本概念讲解 195 | * 结构体 Struct 196 | - 结构体初始化 197 | * 数组和结构体 198 | - 数组名参数的传址调用 199 | - 结构体参数的传值调用 200 | * 复杂类型声明 typedef 201 | - 预处理和编译时 Pre-compile & Compiling time 202 | - typedef 背后编译器的处理过程 203 | * C99 中结构体的扩展用法 204 | - 驱动内核模块编写 205 | 206 | ## Lesson 12 [Does your machine use little-endian?](Lesson-12.md) 判断机器存储是否小尾端 207 | ### 基本概念讲解 208 | * 联合 Union 209 | - 存储分配 210 | * 结构体空洞 Struct Hole 211 | - 对齐和填充 Alignment & Padding 212 | * 数据的存储表示 Complements 213 | - 原码,反码和补码 214 | 215 | ## Lesson 13 [Sorry, your car is restricted today](Lesson-13.md) 对不起,你的车今天限行 216 | ### 基本概念讲解 217 | * 分支语句 Switch 218 | * 枚举用法 enum 219 | - 枚举类型的初始化 220 | * 增量式开发 Incremental Development 221 | - 步步为营而不是一蹴而就 222 | * 预定义宏的用法 223 | - \_\_DATE\_\_ 224 | - \_\_TIME\_\_ 225 | 226 | ## Lesson 14 [Is there a way out?](Lesson-14.md) 判断地图上某点是否有出路 227 | ### 基本概念讲解 228 | * 二维数组 229 | - 循环和分支 230 | * 逻辑表达式 Logical Expression 231 | - 或 || 232 | - 与 && 233 | * 随机数生成 Random 234 | - 时间种子 Time seed 235 | 236 | 237 | # Advanced Lessons 238 | 239 | ## Lesson 15 [Count bit 1 in a number](Lesson-15.md) 统计一个数二进制表示中1的个数 240 | ### 基本概念讲解 241 | * 位操作 242 | - 移位 >> 243 | - 与 & 244 | * 异或操作: 245 | - 按位加法 246 | * 算法效率 247 | - 过早优化是万恶之源 248 | - 先求运行,再求正确,最后求快 249 | * 位域操作 250 | - 通过位域实现位操作 251 | - 嵌入式编程中的寄存器配置 252 | 253 | ## Lesson 16 [How to strcpy](Lesson-16.md) 字符串拷贝 254 | ### 基本概念讲解 255 | * 指针 256 | - 计算机存储体系 257 | * 动态内存分配 Memory Allocate 258 | - heap & stack 259 | * assert 宏 260 | - 三元表达式 261 | * 寻址和访存 262 | - 内存对齐 263 | - 防止编译器优化 volatile 264 | 265 | ## Lesson 17 [Count words in an artitle](Lesson-17.md) 统计单词个数 266 | ### 基本概念讲解 267 | * 指针数组 268 | - 和二维数组的比较 269 | * 动态内存分配 270 | - malloc & free 271 | * 递归 Recursive 272 | - 循环和递归 273 | * 变量的生存期和作用域 274 | - static 用法 275 | * 状态机思想的简单应用 276 | - state machine 277 | 278 | ## Lesson 18 [My printf](Lesson-18.md) 实现 printf 279 | ### 基本概念讲解 280 | * 字符指针数组 281 | * 可变长度参数的函数实现 282 | - 字符串常量 const char * 283 | - ... 可变参数的用法 284 | * 栈帧的应用 285 | - va_list 286 | - va_start 287 | - va_arg 288 | - va_end 289 | 290 | ## Lesson 19 [Shell command parser](Lesson-19.md) 命令解释器 291 | ### 基本概念讲解 292 | * 函数指针 293 | - 回调函数 Call-Back Function 294 | * main 参数 argc, argv 295 | - 字符指针数组 vs 指针的指针 296 | * 进程的环境变量 297 | - 进程栈空间布局 298 | * 函数指针数组 299 | - 结构体数组 300 | * 策略和机制分离 301 | - 高内聚低耦合原则 302 | 303 | ## Lesson 20 [Preprocessor](Lesson-20.md) 预处理器实现 304 | ### 基本概念讲解 305 | * C语言去注释问题 306 | - 状态的变迁 20.1 307 | - 状态机编程模型1(if-else) 20.2 308 | * 去多余空格问题 309 | - Unix 编程艺术之表示原则: 把知识叠入数据以求逻辑质朴而健壮。 310 | - 字节流处理: 重定向和管道 311 | - 状态机编程模型2(状态迁移表和函数指针数组) 20.3 312 | * 宏定义替换问题 313 | - #define 314 | - 状态机的设计思路和设计过程 20.4 315 | - 状态机的编程实现过程 20.5 316 | * 条件编译问题 317 | - #if/#endif 318 | - 实现代码分析 20.6 319 | 320 | ## Lesson 21 [Lexical analysis](Lesson-21.md) 词法分析器实现 321 | ### 基本概念讲解 322 | * flex 词法分析器生成工具 323 | - lex.l 文件介绍 324 | - yy_nxt 数组 325 | - yy_accept 数组 326 | 327 | * 词法分析器实现 328 | - 如何使用 yy_nxt 和 yy_accept 329 | - 词法匹配时的状态判别 330 | 331 | 332 | # Homework Projects 333 | 334 | **The next 3 lessons are projects you should do it by yourself.** 335 | 336 | ## Lesson 22 [Guess number in my hand](Lesson-22.md) 猜数游戏 337 | ### 问题描述 338 | 猜数游戏:电脑随机产生4位数,然后用户输入4位数,电脑告诉你是?A?B,请你最后猜出电脑的4位数是多少? 339 | (4位数字互不重复,A表示位置和数字都对,B表示位置不对,数字对) 340 | 341 | 342 | ## Lesson 23 [Five-Chess game](Lesson-23.md) 五子棋 343 | ### 问题描述 344 | 五子棋:在一个9x9的棋盘上通过两人对弈的形式,依次在棋盘上放置两种颜色的棋子,哪一方先让五个棋子形成一条直线(包括横、竖、对角线3个方向),即为获胜。 345 | (实现一个计算机下棋算法,让你的同组成员无法胜出,则算你赢) 346 | 347 | 348 | ## Lesson 24 [Build a simple Search Engenine](Lesson-24.md) 简单搜索引擎 349 | ### 问题描述 350 | 简单搜索引擎:从网页文件中抓取正文文本 (例如 "\hello, lumit.\" ),搜索是否存在用户输入的关键字 lumit,并返回相关段落正文。 351 | 同时从网页文件中抓取超链接URL (例如 \lumit - let us make it together.\ ),并下载相关网页文件。依此递归。 352 | 353 | 354 | 355 | -------------------------------------------------------------------------------- /Unit-2/Lesson-25.md: -------------------------------------------------------------------------------- 1 | ## Lesson 25 - mycp (cp命令实现) 2 | 3 | ### 课程任务 4 | * 完成 Linux 下的 cp 命令,实现文件的复制功能。 5 | * 实现 cat 命令,查看复制后的文件内容。 6 | 7 | #### cp 命令格式 8 | 9 | NAME 10 | cp -- copy files 11 | 12 | SYNOPSIS 13 | cp source_file target_file 14 | 15 | #### cat 命令格式 16 | 17 | NAME 18 | cat -- concatenate and print files 19 | 20 | SYNOPSIS 21 | cat filename 22 | 23 | ### 预备知识 24 | * [文件的基本概念](http://learn.akae.cn/media/ch25s02.html) 25 | 26 | ### 重要知识点 27 | 28 | * FILE struct 29 | 30 | typedef struct __sFILE { 31 | unsigned char *_p; /* current position in (some) buffer */ 32 | int _r; /* read space left for getc() */ 33 | int _w; /* write space left for putc() */ 34 | short _flags; /* flags, below; this FILE is free if 0 */ 35 | short _file; /* fileno, if Unix descriptor, else -1 */ 36 | struct __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */ 37 | int _lbfsize; /* 0 or -_bf._size, for inline putc */ 38 | 39 | /* operations */ 40 | void *_cookie; /* cookie passed to io functions */ 41 | int (*_close)(void *); 42 | int (*_read) (void *, char *, int); 43 | fpos_t (*_seek) (void *, fpos_t, int); 44 | int (*_write)(void *, const char *, int); 45 | 46 | /* separate buffer for long sequences of ungetc() */ 47 | struct __sbuf _ub; /* ungetc buffer */ 48 | struct __sFILEX *_extra; /* additions to FILE to not break ABI */ 49 | int _ur; /* saved _r when _r is counting ungetc data */ 50 | 51 | /* tricks to meet minimum requirements even when malloc() fails */ 52 | unsigned char _ubuf[3]; /* guarantee an ungetc() buffer */ 53 | unsigned char _nbuf[1]; /* guarantee a getc() buffer */ 54 | 55 | /* separate buffer for fgetln() when line crosses buffer boundary */ 56 | struct __sbuf _lb; /* buffer for fgetln() */ 57 | 58 | /* Unix stdio files get aligned to block boundaries on fseek() */ 59 | int _blksize; /* stat.st_blksize (may be != _bf._size) */ 60 | fpos_t _offset; /* current lseek offset (see WARNING) */ 61 | } FILE; 62 | 63 | * stdio/stdout/stderr 64 | 65 | #define stdin __stdinp 66 | #define stdout __stdoutp 67 | #define stderr __stderrp 68 | 69 | extern FILE *__stdinp; 70 | extern FILE *__stdoutp; 71 | extern FILE *__stderrp; 72 | 73 | * 两个常用的宏定义 (stdio.h stddef.h) 74 | 75 | #define EOF (-1) 76 | #define NULL ((void *)0) 77 | 78 | * 几个常见的 typedef 79 | * size_t 80 | * fpos_t 81 | * va_list 82 | 83 | #### 常用 API 84 | 85 | fopen(); 打开文件 86 | fclose(); 关闭一个流。 87 | 88 | feof(); 检测文件结束符 89 | fread(); 从文件流读取数据 90 | fwrite(); 将数据写至文件流 91 | fprintf(); 格式化输出数据至文件 92 | fscanf(); 格式化字符串输入 93 | fflush(); 更新缓冲区 94 | 95 | fgetc(); 由文件中读取一个字符 96 | fgets(); 文件中读取一字符串 97 | fputc(); 将一指定字符写入文件流中 98 | fputs(); 将一指定的字符串写入文件内 99 | 100 | fseek(); 移动文件流的读写位置 101 | fsetpos(); 定位流上的文件指针 102 | fgetpos(); 移动文件流的读写位置 103 | ftell(); 取得文件流的读取位置 104 | rewind(); 重设读取目录的位置为开头位置 105 | 106 | fileno(); 获取文件描述符 107 | ferror(); 检查流是否有错误 108 | 109 | freopen(); 打开文件 110 | remove(); 删除文件 111 | rename(); 更改文件名称或位置 112 | tmpfile(); 以wb+形式创建一个临时二进制文件 113 | tmpnam(); 产生一个唯一的文件名 114 | 115 | ### mycp 命令实现 116 | 117 | * [系统调用实现参考](http://blog.csdn.net/buaa_shang/article/details/9146793) 118 | 119 | * [标准库实现参考](http://book.51cto.com/art/200903/114931.htm) 120 | 121 | -------------------------------------------------------------------------------- /Unit-2/Lesson-26.md: -------------------------------------------------------------------------------- 1 | ## Lesson 26 - ELF Header Parser (ELF文件头分析器实现) 2 | 3 | ### 课程任务 4 | * 完成对 ELF 格式文件头(ELF Header)的读取,实现 readelf -a 的功能。 5 | 6 | $ readelf -a max.o 7 | ELF Header: 8 | Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 9 | Class: ELF32 10 | Data: 2's complement, little endian 11 | Version: 1 (current) 12 | OS/ABI: UNIX - System V 13 | ABI Version: 0 14 | Type: REL (Relocatable file) 15 | Machine: Intel 80386 16 | Version: 0x1 17 | Entry point address: 0x0 18 | Start of program headers: 0 (bytes into file) 19 | Start of section headers: 200 (bytes into file) 20 | Flags: 0x0 21 | Size of this header: 52 (bytes) 22 | Size of program headers: 0 (bytes) 23 | Number of program headers: 0 24 | Size of section headers: 40 (bytes) 25 | Number of section headers: 8 26 | Section header string table index: 5 27 | 28 | * 在完成上述功能的基础上,能够区分 .o .so .elf 这3种文件属性,实现 file 命令的部分功能。 29 | 30 | $ gcc -c hello.c -o hello.o 31 | $ file hello.o 32 | hello.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped 33 | $ gcc hello.c -o a.out 34 | $ file a.out 35 | a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1], not stripped 36 | 37 | ### 预备知识 38 | * [ELF文件简介](http://learn.akae.cn/media/ch18s05.html) 39 | 40 | * [UNIX/LINUX 平台可执行文件格式分析](http://www.ibm.com/developerworks/cn/linux/l-excutff/) 41 | 42 | * [elf文件格式分析](http://blog.csdn.net/wu5795175/article/details/7657580) 43 | 44 | * [elf文件格式详解](http://blog.chinaunix.net/attachment/attach/26/40/46/9726404697228d82cda2af11366fa7722d3a4f1a58.pdf) 45 | 46 | * [格式化I/O函数](http://learn.akae.cn/media/ch25s02.html#id2832755) 47 | 48 | ### 重要知识点 49 | 50 | * 常用 API 51 | 52 | printf(); 格式化输出数据 53 | scanf(); 格式输入函数 54 | 55 | sprintf(); 格式化字符串复制 56 | sscanf(); 格式化字符串输入 57 | 58 | vfprintf(); 格式化输出数据至文件 59 | vprintf(); 格式化输出数据 60 | vsprintf(); 格式化字符串复制 61 | 62 | getc(); 由文件中读取一个字符 63 | putc(); 将一指定字符写入文件中 64 | getchar(); 由标准输入设备内读进一字符 65 | putchar(); 将指定的字符写到标准输出设备 66 | gets(); 由标准输入设备内读进一字符串 67 | puts(); 送一字符串到流stdout中 68 | 69 | ungetc(); 将指定字符写回文件流中 70 | perror(); 打印出错误原因信息字符串 71 | 72 | ### 编程提示 73 | 74 | #### readelf 命令源码实现 75 | 76 | * [readelf.h 头文件参考](http://www.oschina.net/code/explore/freebsd/contrib/file/readelf.h) 77 | 78 | typedef struct { 79 | Elf32_Char e_ident[EI_NIDENT]; 80 | Elf32_Half e_type; 81 | Elf32_Half e_machine; 82 | Elf32_Word e_version; 83 | Elf32_Addr e_entry; /** Entry point */ 84 | Elf32_Off e_phoff; 85 | Elf32_Off e_shoff; 86 | Elf32_Word e_flags; 87 | Elf32_Half e_ehsize; 88 | Elf32_Half e_phentsize; 89 | Elf32_Half e_phnum; 90 | Elf32_Half e_shentsize; 91 | Elf32_Half e_shnum; 92 | Elf32_Half e_shstrndx; 93 | } Elf32_Ehdr; 94 | 95 | * [readelf.c 源文件参考](http://www.oschina.net/code/explore/freebsd/contrib/file/readelf.c) 96 | 97 | #### 关键代码 98 | 99 | struct type_string 100 | { 101 | int type; 102 | char *string; 103 | } s[] = 104 | { 105 | { 0, "Unknow" }, 106 | { 2, "EXEC" }, 107 | { 1, "REL" }, 108 | { -1, "Other Format" }, 109 | }; 110 | 111 | // ELF Header size 112 | #define HSIZE (int)sizeof(Elf32_Ehdr) 113 | 114 | char buf[HSIZE]; 115 | int n; 116 | 117 | n = fread(buf, HSIZE, 1, fp); 118 | 119 | Elf32_Ehdr * p; 120 | p = (Elf32_Ehdr *)buf; 121 | 122 | printf("type = %d\n", p->e_type); 123 | printf("Type: %s\n", s[get_type_index(p->e_type)].string); 124 | 125 | 126 | ### 课后阅读 127 | * [《unix编程艺术》策略同机制分离,接口同引擎分离](http://www.cnblogs.com/chgaowei/archive/2011/07/26/2117644.html) 128 | -------------------------------------------------------------------------------- /Unit-2/Lesson-27.md: -------------------------------------------------------------------------------- 1 | ## Lesson 27 - sed simple (简单流处理器实现和正则表达式) 2 | 3 | ### 课程任务 4 | * 实现 sed 命令中最简单的字符串替换功能,从标准输入 stdin 读入字符流,然后经过处理后,从标准输出 stdout 显示。 5 | - sed 命令例子参考 http://www.folkstalk.com/2012/01/sed-command-in-unix-examples.html 6 | 7 | $ echo "unix is great os. unix is opensource. unix is free os." | sed 's/unix/linux/' 8 | linux is great os. unix is opensource. unix is free os. 9 | 10 | $ echo "unix is great os. unix is opensource. unix is free os." | sed 's/unix/linux/g' 11 | linux is great os. linux is opensource. linux is free os. 12 | 13 | $ echo "unix is great os. unix is opensource. unix is free os." | sed 's/unix/linux/3' 14 | unix is great os. unix is opensource. linux is free os. 15 | 16 | 17 | * 在完成上述功能的基础上,实现正则表达式中最简单的 ^ (行首)替换功能。 18 | - 正则表达式学习可参考 http://learn.akae.cn/media/ch32s02.html 19 | 20 | $ echo "unix is great os. unix is opensource. unix is free os." | sed 's/^unix/linux/' 21 | linux is great os. unix is opensource. unix is free os. 22 | 23 | $ echo "unix is great os. unix is opensource. unix is free os." | sed 's/^unix/linux/g' 24 | linux is great os. unix is opensource. unix is free os. 25 | 26 | ### 参考资料 27 | * [sed和正则表达式](http://learn.akae.cn/media/ch32s03.html) 28 | * [文本处理流编辑器sed命令用法](http://www.1987.name/306.html) 29 | * [字符串库函数范例代码](http://www.tutorialspoint.com/c_standard_library/string_h.htm) 30 | 31 | ### 重要知识点 32 | * 字符串的分割 strtok 33 | - s/unix/linux 34 | * 字符串的查找 strstr 35 | * 字符串的拼接 strcat 36 | 37 | #### 常用 API 38 | 39 | strlen(); 计算字符串长度 40 | strcmp(); 比较字符串 41 | strcpy(); 拷贝字符串 42 | strcat(); 连接两字符串 43 | 44 | strchr(); 查找字符串中第一个出现的指定字符 45 | strstr(); 在一字符串中查找指定的字符串 46 | strspn(); 返回字符串连续不含指定字符的字符数 47 | strtok(); 分割字符串 48 | 49 | strpbrk(); 查找字符串中第一个出现的指定字符 50 | strrchr(); 查找字符串中最后出现的指定字符 51 | strcspn(); 返回字符连续不含指定字符的字符数 52 | strcoll(); 采用目前区域的字符排列比较字符串 53 | 54 | strncmp(); 比较2个字符串的前N个字符 55 | strncpy(); 拷贝字符串 56 | strncat(); 连接两字符串 57 | 58 | strerror(); 返回错误原因的描述字符串 59 | strxfrm(); 转换字符串 60 | -------------------------------------------------------------------------------- /Unit-2/Lesson-28.md: -------------------------------------------------------------------------------- 1 | 2 | ## Lesson 28 - math calculator (数学计算器实现) 3 | 4 | ### 课程任务 5 | 实现在 Bash 提示符下面的数学函数计算功能,要求调用不少于 3 种数学函数。 6 | 7 | double sqrt(double x); 开平方 8 | double pow(double x, double y); 计算以x为底数的y次幂 9 | double sin(double x); 正弦 10 | 11 | * 运行示例 12 | 13 | limingth@gmail ~/Github/NCCL.codes/Lesson-32$ ./bashclone 14 | NCCL# math sin 1 15 | result = 0.841471 16 | NCCL# math sqrt 81 17 | result = 9.000000 18 | NCCL# 19 | 20 | ### 参考资料 21 | * http://ganquan.info/standard-c/ 22 | * http://wiki.ubuntu.org.cn/跟我一起写Makefile:使用函数 23 | 24 | ### 重要知识点 25 | * 数学函数接口 sin, sqrt, pow, modf,fmod 等 26 | * 字符串和数值类型的转换 atoi, atof, strtol, strtof 等 27 | * 掌握 Makefile 的写法,注意通用性,提高编程效率 28 | 29 | #### 常用 API 30 | 31 | * 转换函数 32 | 33 | atof(); 将字符串转换成浮点型数 34 | atoi(); 将字符串转换成整型数 35 | atol(); 将字符串转换成长整型数 36 | strtod(); 将字符串转换成浮点数 37 | strtol(); 将字符串转换成长整型数 38 | strtoul(); 将字符串转换成无符号长整型数 39 | 40 | * 三角函数 41 | 42 | double sin(double x); 正弦 43 | double cos(double x); 余弦 44 | double tan(double x); 正切 45 | *cot 三角函数,可以使用tan(PI/2-x)来实现。 46 | 47 | * 反三角函数 48 | 49 | double asin(double x); 结果介于[-PI/2, PI/2] 50 | double acos(double x); 结果介于[0, PI] 51 | double atan(double x); 反正切(主值), 结果介于[-PI/2, PI/2] 52 | double atan2(double y,double); 反正切(整圆值), 结果介于[-PI, PI] 53 | 54 | * 双曲三角函数 55 | 56 | double sinh(double x); 计算双曲正弦 57 | double cosh(double x); 计算双曲余弦 58 | double tanh(double x); 计算双曲正切 59 | 60 | * 指数与对数 61 | 62 | double exp(double x); 求取自然数e的幂 63 | double sqrt(double x); 开平方 64 | double log(double x); 以e为底的对数 65 | double log10(double x); 以10为底的对数 66 | double pow(double x, double y); 计算以x为底数的y次幂 67 | float powf(float x, float y); 与pow一致,输入与输出皆为浮点数 68 | 69 | * 取整 70 | 71 | double ceil(double); 取上整 72 | double floor(double); 取下整 73 | 74 | * 标准化浮点数 75 | 76 | double frexp(double f, int *p); 标准化浮点数, f = x * 2^p, 已知f求x, p ( x介于[0.5, 1] ) 77 | double ldexp(double x, int p); 与frexp相反, 已知x, p求f 78 | 79 | * 取整与取余 80 | 81 | double modf(double, double*); 将参数的整数部分通过指针回传, 返回小数部分 82 | double fmod(double, double); 返回两参数相除的余数 83 | -------------------------------------------------------------------------------- /Unit-2/Lesson-29.md: -------------------------------------------------------------------------------- 1 | 2 | ## Lesson 29 - more command (more命令实现) 3 | 4 | ### 课程任务 5 | 实现Linux下 more 命令的基本功能,要求能够支持以下四个快捷键。 6 | 7 | * j 下移一行 8 | * k 上移一行 9 | * 空格/f 下翻页 10 | * b 上翻页。 11 | 12 | 13 | ### 参考资料 14 | * http://zh.wikipedia.org/wiki/More_(命令) 15 | * Linux 终端概念 http://blog.csdn.net/jifengszf/article/details/4228183 16 | * 自己编写more命令 http://www.cnblogs.com/zhangchaoyang/articles/2293910.html 17 | 18 | 19 | ### 重要知识点 20 | * 学习内存动态分配函数 malloc 21 | * 加强对于指针变量的管理和使用 22 | * 了解Linux关于终端 tty 的配置和编程 23 | 24 | #### 常用 API 25 | 26 | * 内存控制函数 27 | 28 | calloc(); 配置内存空间 29 | free(); 释放原先配置的内存 30 | malloc(); 配置内存空间 31 | realloc(); 重新分配主存 32 | 33 | ### 编程提示: 34 | * more 命令源码 http://git.busybox.net/busybox/tree/util-linux/more.c?h=1_13_stable 35 | 36 | * 关键流程 37 | * 从文件中每读一行,动态分配行缓冲区, 38 | * 将缓冲区内存指针写入到一个行指针数组中, 39 | * 通过用户键盘操作调整显示区域,并更新区域显示内容。 40 | 41 | -------------------------------------------------------------------------------- /Unit-2/Lesson-30.md: -------------------------------------------------------------------------------- 1 | 2 | ## Lesson 30 - sort (sort命令实现) 3 | 4 | ### 课程任务 5 | 实现Linux下 sort 命令的基本功能,要求能够支持以下三个参数。 6 | 7 | * -u 在输出行中去除重复行 8 | * -r 升序改成降序 9 | * -n 以数值来排序 10 | 11 | #### sort 命令运行示例 12 | 13 | limingth@gmail ~/Github/NCCL.codes/Lesson-30$ cat test.txt 14 | red 15 | black 16 | blue 17 | green 18 | yello 19 | blue 20 | limingth@gmail ~/Github/NCCL.codes/Lesson-30$ cat test.txt | sort 21 | black 22 | blue 23 | blue 24 | green 25 | red 26 | yello 27 | limingth@gmail ~/Github/NCCL.codes/Lesson-30$ cat test.txt | sort -u 28 | black 29 | blue 30 | green 31 | red 32 | yello 33 | limingth@gmail ~/Github/NCCL.codes/Lesson-30$ cat test.txt | sort -r 34 | yello 35 | red 36 | green 37 | blue 38 | blue 39 | black 40 | 41 | sort -n 效果 42 | 43 | limingth@gmail ~/Github/NCCL.codes/Lesson-30$ cat test.txt 44 | 1 red 45 | 5 black 46 | 15 blue 47 | 30 green 48 | 17 yello 49 | 2 blue 50 | limingth@gmail ~/Github/NCCL.codes/Lesson-30$ cat test.txt | sort 51 | 1 red 52 | 15 blue 53 | 17 yello 54 | 2 blue 55 | 30 green 56 | 5 black 57 | limingth@gmail ~/Github/NCCL.codes/Lesson-30$ cat test.txt | sort -n 58 | 1 red 59 | 2 blue 60 | 5 black 61 | 15 blue 62 | 17 yello 63 | 30 green 64 | 65 | ### 重要知识点 66 | * 学习 qsort 函数,弄懂快速排序的原理 67 | * 加强对函数指针知识点的巩固和应用 68 | * 掌握 sort 命令的参数和常见应用场景 69 | 70 | ### 参考资料 71 | * sort命令用法 http://roclinux.cn/?p=1350 72 | * qsort 函数的几种用法 http://www.cnblogs.com/pang123hui/archive/2011/01/28/1947003.html 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /Unit-2/Lesson-31.md: -------------------------------------------------------------------------------- 1 | ## Lesson 31 - ll 和 date (ls -l命令实现) 2 | 3 | ### 课程任务 4 | 1. 实现Linux下 ls -l 命令的基本功能,要求能够支持以下三个参数。 5 | 6 | * -i 在输出行中显示 inode 节点号 7 | * -s 显示每个文件占用的块数 8 | * -T 显示完整的时间信息,包含年月日时分秒信息 9 | 10 | 2. 实现 date 命令,显示当前时间。 11 | 12 | $ date 13 | 2014年 1月22日 星期三 14时07分31秒 PST 14 | 15 | 16 | ### 重要知识点 17 | * 学习使用 Linux 系统调用 stat 函数,了解有关 struct stat 中的关键数据结构。 18 | * 加强对结构体指针的使用,结合 Lesson 26 课的 file 命令获得关于文件系统的初步认识。 19 | * 掌握库函数中关于 time 部分的函数接口。 20 | 21 | ### 参考资料 22 | 23 | * [linux stat函数讲解](http://www.cnblogs.com/hnrainll/archive/2011/05/11/2043361.html) 24 | * [stat() example](http://www.minek.com/files/unix_examples/statfile.html) 25 | * [Time Functions Example](http://www.gnu.org/software/libc/manual/html_node/Time-Functions-Example.html) 26 | 27 | * `man 2 stat` 28 | 29 | struct stat { /* when _DARWIN_FEATURE_64_BIT_INODE is NOT defined */ 30 | dev_t st_dev; /* device inode resides on */ 31 | ino_t st_ino; /* inode's number */ 32 | mode_t st_mode; /* inode protection mode */ 33 | nlink_t st_nlink; /* number of hard links to the file */ 34 | uid_t st_uid; /* user-id of owner */ 35 | gid_t st_gid; /* group-id of owner */ 36 | dev_t st_rdev; /* device type, for special file inode */ 37 | struct timespec st_atimespec; /* time of last access */ 38 | struct timespec st_mtimespec; /* time of last data modification */ 39 | struct timespec st_ctimespec; /* time of last file status change */ 40 | off_t st_size; /* file size, in bytes */ 41 | quad_t st_blocks; /* blocks allocated for file */ 42 | u_long st_blksize;/* optimal file sys I/O ops blocksize */ 43 | u_long st_flags; /* user defined flags for file */ 44 | u_long st_gen; /* file generation number */ 45 | }; 46 | 47 | 48 | #### 常用 API 49 | 50 | * 重要数据结构 /usr/include/time.h 51 | 52 | struct tm { 53 | int tm_sec; /* seconds after the minute [0-60] */ 54 | int tm_min; /* minutes after the hour [0-59] */ 55 | int tm_hour; /* hours since midnight [0-23] */ 56 | int tm_mday; /* day of the month [1-31] */ 57 | int tm_mon; /* months since January [0-11] */ 58 | int tm_year; /* years since 1900 */ 59 | int tm_wday; /* days since Sunday [0-6] */ 60 | int tm_yday; /* days since January 1 [0-365] */ 61 | int tm_isdst; /* Daylight Savings Time flag */ 62 | long tm_gmtoff; /* offset from CUT in seconds */ 63 | char *tm_zone; /* timezone abbreviation */ 64 | }; 65 | 66 | * 时间函数 67 | 68 | time(); 取得目前的时间 69 | ctime(); 把日期和时间转换为字符串 70 | localtime(); 取得当地目前时间和日期 71 | strftime(); 将时间格式化 72 | asctime(); 将时间和日期以字符串格式表示 73 | 74 | clock(); 确定处理器时间 75 | difftime(); 计算两个时刻之间的时间差 76 | gmtime(); 把日期和时间转换为(GMT)时间 77 | mktime(); 将时间结构数据转换成经过的秒数 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /Unit-2/Lesson-32.md: -------------------------------------------------------------------------------- 1 | 2 | ## Lesson 32 - Bash Clone (Bash项目) 3 | 4 | ### 参考资料 5 | 6 | * [GNU Bash 源码下载](http://ftp.gnu.org/gnu/bash/) 7 | 8 | * [bash-4.1 源代码在线浏览](http://www.oschina.net/code/explore/bash-4.1) 9 | 10 | * [GNU bash实现机制与源代码简析](http://www.cnblogs.com/napoleon_liu/archive/2011/04/01/2001886.html) 11 | 12 | ### BashClone 项目设计 13 | 14 | * 整个项目新建一个目录 bashclone 15 | 16 | * 每个命令单独建一个目录,目录名就是生成的可执行文件名 17 | - mycp 18 | - readelf 19 | - sed 20 | - math 21 | - more 22 | - sort 23 | - ll 24 | 25 | * 根目录下的主要文件 26 | - main.c shell.c 27 | - Makefile 28 | 29 | * make all 30 | - 编译整个项目 31 | 32 | * make test 33 | - 单独测试每个命令 34 | 35 | ### ./bashclone 执行程序 36 | 37 | limingth@gmail ~/Github/NCCL.codes/Lesson-32$ ./bashclone 38 | demo argc & argv 39 | NCCL# mycp /usr/include/stdio.h stdio.h 40 | 41 | NCCL# readelf shell.o 42 | n = 1 43 | HSIZE = 48 44 | type = 1 45 | Type: REL 46 | 47 | NCCL# readelf bashclone 48 | n = 1 49 | HSIZE = 48 50 | type = 2 51 | Type: EXEC 52 | 53 | NCCL# sed 's/unix/linux' 54 | I love unix, unix is a great os. unix is better than linux. 55 | I love linux', unix is a great os. unix is better than linux. 56 | 57 | NCCL# sed 's/unix/linux/g' 58 | I love unix, unix is a great os. unix is better than linux. 59 | I love linux', linux is a great os. linux is better than linux. 60 | 61 | NCCL# sed 's/unix/linux/3' 62 | I love unix, unix is a great os. unix is better than linux. 63 | I love unix', unix is a great os. linux is better than linux. 64 | 65 | NCCL# math sin 1 66 | result = 0.841471 67 | 68 | NCCL# math sqrt 2 69 | result = 1.414214 70 | 71 | NCCL# more test.txt 72 | lines = 7 73 | w = 89, h = 27 74 | 1 red 75 | 5 black 76 | 15 blue 77 | 30 green 78 | 17 yello 79 | 2 blue 80 | 15 blue 81 | 82 | NCCL# sort test.txt 83 | 1 red 84 | 5 black 85 | 15 blue 86 | 30 green 87 | 17 yello 88 | 2 blue 89 | 15 blue 90 | --- after sort --- 91 | 1 red 92 | 15 blue 93 | 15 blue 94 | 17 yello 95 | 2 blue 96 | 30 green 97 | 5 black 98 | 99 | NCCL# sort test.txt -n 100 | 1 red 101 | 5 black 102 | 15 blue 103 | 30 green 104 | 17 yello 105 | 2 blue 106 | 15 blue 107 | --- after sort --- 108 | 1 red 109 | 2 blue 110 | 5 black 111 | 15 blue 112 | 15 blue 113 | 17 yello 114 | 30 green 115 | 116 | NCCL# sort test.txt -u 117 | 1 red 118 | 5 black 119 | 15 blue 120 | 30 green 121 | 17 yello 122 | 2 blue 123 | 15 blue 124 | --- after sort --- 125 | 1 red 126 | 2 blue 127 | 5 black 128 | 15 blue 129 | 17 yello 130 | 30 green 131 | 132 | NCCL# sort test.txt -r 133 | 1 red 134 | 5 black 135 | 15 blue 136 | 30 green 137 | 17 yello 138 | 2 blue 139 | 15 blue 140 | --- after sort --- 141 | 5 black 142 | 30 green 143 | 2 blue 144 | 17 yello 145 | 15 blue 146 | 1 red 147 | 148 | NCCL# ll test.txt 149 | Access mode: 0100644 150 | file uid = limingth 151 | file size = 56 152 | file last modify mtime = Sat Jan 25 00:12:24 2014 153 | The time is 01 25 00:12:24 2014 154 | 155 | NCCL# ll test.txt -i 156 | file st_ino = 16128001 157 | 158 | NCCL# ll test.txt -s 159 | file st_blocks = 8 160 | 161 | NCCL# ll test.txt -T 162 | The time is 01 25 00:12:24 2014 163 | 164 | 165 | -------------------------------------------------------------------------------- /Unit-2/Lesson-33.md: -------------------------------------------------------------------------------- 1 | 2 | ## Lesson 33 - 动态数组实现 3 | 4 | ### 课程任务 5 | 模拟高级语言中动态数组 Array 的特性,例如 [Ruby Array](http://ruby-doc.org/core-2.0/Array.html),用链表实现动态数组所需要的相关接口。 6 | 7 | ### 提高要求 8 | 使用以上实现的动态数组接口,模拟 qsort 函数通过函数指针 compar 作为传入参数,完成动态数组的冒泡插入排序。 9 | 10 | * Array.new -> array_new() 11 | * arr.first -> array_first() 12 | * arr.last -> array_last() 13 | * browsers.length -> array_length() 14 | * a.insert(2, 99) -> array_insert() 15 | * a.delete_at(2) -> array_delete_at() 16 | * a.clear -> array_clear() 17 | * a.index("b") -> array_index() 18 | * a.reverse! -> array_reverse() 19 | 20 | ### Ruby Array 学习实践 21 | 登录下面的Ruby在线编程网站 22 | 23 | #### 输入代码 24 | 25 | #!/usr/local/bin/ruby -w 26 | 27 | puts "Hello World!"; 28 | 29 | samples = ['a', 'c', 'd']; 30 | puts samples.first 31 | puts samples.last 32 | puts samples.length 33 | 34 | samples.insert(1, 'b') 35 | print samples 36 | puts 37 | 38 | samples.insert(5, 'f') 39 | print samples 40 | puts 41 | 42 | puts samples.index('f') 43 | 44 | puts samples.at(3) 45 | 46 | samples.delete_at(3) 47 | print samples 48 | puts 49 | 50 | samples.delete_at(3) 51 | print samples 52 | puts 53 | 54 | samples.reverse! 55 | print samples 56 | puts 57 | 58 | samples.sort! 59 | print samples 60 | puts 61 | 62 | samples.clear 63 | print samples 64 | puts 65 | 66 | #### 观察结果 67 | 68 | Executing the program.... 69 | $ruby main.rb 70 | Hello World! 71 | a 72 | d 73 | 3 74 | ["a", "b", "c", "d"] 75 | ["a", "b", "c", "d", nil, "f"] 76 | 5 77 | d 78 | ["a", "b", "c", nil, "f"] 79 | ["a", "b", "c", "f"] 80 | ["f", "c", "b", "a"] 81 | ["a", "b", "c", "f"] 82 | [] 83 | 84 | ### API 设计 85 | 86 | struct node; 87 | typedef struct node * link; 88 | typedef link Array; 89 | typedef link Item; 90 | 91 | Array array_new(void); // return the Array name 92 | Item array_first(Array name); // get the first Item of Array 93 | Item array_last(Array name); // get the last Item of Array 94 | int array_length(Array name); // count the size of Array elements 95 | void array_insert(Array name, int index, char data); // Inserts the given values before the element with the given index. -1 is the last element. 96 | void array_delete_at(int index, Array name); // Deletes the element at the specified index, returning that element, or nil if the index is out of range. 97 | void array_clear(Array name); // Removes all elements from Array name. 98 | int array_index(char data); // Returns the index of the first object in ary such that the object is == to obj. 99 | Array array_reverse(Array name); // Returns a new array containing self‘s elements in reverse order. 100 | 101 | Array array_sort(Array name, int (*compar)(Item n1, Item n2)); // Sort the array by function pointed to compar 102 | 103 | ### 重要知识点 104 | * 链表的生成,插入,删除,查找,逆序等操作 105 | * 链表的冒泡排序 106 | -------------------------------------------------------------------------------- /Unit-2/Lesson-34.md: -------------------------------------------------------------------------------- 1 | 2 | ## Lesson 34 - 约瑟夫环问题 3 | 4 | ### 课程任务 5 | 通过循环链表 circular list 这种特殊的数据结构(简称 clist),实现 Lesson 10 要求的约瑟夫环(Josephus Ring)问题。 6 | 7 | ### 重要知识点 8 | * 循环链表的生成,插入,删除等操作 9 | * cursor 游标的使用 10 | 11 | ### 数据结构和接口设计 12 | 13 | struct node 14 | { 15 | void *data; 16 | struct node * next; 17 | }; 18 | 19 | typedef struct node * link; 20 | 21 | link make_node(void *data); 22 | int *make_data(int data); 23 | 24 | void print_int_data(void *data); 25 | 26 | link clist_new(void); 27 | void clist_print(link cur, void (*pf)(void *)); 28 | link clist_insert_after(link cur, link item); 29 | link clist_delete(link cur, link item); 30 | int clist_length(link cur); 31 | 32 | ### 主程序流程 33 | 34 | #include 35 | #include "clist.h" 36 | 37 | int main(void) 38 | { 39 | link cursor = NULL; 40 | int i = 0; 41 | 42 | clist_print(cursor, print_int_data); 43 | 44 | for (i = 0; i < 100; i++) 45 | { 46 | int *p = make_data(i+1); 47 | link item = make_node(p); 48 | cursor = clist_insert_after(cursor, item); 49 | } 50 | 51 | cursor = cursor->next; 52 | clist_print(cursor, print_int_data); 53 | printf("ring list length = %d\n", clist_length(cursor)); 54 | 55 | int step = 0; 56 | while (cursor != NULL) 57 | { 58 | print_int_data(cursor->data); 59 | step++; 60 | 61 | if (step == 3) 62 | { 63 | printf("-> %d out\n", *(int *)(cursor->data)); 64 | cursor = clist_delete(cursor, cursor); 65 | printf("length = %d\n", clist_length(cursor)); 66 | step = 0; 67 | } 68 | else 69 | cursor = cursor->next; 70 | 71 | //getchar(); 72 | //sleep(1); 73 | } 74 | 75 | return 0; 76 | } 77 | 78 | -------------------------------------------------------------------------------- /Unit-2/Lesson-35.md: -------------------------------------------------------------------------------- 1 | ## Lesson 35 - 表达式求值问题 2 | 3 | ### 课程任务 4 | 学习[逆波兰表达式的概念](http://zh.wikipedia.org/wiki/%E9%80%86%E6%B3%A2%E5%85%B0%E8%A1%A8%E7%A4%BA%E6%B3%95),使用栈这种数据结构作为操作数缓存区,计算后缀表达式的值。 5 | 6 | 例如 12+3*4+ 和 123*+4- ,结果分别为 13 和 3。 7 | 8 | 后缀表达式计算规则如下: 9 | 10 | 1. 如果是操作数,则放入栈中; 11 | 2. 如果是操作符,则取出栈中两个操作数,进行运算后,将结果放入栈中; 12 | 3. 直到最后栈中只有一个元素,此元素就是计算结果; 13 | 14 | * 提示:只需要考虑实现加减乘除四则运算,所有数字都是1个字符的情况。 15 | 16 | ### 提高要求 17 | 使用2个栈--操作数栈和操作符栈,实现将中缀表达式转换为后缀形式,并实现求值。 18 | 19 | 例如 5 + ((1 + 2) * 4) - 3 => 5 1 2 + 4 * + 3 - => 14 20 | 21 | 中缀表达式转换成后缀表达式,此方法需要遵循规则如下: 22 | 23 | 1. 如果读入操作数,则直接放入输出字符串; 24 | 2. 如果读入一般运算符如+-*/,则放入堆栈,但是放入堆栈之前必须要检查栈顶,并确定栈顶运算符的优先级比放入的运算符的优先级低; 25 | 如果放入的优先级较低,则需要将栈顶的运算符放入输出字符串; 26 | 3. 如果读入(,因为左括号优先级最高,因此放入栈中,但是注意,当左括号放入栈中后,则优先级最低; 27 | 4. 如果读入),则将栈中运算符取出放入输出字符串,直到取出(为止,注意:()不输出到输出字符串; 28 | 5. 顺序读完表达式,如果栈中还有操作符,则弹出,并放入输出字符串; 29 | 30 | ### 重要知识点 31 | * 栈 32 | * 逆波兰表达式 33 | * 后缀表示法 34 | 35 | ### 参考资料 36 | * 栈的数据结构表示 37 | * 后缀表达式总结 38 | * 前缀,中缀,后缀表达式学习笔记(1) 39 | -------------------------------------------------------------------------------- /Unit-2/Lesson-36.md: -------------------------------------------------------------------------------- 1 | 2 | ## Lesson 36 - 广度优先解决迷宫问题 3 | 4 | ### 课程任务 5 | 队列是一组元素的集合,提供两种基本操作:Enqueue(入队)将元素添加到队尾,Dequeue(出队)从队头取出元素并返回。就像排队买票一样,先来先服务,先入队的人也是先出队的,这种方式称为FIFO(First In First Out,先进先出),有时候队列本身也被称为FIFO。 6 | 7 | 请使用队列解决迷宫问题 -- 我们定义一个二维数组: 8 | 9 | int maze[5][5] = { 10 | 0, 1, 0, 0, 0, 11 | 0, 1, 0, 1, 0, 12 | 0, 0, 0, 0, 0, 13 | 0, 1, 1, 1, 0, 14 | 0, 0, 0, 1, 0, 15 | }; 16 | 17 | 它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的路线。 18 | 19 | (0, 0) (1, 0) (2, 0) (2, 1) (2, 2) (2, 3) (2, 4) (3, 4) (4, 4) 20 | 21 | * 提示:使用队列进行广度优先搜索,使用 head, tail 来表示队列的队首和队尾,使用栈来对前趋节点进行逆序输出。 22 | 23 | ### 重要知识点 24 | * 队列 25 | * 栈 26 | 27 | ### 参考资料 28 | * 队列与广度优先搜索 29 | * 用深度优先搜索解迷宫问题 -------------------------------------------------------------------------------- /Unit-2/Lesson-37.md: -------------------------------------------------------------------------------- 1 | 2 | ## Lesson 37 - 词频统计器 3 | 4 | ### 课程任务 5 | 链表的每个节点可以有一个后继 next,而二叉树(Binary Tree)的每个节点可以有两个后继:l 表示左子树,r 表示右子树。 6 | 7 | **排序二叉树(BST,Binary Search Tree)** 是二叉树的一个特殊形态,它具有这样的性质: 8 | 9 | 对于二叉树中的任意节点,如果它有左子树或右子树,则该节点的数据成员大于左子树所有节点的数据成员,且小于右子树所有节点的数据成员。 10 | 11 | 使用排序二叉树这种数据结构,统计一个文本文件中所有英文字母的出现次数,然后按字母顺序打印输出。简化起见,字母不区分大小写。 12 | 13 | ### 提高要求 14 | 统计文本中英文单词的出现次数,使用 [tree 树形打印软件](https://www.essex.ac.uk/linguistics/external/clmt/latex4ling/trees/tree/tree.tar),打印上题中生成的二叉树,并按照单词出现的次数从多到少依次打印输出。 15 | 16 | * 提示:可以获得二叉树中单词出现次数最多的节点,然后将它从树上删除,重复上述操作,直到输出所有单词节点。 17 | 18 | ### 重要知识点 19 | * 空二叉树 vs 满二叉树 vs 完全二叉树 20 | * 平衡二叉树 和 排序二叉树 21 | * 二叉树的前序(Pre-order),中序(In-order)和后序(Post-order)遍历。 22 | * 前序和中序遍历的结果合在一起可以唯一确定二叉树的形态,也就是说根据遍历结果可以构造出二叉树。 23 | * 排序二叉树的中序遍历结果就是所有节点根据键值从小到大的顺序输出。 24 | * 排序二叉树的插入操作 25 | * 排序二叉树的删除操作 26 | 27 | ### 参考资料 28 | * 二叉树的基本概念 29 | * The `Tree' preprocessor 30 | 31 | -------------------------------------------------------------------------------- /Unit-2/Lesson-38.md: -------------------------------------------------------------------------------- 1 | 2 | ## Lesson 38 - 堆排序问题 3 | 4 | ### 课程任务 5 | 堆是一个近似完全二叉树的结构,并同时满足堆的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。 6 | 7 | **如果一个堆的根节点是大值,则称为最大堆。** 8 | 9 | 堆排序算法的基本思想是,将数组A创建为一个最大堆,然后交换堆的根(最大元素)和最后一个叶节点x,将x从堆中去掉形成新的堆A1,然后重复以上动作,直到堆中只有一个节点。 10 | 11 | 通常堆是通过一维数组来实现的。在起始数组下标为 0 的情形中: 12 | 13 | * 父节点i的左子节点在位置 (2*i+1); 14 | * 父节点i的右子节点在位置 (2*i+2); 15 | 16 | #### 堆、二叉树和数组下标的对应关系 17 | ![heap-array](../images/heap-array.png) 18 | 19 | #### 堆排序算法 20 | * 数组的起始状态(随机排列) 21 | ![heap-random](../images/heap-random.png) 22 | 23 | * **单一末端子节点的最大堆调整(Max_Heapify)** 24 | ![heap-0-max-heapify](../images/heap-0-max-heapify.png) 25 | 26 | 如下图所示,将堆的任一子节点 A(4)作调整,使得以A为根节点的树,所有子节点永远小于父节点。 27 | 28 | 这个调整需要用到递归,较小的子节点会(4)逐级下降。 29 | 30 | **算法需要确保在对 A(4) 做调整时,A 的左子树 14 和右子树 7 都分别已经是最大堆了。这是由子节点做调整的先后顺序来确保的。** 31 | 32 | ![heap-max-heapify](../images/heap-max-heapify.png) 33 | 34 | * **建立最大堆树(Build_Max_Heap)** 35 | - 将堆所有子节点数据按照从最底层向最上层的顺序,进行最大堆调整(Max_Heapify),重新排序后建立最大堆树。(这样根节点就是最大值) 36 | 37 | ![heap-1-build-max](../images/heap-1-build-max.png) 38 | 39 | * 交换根节点(最大值)和数组最后那个位置的元素,然后对 size-1 的树重新进行“建立最大堆树” 40 | ![heap-2-swap-max-to-last](../images/heap-2-swap-max-to-last.png) 41 | ![heap-3-swap-max-to-next](../images/heap-3-swap-max-to-next.png) 42 | 43 | * 重复以上动作,直到堆中只有一个节点,算法结束 44 | ![heap-4-swap-to-first](../images/heap-4-swap-to-first.png) 45 | 46 | 47 | ### 参考资料 48 | * 堆排序 49 | * 经典排序算法 - 堆排序Heap sort 50 | 51 | 52 | -------------------------------------------------------------------------------- /Unit-2/Lesson-39.md: -------------------------------------------------------------------------------- 1 | 2 | ## Lesson 39 - 构造符号表 3 | 4 | ### 课程任务 5 | [符号表](http://zh.wikipedia.org/wiki/%E7%AC%A6%E5%8F%B7%E8%A1%A8)是一种用于语言翻译器(例如编译器和解释器)中的数据结构。 6 | 7 | 在符号表中,程序源代码中的每个标识符都和它的声明或使用信息绑定在一起,比如其数据类型、作用域以及内存地址。 8 | 9 | 参考 [一个C语言实现的哈希表](http://hi.baidu.com/thinkingroom/item/ceed1103c3d3d9e935990234),实现对 a.out 中符号地址的查询功能。 10 | 11 | * 提示:可以通过 nm a.out 输出符号表信息,或者通过对 a.out ELF 格式的解析获取符号表信息。 12 | 13 | ### 参考资料 14 | * 散列表 15 | * 散列表(哈希表)工作原理 16 | * 散列表(Hash Table)全解析 17 | * 语法制导翻译 18 | * [《数据抽象和问题求解:C++语言描述》](http://books.google.com.hk/books?id=LniK4hrQagUC&pg=PP13&lpg=PP13&dq=%E6%95%B0%E6%8D%AE%E6%8A%BD%E8%B1%A1%E5%92%8C%E9%97%AE%E9%A2%98%E6%B1%82%E8%A7%A3&source=bl&ots=N1Mx3DwnL0&sig=4C-zNvCjDmvsFQ6dnZ0iRZb5B94&hl=zh-CN&sa=X&ei=MkIFU-KvAoeiigev24CwDw&ved=0CGYQ6AEwCA#v=onepage&q=%E6%95%B0%E6%8D%AE%E6%8A%BD%E8%B1%A1%E5%92%8C%E9%97%AE%E9%A2%98%E6%B1%82%E8%A7%A3&f=false) 19 | -------------------------------------------------------------------------------- /Unit-2/Lesson-40.md: -------------------------------------------------------------------------------- 1 | ## Lesson 40 - MyDictionary项目 2 | 3 | 项目说明 4 | ======== 5 | 6 | 给定文本文件“dict.txt”,该文件用于存储词库。词库为“英-汉”,“汉-英”双语词典,每个单词和其解释的格式固定,如下所示: 7 | 8 | #单词 9 | Trans:解释1@解释2@…解释n 10 | 11 | 每个新单词由“#”开头,解释之间使用“@”隔开。一个词可能有多个解释,解释均存储在一行里,行首固定以“Trans:”开头。 12 | 13 | 下面是一个典型的例子: 14 | 15 | #abyssinian 16 | Trans:a. 阿比西尼亚的@n. 阿比西尼亚人;依索比亚人 17 | 18 | 该词有两个解释,一个是“a. 阿比西尼亚的”;另一个是“n. 阿比西尼亚人;依索比亚人”。 19 | 20 | * 词库文件下载 [dict.txt](https://dl.dropboxusercontent.com/u/63667688/dict.txt) 21 | 22 | 项目要求 23 | ======== 24 | 25 | ### 1. 单词查询 26 | 27 | 要求编写程序将词库文件读取到内存中,接受用户输入的单词,在字典中查找单词,并且将解释输出到屏幕上。 28 | 用户可以反复输入,直到用户输入“exit”字典程序退出。 29 | 30 | 程序执行格式如下所示: 31 | ./mydict 32 | 默认使用 dict.txt 文本词库进行单词查找。 33 | ./mydict -f mydict.txt 34 | 表示使用文本词库 mydict.txt 文件进行单词查找。 35 | 36 | *用户输入单词的前n个字母,可以作为模糊查询,提示用户匹配的单词。* 37 | 38 | ### 2. 支持用户自添加新词/删除单词 39 | 用户添加的新词存放在指定文件中。如果待查单词在词库中找不到,则使用用户提供的词库。用户的词库使用文本形式保存,便于用户修改。 40 | 41 | 程序执行格式如下所示。 42 | ./mydict --add/del -f mydict.txt 43 | --add/del 表示进入删除或者添加模式,-f为固定参数,用来指定用户词库文件名. 44 | 45 | ### 3. 查询单词的词频统计 46 | 用户查询过程中,记录查询单词和查询次数,便于用户进行单词词频的统计。 47 | 48 | 程序执行格式如下所示。 49 | ./mydict --search-sort 50 | 51 | 按照查询次数从多到少依次列出用户曾经查询过的单词和查询次数。 52 | 53 | * 可以在此基础上,实现一个简单的生词记忆程序,帮助用户背记经常查询的生词* 54 | 55 | ### 4. 网页翻译 56 | 用户指定一个web页面的链接,程序对网页上面的正文内容进行翻译,并输出到一个文本文件中。 57 | 58 | 程序执行格式如下所示。 59 | ./mydict --translate http://www.google.com.hk/intl/en/about/ 60 | ./mydict --translate http://www.kernel.org -o result.html 61 | 62 | 63 | 技术参考 64 | ======== 65 | 66 | ### ncurses 库 - 实现 Linux 终端上的图形界面编程 67 | 参考资料: google "NCURSES Programming HOWTO中文版" 68 | 安装: sudo apt-get install ncurses-dev 69 | 使用: gcc your_program.c -lncurses 70 | 71 | ### wget 命令 - 网页抓取工具 72 | 参考资料: man wget 73 | 74 | ### system 调用 - 实现C程序中调用 shell 命令 75 | 参考资料: man system 76 | 77 | 考察知识点 78 | ========== 79 | (1) 变量数据类型 80 | (2) 数组 81 | (3) 结构体 82 | (4) typedef关键字的使用 83 | (5) 控制结构 84 | (6) 函数接口设计 85 | (7) static关键字的使用 86 | (8) 文件拆分与代码组织 87 | (9) 模块化设计思想 88 | (10) 简单的面向对象程序设计思想 89 | (11) 指针与指针控制 90 | (12) const关键字的使用 91 | (13) C语言程序的命令行参数 92 | (14) 多文件符号解析 93 | (15) 头文件包含 94 | (16) 宏 95 | (17) 条件编译 96 | (18) 字符串操作 97 | (19) malloc函数 98 | (20) 常用的字符串库函数 99 | (21) 文件操作 100 | (22) 简单的出错处理 101 | (23) 排序算法和二分查找算法 102 | (24) 二进制文件和文本文件的区别 103 | (25) 链表操作 104 | (26) 复杂链表的链表操作 105 | (27) 二叉树 106 | (28) makefile的使用 107 | (29) 编程工具的使用(vi,gcc,gdb) 108 | (30) 文档组织和项目规划 109 | 110 | 111 | -------------------------------------------------------------------------------- /Unit-2/Lesson-41.md: -------------------------------------------------------------------------------- 1 | ## Lesson 41 - BSearch 实现 2 | 3 | ### 课程任务 4 | 在 [《C程序设计语言》](https://www.dropbox.com/s/qer3va6rtq8o1dj/C%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E8%AF%AD%E8%A8%80%EF%BC%88%E7%AC%AC2%E7%89%88%C2%B7%E6%96%B0%E7%89%88%EF%BC%89.pdf)书第3.3小节中,介绍了一个折半查找函数 binsearch(),如下所示: 5 | 6 | /* binsearch: find x in v[0] <= v[1] <= ... <= v[n-1] */ 7 | int binsearch(int x, int v[], int n) 8 | { 9 | int low, high, mid; 10 | low = 0; 11 | high = n - 1; 12 | while (low <= high) { 13 | mid = (low+high)/2; 14 | if (x < v[mid]) 15 | high = mid - 1; 16 | else if (x > v[mid]) 17 | low = mid + 1; 18 | else /* found match */ 19 | return mid; 20 | } 21 | return -1; /* no match */ 22 | } 23 | 24 | 请参照这个算法思想,实现标准库函数中 bsearch 函数。 25 | 26 | #include 27 | 28 | void * 29 | bsearch(const void *key, const void *base, size_t nel, size_t width, 30 | int (*compar) (const void *, const void *)); 31 | 32 | ### 参考资料 33 | * 把二分查找算法写正确需要注意的地方 34 | * 二分查找(Binary Search)需要注意的问题,以及在数据库内核中的实现 35 | -------------------------------------------------------------------------------- /Unit-2/Lesson-42.md: -------------------------------------------------------------------------------- 1 | 2 | ## Lesson 42 - QSort 实现 3 | 4 | ### 课程任务 5 | 6 | 快速排序采用了一种分治策略,学术上称之为分治法(Divide-and-Conquer Method)。 7 | 8 | 分治的基本思想是将原问题分解成若干个规模更小但是结构跟原问题相似的子问题。递归的解决这些子问题,然后将这些子问题的解合并为原问题的解。 9 | 10 | 在 [《C程序设计语言》](https://www.dropbox.com/s/qer3va6rtq8o1dj/C%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E8%AF%AD%E8%A8%80%EF%BC%88%E7%AC%AC2%E7%89%88%C2%B7%E6%96%B0%E7%89%88%EF%BC%89.pdf)书中,介绍了一个快速排序函数 qsort(),如下所示: 11 | 12 | /* swap: interchange v[i] and v[j] */ 13 | void swap(int v[], int i, int j) 14 | { 15 | int temp; 16 | temp = v[i]; 17 | v[i] = v[j]; 18 | v[j] = temp; 19 | } 20 | 21 | /* qsort: sort v[left]...v[right] into increasing order */ 22 | void qsort(int v[], int left, int right) 23 | { 24 | int i, last; 25 | void swap(int v[], int i, int j); 26 | if (left >= right) /* do nothing if array contains */ 27 | return; /* fewer than two elements */ 28 | 29 | swap(v, left, (left + right)/2); /* move partition elem */ 30 | last = left; /* to v[0] */ 31 | for (i = left + 1; i <= right; i++) /* partition */ 32 | if (v[i] < v[left]) 33 | swap(v, ++last, i); 34 | swap(v, left, last); 35 | qsort(v, left, last-1); 36 | qsort(v, last+1, right); 37 | /* restore partition elem */ 38 | } 39 | 40 | 请参照这个算法思想,实现标准库函数中 qsort 函数。 41 | 42 | #include 43 | 44 | void 45 | qsort(void *base, size_t nel, size_t width, 46 | int (*compar)(const void *, const void *)); 47 | 48 | ### 参考资料 49 | * 快速排序 50 | -------------------------------------------------------------------------------- /Unit-2/Lesson-43.md: -------------------------------------------------------------------------------- 1 | 2 | ## Lesson 43 - 深度优先解决迷宫问题 3 | 4 | ### 课程任务 5 | 请用深度优先解决 [Lesson 36](Lesson-36.md) 中的迷宫问题,找出该问题的所有解。 6 | 7 | ### 提高要求 8 | 使用栈作为数据结构,通过回溯法来找出所有解。 9 | 10 | * 提示: 当找到一个解后,如果栈里仍有可扩展点,则回退到和这个点具有共同父节点的点为止。 11 | 12 | ### 参考资料 13 | * 深度优先搜索 -------------------------------------------------------------------------------- /Unit-2/Lesson-44.md: -------------------------------------------------------------------------------- 1 | 2 | ## Lesson 44 - KMP 算法实现 3 | 4 | ### 课程任务 5 | 6 | 参考 [Knuth-Morris-Pratt 字符串查找算法](http://zh.wikipedia.org/wiki/%E5%85%8B%E5%8A%AA%E6%96%AF-%E8%8E%AB%E9%87%8C%E6%96%AF-%E6%99%AE%E6%8B%89%E7%89%B9%E7%AE%97%E6%B3%95),实现字符串查找的 KMP 算法。 7 | 8 | 重要结论: 9 | * 当比较过程中发生不匹配时,不需要把搜索位置移回到已经比较过的位置,可以根据前面比较过字符中所包含的部分匹配信息(partial match),向后移动较多位置,从而提高比较效率。 10 | * 部分匹配表的作用就是计算向后移动的位数=已匹配的字符数-对应的部分匹配值 11 | * 最后一个元素的部分匹配值为0,表示找到一个完全匹配,跳过整个匹配字符串继续向后搜索。 12 | * 部分匹配的本质就是字符串的头部和尾部会有重复,重复部分的长度等于最长的前缀后缀共有元素长度,每次不匹配时需要向后移动的长度就是要确保这个匹配(即前缀和后缀的最多共有元素产生相同比较)能够发生。 13 | 14 | ### 参考资料 15 | * 字符串匹配的KMP算法 16 | * 字符串匹配的Boyer-Moore算法 17 | * Knuth-Morris-Pratt string matching 18 | * Knuth-Morris-Pratt (KMP) String Search Algorithm source code 19 | -------------------------------------------------------------------------------- /Unit-2/Lesson-45.md: -------------------------------------------------------------------------------- 1 | 2 | ## Lesson 45 - 最长公共子序列(LCS)问题 3 | 4 | ### 课程任务 5 | 6 | LCS:又称最长公共子序列(Longest Common Subsequences)。 其中子序列(subsequence)的概念不同于串的子串。它是一个不一定连续但按顺序取自字符串X中的字符序列。 7 | 8 | 一个序列 S,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。 9 | 10 | 参考 [动态规划](http://zh.wikipedia.org/wiki/动态规划) ,给定2个字符串,求它们的最长公共子序列。 11 | 12 | 例如 13 | 14 | a = "ABCBDAB" 15 | b = "BDCBA" 16 | 17 | LCS => "BCBA" 18 | 19 | * 提示:转移方程: 20 | 21 | dp[i,j] = 0 i=0 || j=0 22 | 23 | dp[i,j] = dp[i-1][j-1]+1 i>0,j>0, a[i] = b[j] 24 | 25 | dp[i,j] = max(dp[i-1][j],dp[i][j-1]) i>0,j>0, a[i] != b[j] 26 | 27 | a串长度为0,b串长度为0,两者的公共子序列长度为0 28 | 29 | 若两序列的最后一个字符相同,那么公共子序列长度为去掉这最后一个字符后新生成的两个串的公共子序列长度+1 30 | 31 | 若两序列最后一个字符不同,那么他们最大子序列的长度为c[i-1][j]和c[i][j-1]中较大的一个 32 | 33 | ### 参考资料 34 | * 最长公共子序列 35 | * diff 原理初探 36 | * Dynamic Programming 37 | * 最长公共子序列问题 38 | -------------------------------------------------------------------------------- /Unit-2/Lesson-46.md: -------------------------------------------------------------------------------- 1 | 2 | ## Lesson 46 - Dijkstra 算法 3 | 4 | ### 课程任务 5 | 对下面的有向图,求出从A出发到任一其他点的最短路径。 6 | 7 | ![vector-graph](../images/vector-graph.jpg) 8 | 9 | 算法要点: 10 | * 首先将各点的已知最短距离设为无穷大,前驱点都未知 11 | * 从起点开始拓展边(u,v) 如果d[v] > d[u] + w(u,v) 则更新d[v] 12 | * 更新d[v]的同时,记录v的前驱点,以便未来能够回溯出最短路径 13 | * 起点所在的集合为S,保留我们已知d[v]的值是最短路径的顶点集合 14 | * 其他所有点的集合为Q,每次遍历都有一个顶点从Q移动到S,这个被选择的顶点是Q中拥有最小的d[u]值的顶点 15 | 16 | ![dj-algorithm](../images/dj-algorithm.png) 17 | 18 | ### 图论编程 19 | * 点集合用一维字符数组表示,数组元素为点的名称 20 | * 边集合用二维整型数组表示,数组元素为边的长度 21 | * 有向图用横坐标和纵坐标表示,横坐标为起点,纵坐标为终点 22 | * 最佳路径的轨迹,只需记录该路径上每个点的前趋,前驱点也是用一维数组表示 23 | 24 | ### 参考资料 25 | * 迪科斯彻算法 26 | * 迪科斯彻算法(Dijkstra)[视频演示](http://v.youku.com/v_show/id_XMjQyOTY1NDQw.html) 27 | -------------------------------------------------------------------------------- /Unit-2/Lesson-47.md: -------------------------------------------------------------------------------- 1 | 2 | ## Lesson 47 - Huffman Coding 算法 3 | 4 | ### 课程任务 5 | 霍夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度,树的路径长度是从树根到每一结点的路径长度之和 6 | 7 | 霍夫曼编码(Huffman Coding)是一种编码方式,是一种用于无损数据压缩的熵编码(权编码)算法。 8 | 9 | 请对 [Lesson 37](Lesson-37.md) 所统计的文本中出现的英文字母,进行霍夫曼编码,并对比使用算法后的文本大小压缩比。 10 | 11 | 算法要点: 12 | * 将每个英文字母依照出现频率由小排到大 13 | * 将最小的两个字母频率相加合成一个新的节点 14 | * 比较新节点和其他节点,仍然找出频率最小的2个点合并 15 | * 重复上面2个步骤,直到没有可以比较的对象 16 | * 最后产生的树状图就是霍夫曼树 17 | 18 | ![huffman-tree](../images/huffman-tree.png) 19 | ![huffman-tree](../images/huffman-freq.png) 20 | 21 | ### 参考资料 22 | * 霍夫曼编码算法 23 | * 哈夫曼编码的C语言实现 24 | * Huffman 编码压缩算法 25 | -------------------------------------------------------------------------------- /Unit-2/Lesson-48.md: -------------------------------------------------------------------------------- 1 | 2 | ## Lesson 48 - 地图导航项目 3 | 4 | ### 课程任务 5 | * 请根据下图的信息,使用 ncurses 库绘制出一张中国城市地图 6 | * 实现一个地图导航应用,可以添加和删除新的城市和路线信息 7 | * 提供用户输入界面,可以计算出任意两个城市之间的最短路径和路线信息。 8 | 9 | ![china-cities](../images/china-cities.png) 10 | 11 | ### 重要知识点 12 | * ncurses 库的使用 13 | - http://www.paulgriffiths.net/program/c/ 14 | - http://invisible-island.net/ncurses/ncurses-intro.html 15 | 16 | ### 参考资料 17 | * 用弗洛伊德最短路径实现任意两个城市之间的最短距离 18 | -------------------------------------------------------------------------------- /Unit-2/README.md: -------------------------------------------------------------------------------- 1 | NCCL - New Concept C Language 2 | ============================= 3 | 4 | Unit 1 的全部免费视频课程共 42 集已经可以下载,请点击下面的链接进入学习 5 | 6 | 新概念 C 语言 Unit 1 相关资源: [<课程链接>](https://github.com/limingth/NCCL/blob/master/Unit-1/README.md) [<代码链接>](https://github.com/limingth/NCCL.codes) [<在线观看视频链接>](http://c.biancheng.net/cpp/u/shipin_liming/) (手机上观看视频需要安装百度云盘) 7 | 8 | ## Unit 2 课程规划 9 | 10 | 本阶段学习没有视频课程,只接受基于互联网的一对一在线辅导编程。 11 | 12 | 如需要学习,请直接联系咨询 QQ:2372614758 (毛豆网李明老师)或者申请加入QQ群 279027455 13 | 14 | ### Section 1 库函数 15 | 基本概念介绍:[C标准函数库](http://zh.wikipedia.org/zh-cn/C%E6%A8%99%E6%BA%96%E5%87%BD%E5%BC%8F%E5%BA%AB) 16 | * Lesson 25 - mycp (cp命令实现) 17 | - [文件读写](Lesson-25.md) 18 | * Lesson 26 - ELF Header Parser (ELF文件头分析器实现) 19 | - [输入输出](Lesson-26.md) 20 | * Lesson 27 - sed simple (简单流处理器实现和正则表达式) 21 | - [字符串处理](Lesson-27.md) 22 | * Lesson 28 - math calculator (数学计算器实现) 23 | - [数学库](Lesson-28.md) 24 | * Lesson 29 - more command (more命令实现) 25 | - [内存管理](Lesson-29.md) 26 | * Lesson 30 - sort (sort命令实现) 27 | - [排序查找](Lesson-30.md) 28 | * Lesson 31 - ll (ls -l命令实现) 29 | - [时间日期](Lesson-31.md) 30 | 31 | #### 项目选题 32 | * Lesson 32 - MyBash 项目 33 | - [Bash命令解释器](Lesson-32.md) 34 | - Bash 基本功能,文件查看功能 35 | - mycp,file,sed, math, more, sort,ll命令 36 | 37 | ### Section 2 常用数据结构 38 | * Lesson 33 - 动态数组实现 39 | - [单向链表](Lesson-33.md) 40 | * Lesson 34 - 约瑟夫环问题 41 | - [循环链表](Lesson-34.md) 42 | * Lesson 35 - 表达式求值问题 43 | - [栈](Lesson-35.md) 44 | * Lesson 36 - 广度优先解决迷宫问题 45 | - [队列](Lesson-36.md) 46 | * Lesson 37 - 词频统计器 47 | - [二叉树](Lesson-37.md) 48 | * Lesson 38 - 堆排序问题 49 | - [堆](Lesson-38.md) 50 | * Lesson 39 - 构造符号表 51 | - [散列表](Lesson-39.md) 52 | 53 | #### 项目选题 54 | * Lesson 40 - MyDictionary 项目 55 | - [查字典程序](Lesson-40.md) 56 | 57 | ### Section 3 常用基本算法 58 | * Lesson 41 - BSearch 实现 59 | - [二分查找法](Lesson-41.md) 60 | * Lesson 42 - QSort 实现 61 | - [分治法](Lesson-42.md) 62 | * Lesson 43 - 深度优先解决迷宫问题 63 | - [回溯法](Lesson-43.md) 64 | * Lesson 44 - KMP 算法实现 65 | - [字符串匹配KMP算法](Lesson-44.md) 66 | * Lesson 45 - 最长公共子序列(LCS)问题 67 | - [动态规划算法](Lesson-45.md) 68 | * Lesson 46 - Dijkstra 算法 69 | - [最短路径算法](Lesson-46.md) 70 | * Lesson 47 - Huffman Coding 算法 71 | - [霍夫曼编码算法](Lesson-47.md) 72 | 73 | #### 项目选题 74 | * Lesson 48 - MyGPS 项目 75 | - [地图导航项目](Lesson-48.md) 76 | 77 | ### 参考教材 78 | - [C Programming Language Edition 2](http://ishare.iask.sina.com.cn/download/explain.php?fileid=2302709) 79 | - [Standard C 语言标准函数库速查](http://ganquan.info/standard-c/) 80 | - [The C Standard Library Reference](http://www.tutorialspoint.com/c_standard_library/) 81 | - [The C Library Reference Guide](http://www.acm.uiuc.edu/webmonkeys/book/c_guide/) 82 | - [Linux C 一站式编程](http://docs.linuxtone.org/ebooks/C&CPP/c/) 83 | - [C语言标准库函数](https://www.scaler.com/topics/c/library-functions-in-c/) 84 | 85 | -------------------------------------------------------------------------------- /Unit-3/Lesson-49.md: -------------------------------------------------------------------------------- 1 | ## Lesson 49 Delete the comments in the C program C程序去注释问题 2 | 3 | ### [Codes List](Lesson-49/) 4 | 5 | * 语法知识点 6 | - 状态机编程 Finite State Machine 7 | - 文件读写函数 fopen/fread/fwrite/fclose 8 | - C语言注释语法 -------------------------------------------------------------------------------- /Unit-3/Lesson-49/Makefile: -------------------------------------------------------------------------------- 1 | SRC = state.c readfile.c 2 | 3 | all: 4 | gcc -DDEBUG $(SRC) -o a.out 5 | gcc $(SRC) -o demo 6 | 7 | run: 8 | ./demo test.c 9 | 10 | -------------------------------------------------------------------------------- /Unit-3/Lesson-49/a.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/Unit-3/Lesson-49/a.out -------------------------------------------------------------------------------- /Unit-3/Lesson-49/demo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/Unit-3/Lesson-49/demo -------------------------------------------------------------------------------- /Unit-3/Lesson-49/out.txt: -------------------------------------------------------------------------------- 1 | Open test.c Successed! 2 | #include 3 | * 4 | /* 5 | * state.c - using FSM to find (+/-)number strings in buf 6 | * 7 | * Copyright (C) 2010 li ming 8 | * 9 | * find number string such as 123, +1, -03708 in "ab123+1--03708" 10 | * 11 | */*8* 12 | 13 | * 14 | /* the string buffer to deal with */ 15 | char ch = '\"'; /*test* /222*/ char buf[1024] = "abc /*test*/ 1234"; 16 | 17 | /* the result number string buffer to save the result */ 18 | char numstr[32][64]; 19 | 20 | 21 | 406 bytes read from test.c 22 | your input string is: #include 23 | * 24 | /* 25 | * state.c - using FSM to find (+/-)number strings in buf 26 | * 27 | * Copyright (C) 2010 li ming 28 | * 29 | * find number string such as 123, +1, -03708 in "ab123+1--03708" 30 | * 31 | */*8* 32 | 33 | * 34 | /* the string buffer to deal with */ 35 | char ch = '\"'; /*test* /222*/ char buf[1024] = "abc /*test*/ 1234"; 36 | 37 | /* the result number string buffer to save the result */ 38 | char numstr[32][64]; 39 | 40 | 41 | ------------------------------------------- 42 | (0)0:0x23 43 | new state: 0 44 | #(0)0:0x69 45 | new state: 0 46 | i(0)0:0x6e 47 | new state: 0 48 | n(0)0:0x63 49 | new state: 0 50 | c(0)0:0x6c 51 | new state: 0 52 | l(0)0:0x75 53 | new state: 0 54 | u(0)0:0x64 55 | new state: 0 56 | d(0)0:0x65 57 | new state: 0 58 | e(0)0:0x20 59 | new state: 0 60 | (0)0:0x3c 61 | new state: 0 62 | <(0)0:0x73 63 | new state: 0 64 | s(0)0:0x74 65 | new state: 0 66 | t(0)0:0x64 67 | new state: 0 68 | d(0)0:0x69 69 | new state: 0 70 | i(0)0:0x6f 71 | new state: 0 72 | o(0)0:0x2e 73 | new state: 0 74 | .(0)0:0x68 75 | new state: 0 76 | h(0)0:0x3e 77 | new state: 0 78 | >(0)0:0xa 79 | new state: 0 80 | 81 | (0)2:0x2a 82 | new state: 2 83 | *(0)0:0xa 84 | new state: 0 85 | 86 | (0)1:0x2f 87 | new state: 1 88 | (1)2:0x2a 89 | new state: 2 90 | (2)0:0xa 91 | new state: 0 92 | (2)0:0x20 93 | new state: 0 94 | (2)2:0x2a 95 | new state: 2 96 | (3)0:0x20 97 | new state: 0 98 | (2)0:0x73 99 | new state: 0 100 | (2)0:0x74 101 | new state: 0 102 | (2)0:0x61 103 | new state: 0 104 | (2)0:0x74 105 | new state: 0 106 | (2)0:0x65 107 | new state: 0 108 | (2)0:0x2e 109 | new state: 0 110 | (2)0:0x63 111 | new state: 0 112 | (2)0:0x20 113 | new state: 0 114 | (2)0:0x2d 115 | new state: 0 116 | (2)0:0x20 117 | new state: 0 118 | (2)0:0x75 119 | new state: 0 120 | (2)0:0x73 121 | new state: 0 122 | (2)0:0x69 123 | new state: 0 124 | (2)0:0x6e 125 | new state: 0 126 | (2)0:0x67 127 | new state: 0 128 | (2)0:0x20 129 | new state: 0 130 | (2)0:0x46 131 | new state: 0 132 | (2)0:0x53 133 | new state: 0 134 | (2)0:0x4d 135 | new state: 0 136 | (2)0:0x20 137 | new state: 0 138 | (2)0:0x74 139 | new state: 0 140 | (2)0:0x6f 141 | new state: 0 142 | (2)0:0x20 143 | new state: 0 144 | (2)0:0x66 145 | new state: 0 146 | (2)0:0x69 147 | new state: 0 148 | (2)0:0x6e 149 | new state: 0 150 | (2)0:0x64 151 | new state: 0 152 | (2)0:0x20 153 | new state: 0 154 | (2)0:0x28 155 | new state: 0 156 | (2)0:0x2b 157 | new state: 0 158 | (2)1:0x2f 159 | new state: 1 160 | (2)0:0x2d 161 | new state: 0 162 | (2)0:0x29 163 | new state: 0 164 | (2)0:0x6e 165 | new state: 0 166 | (2)0:0x75 167 | new state: 0 168 | (2)0:0x6d 169 | new state: 0 170 | (2)0:0x62 171 | new state: 0 172 | (2)0:0x65 173 | new state: 0 174 | (2)0:0x72 175 | new state: 0 176 | (2)0:0x20 177 | new state: 0 178 | (2)0:0x73 179 | new state: 0 180 | (2)0:0x74 181 | new state: 0 182 | (2)0:0x72 183 | new state: 0 184 | (2)0:0x69 185 | new state: 0 186 | (2)0:0x6e 187 | new state: 0 188 | (2)0:0x67 189 | new state: 0 190 | (2)0:0x73 191 | new state: 0 192 | (2)0:0x20 193 | new state: 0 194 | (2)0:0x69 195 | new state: 0 196 | (2)0:0x6e 197 | new state: 0 198 | (2)0:0x20 199 | new state: 0 200 | (2)0:0x62 201 | new state: 0 202 | (2)0:0x75 203 | new state: 0 204 | (2)0:0x66 205 | new state: 0 206 | (2)0:0xa 207 | new state: 0 208 | (2)0:0x20 209 | new state: 0 210 | (2)2:0x2a 211 | new state: 2 212 | (3)0:0xa 213 | new state: 0 214 | (2)0:0x20 215 | new state: 0 216 | (2)2:0x2a 217 | new state: 2 218 | (3)0:0x20 219 | new state: 0 220 | (2)0:0x43 221 | new state: 0 222 | (2)0:0x6f 223 | new state: 0 224 | (2)0:0x70 225 | new state: 0 226 | (2)0:0x79 227 | new state: 0 228 | (2)0:0x72 229 | new state: 0 230 | (2)0:0x69 231 | new state: 0 232 | (2)0:0x67 233 | new state: 0 234 | (2)0:0x68 235 | new state: 0 236 | (2)0:0x74 237 | new state: 0 238 | (2)0:0x20 239 | new state: 0 240 | (2)0:0x28 241 | new state: 0 242 | (2)0:0x43 243 | new state: 0 244 | (2)0:0x29 245 | new state: 0 246 | (2)0:0x20 247 | new state: 0 248 | (2)0:0x32 249 | new state: 0 250 | (2)0:0x30 251 | new state: 0 252 | (2)0:0x31 253 | new state: 0 254 | (2)0:0x30 255 | new state: 0 256 | (2)0:0x9 257 | new state: 0 258 | (2)0:0x6c 259 | new state: 0 260 | (2)0:0x69 261 | new state: 0 262 | (2)0:0x20 263 | new state: 0 264 | (2)0:0x6d 265 | new state: 0 266 | (2)0:0x69 267 | new state: 0 268 | (2)0:0x6e 269 | new state: 0 270 | (2)0:0x67 271 | new state: 0 272 | (2)0:0x20 273 | new state: 0 274 | (2)0:0x3c 275 | new state: 0 276 | (2)0:0x6c 277 | new state: 0 278 | (2)0:0x69 279 | new state: 0 280 | (2)0:0x6d 281 | new state: 0 282 | (2)0:0x69 283 | new state: 0 284 | (2)0:0x6e 285 | new state: 0 286 | (2)0:0x67 287 | new state: 0 288 | (2)0:0x74 289 | new state: 0 290 | (2)0:0x68 291 | new state: 0 292 | (2)0:0x40 293 | new state: 0 294 | (2)0:0x61 295 | new state: 0 296 | (2)0:0x6b 297 | new state: 0 298 | (2)0:0x61 299 | new state: 0 300 | (2)0:0x65 301 | new state: 0 302 | (2)0:0x64 303 | new state: 0 304 | (2)0:0x75 305 | new state: 0 306 | (2)0:0x2e 307 | new state: 0 308 | (2)0:0x6f 309 | new state: 0 310 | (2)0:0x72 311 | new state: 0 312 | (2)0:0x67 313 | new state: 0 314 | (2)0:0x3e 315 | new state: 0 316 | (2)0:0xa 317 | new state: 0 318 | (2)0:0x20 319 | new state: 0 320 | (2)2:0x2a 321 | new state: 2 322 | (3)0:0xa 323 | new state: 0 324 | (2)0:0x20 325 | new state: 0 326 | (2)2:0x2a 327 | new state: 2 328 | (3)0:0x20 329 | new state: 0 330 | (2)0:0x66 331 | new state: 0 332 | (2)0:0x69 333 | new state: 0 334 | (2)0:0x6e 335 | new state: 0 336 | (2)0:0x64 337 | new state: 0 338 | (2)0:0x20 339 | new state: 0 340 | (2)0:0x6e 341 | new state: 0 342 | (2)0:0x75 343 | new state: 0 344 | (2)0:0x6d 345 | new state: 0 346 | (2)0:0x62 347 | new state: 0 348 | (2)0:0x65 349 | new state: 0 350 | (2)0:0x72 351 | new state: 0 352 | (2)0:0x20 353 | new state: 0 354 | (2)0:0x73 355 | new state: 0 356 | (2)0:0x74 357 | new state: 0 358 | (2)0:0x72 359 | new state: 0 360 | (2)0:0x69 361 | new state: 0 362 | (2)0:0x6e 363 | new state: 0 364 | (2)0:0x67 365 | new state: 0 366 | (2)0:0x20 367 | new state: 0 368 | (2)0:0x73 369 | new state: 0 370 | (2)0:0x75 371 | new state: 0 372 | (2)0:0x63 373 | new state: 0 374 | (2)0:0x68 375 | new state: 0 376 | (2)0:0x20 377 | new state: 0 378 | (2)0:0x61 379 | new state: 0 380 | (2)0:0x73 381 | new state: 0 382 | (2)0:0x20 383 | new state: 0 384 | (2)0:0x31 385 | new state: 0 386 | (2)0:0x32 387 | new state: 0 388 | (2)0:0x33 389 | new state: 0 390 | (2)0:0x2c 391 | new state: 0 392 | (2)0:0x20 393 | new state: 0 394 | (2)0:0x2b 395 | new state: 0 396 | (2)0:0x31 397 | new state: 0 398 | (2)0:0x2c 399 | new state: 0 400 | (2)0:0x20 401 | new state: 0 402 | (2)0:0x2d 403 | new state: 0 404 | (2)0:0x30 405 | new state: 0 406 | (2)0:0x33 407 | new state: 0 408 | (2)0:0x37 409 | new state: 0 410 | (2)0:0x30 411 | new state: 0 412 | (2)0:0x38 413 | new state: 0 414 | (2)0:0x20 415 | new state: 0 416 | (2)0:0x69 417 | new state: 0 418 | (2)0:0x6e 419 | new state: 0 420 | (2)0:0x20 421 | new state: 0 422 | (2)4:0x22 423 | new state: 4 424 | (2)0:0x61 425 | new state: 0 426 | (2)0:0x62 427 | new state: 0 428 | (2)0:0x31 429 | new state: 0 430 | (2)0:0x32 431 | new state: 0 432 | (2)0:0x33 433 | new state: 0 434 | (2)0:0x2b 435 | new state: 0 436 | (2)0:0x31 437 | new state: 0 438 | (2)0:0x2d 439 | new state: 0 440 | (2)0:0x2d 441 | new state: 0 442 | (2)0:0x30 443 | new state: 0 444 | (2)0:0x33 445 | new state: 0 446 | (2)0:0x37 447 | new state: 0 448 | (2)0:0x30 449 | new state: 0 450 | (2)0:0x38 451 | new state: 0 452 | (2)4:0x22 453 | new state: 4 454 | (2)0:0xa 455 | new state: 0 456 | (2)0:0x20 457 | new state: 0 458 | (2)2:0x2a 459 | new state: 2 460 | (3)0:0xa 461 | new state: 0 462 | (2)0:0x20 463 | new state: 0 464 | (2)2:0x2a 465 | new state: 2 466 | (3)1:0x2f 467 | new state: 1 468 | (0)2:0x2a 469 | new state: 2 470 | *(0)0:0x38 471 | new state: 0 472 | 8(0)2:0x2a 473 | new state: 2 474 | *(0)0:0xa 475 | new state: 0 476 | 477 | (0)0:0xa 478 | new state: 0 479 | 480 | (0)2:0x2a 481 | new state: 2 482 | *(0)0:0xa 483 | new state: 0 484 | 485 | (0)1:0x2f 486 | new state: 1 487 | (1)2:0x2a 488 | new state: 2 489 | (2)0:0x20 490 | new state: 0 491 | (2)0:0x74 492 | new state: 0 493 | (2)0:0x68 494 | new state: 0 495 | (2)0:0x65 496 | new state: 0 497 | (2)0:0x20 498 | new state: 0 499 | (2)0:0x73 500 | new state: 0 501 | (2)0:0x74 502 | new state: 0 503 | (2)0:0x72 504 | new state: 0 505 | (2)0:0x69 506 | new state: 0 507 | (2)0:0x6e 508 | new state: 0 509 | (2)0:0x67 510 | new state: 0 511 | (2)0:0x20 512 | new state: 0 513 | (2)0:0x62 514 | new state: 0 515 | (2)0:0x75 516 | new state: 0 517 | (2)0:0x66 518 | new state: 0 519 | (2)0:0x66 520 | new state: 0 521 | (2)0:0x65 522 | new state: 0 523 | (2)0:0x72 524 | new state: 0 525 | (2)0:0x20 526 | new state: 0 527 | (2)0:0x74 528 | new state: 0 529 | (2)0:0x6f 530 | new state: 0 531 | (2)0:0x20 532 | new state: 0 533 | (2)0:0x64 534 | new state: 0 535 | (2)0:0x65 536 | new state: 0 537 | (2)0:0x61 538 | new state: 0 539 | (2)0:0x6c 540 | new state: 0 541 | (2)0:0x20 542 | new state: 0 543 | (2)0:0x77 544 | new state: 0 545 | (2)0:0x69 546 | new state: 0 547 | (2)0:0x74 548 | new state: 0 549 | (2)0:0x68 550 | new state: 0 551 | (2)0:0x20 552 | new state: 0 553 | (2)2:0x2a 554 | new state: 2 555 | (3)1:0x2f 556 | new state: 1 557 | (0)0:0xa 558 | new state: 0 559 | 560 | (0)0:0x63 561 | new state: 0 562 | c(0)0:0x68 563 | new state: 0 564 | h(0)0:0x61 565 | new state: 0 566 | a(0)0:0x72 567 | new state: 0 568 | r(0)0:0x20 569 | new state: 0 570 | (0)0:0x63 571 | new state: 0 572 | c(0)0:0x68 573 | new state: 0 574 | h(0)0:0x20 575 | new state: 0 576 | (0)0:0x3d 577 | new state: 0 578 | =(0)0:0x20 579 | new state: 0 580 | (0)3:0x27 581 | new state: 3 582 | '(4)0:0x5c 583 | new state: 0 584 | \(4)4:0x22 585 | new state: 4 586 | "(4)3:0x27 587 | new state: 3 588 | '(0)0:0x3b 589 | new state: 0 590 | ;(0)0:0x20 591 | new state: 0 592 | (0)1:0x2f 593 | new state: 1 594 | (1)2:0x2a 595 | new state: 2 596 | (2)0:0x74 597 | new state: 0 598 | (2)0:0x65 599 | new state: 0 600 | (2)0:0x73 601 | new state: 0 602 | (2)0:0x74 603 | new state: 0 604 | (2)2:0x2a 605 | new state: 2 606 | (3)0:0x20 607 | new state: 0 608 | (2)1:0x2f 609 | new state: 1 610 | (2)0:0x32 611 | new state: 0 612 | (2)0:0x32 613 | new state: 0 614 | (2)0:0x32 615 | new state: 0 616 | (2)2:0x2a 617 | new state: 2 618 | (3)1:0x2f 619 | new state: 1 620 | (0)0:0x20 621 | new state: 0 622 | (0)0:0x20 623 | new state: 0 624 | (0)0:0x63 625 | new state: 0 626 | c(0)0:0x68 627 | new state: 0 628 | h(0)0:0x61 629 | new state: 0 630 | a(0)0:0x72 631 | new state: 0 632 | r(0)0:0x20 633 | new state: 0 634 | (0)0:0x62 635 | new state: 0 636 | b(0)0:0x75 637 | new state: 0 638 | u(0)0:0x66 639 | new state: 0 640 | f(0)0:0x5b 641 | new state: 0 642 | [(0)0:0x31 643 | new state: 0 644 | 1(0)0:0x30 645 | new state: 0 646 | 0(0)0:0x32 647 | new state: 0 648 | 2(0)0:0x34 649 | new state: 0 650 | 4(0)0:0x5d 651 | new state: 0 652 | ](0)0:0x20 653 | new state: 0 654 | (0)0:0x3d 655 | new state: 0 656 | =(0)0:0x20 657 | new state: 0 658 | (0)4:0x22 659 | new state: 4 660 | "(5)0:0x61 661 | new state: 0 662 | a(5)0:0x62 663 | new state: 0 664 | b(5)0:0x63 665 | new state: 0 666 | c(5)0:0x20 667 | new state: 0 668 | (5)1:0x2f 669 | new state: 1 670 | /(5)2:0x2a 671 | new state: 2 672 | *(5)0:0x74 673 | new state: 0 674 | t(5)0:0x65 675 | new state: 0 676 | e(5)0:0x73 677 | new state: 0 678 | s(5)0:0x74 679 | new state: 0 680 | t(5)2:0x2a 681 | new state: 2 682 | *(5)1:0x2f 683 | new state: 1 684 | /(5)0:0x20 685 | new state: 0 686 | (5)0:0x31 687 | new state: 0 688 | 1(5)0:0x32 689 | new state: 0 690 | 2(5)0:0x33 691 | new state: 0 692 | 3(5)0:0x34 693 | new state: 0 694 | 4(5)4:0x22 695 | new state: 4 696 | "(0)0:0x3b 697 | new state: 0 698 | ;(0)0:0xa 699 | new state: 0 700 | 701 | (0)0:0xa 702 | new state: 0 703 | 704 | (0)1:0x2f 705 | new state: 1 706 | (1)2:0x2a 707 | new state: 2 708 | (2)0:0x20 709 | new state: 0 710 | (2)0:0x74 711 | new state: 0 712 | (2)0:0x68 713 | new state: 0 714 | (2)0:0x65 715 | new state: 0 716 | (2)0:0x20 717 | new state: 0 718 | (2)0:0x72 719 | new state: 0 720 | (2)0:0x65 721 | new state: 0 722 | (2)0:0x73 723 | new state: 0 724 | (2)0:0x75 725 | new state: 0 726 | (2)0:0x6c 727 | new state: 0 728 | (2)0:0x74 729 | new state: 0 730 | (2)0:0x20 731 | new state: 0 732 | (2)0:0x6e 733 | new state: 0 734 | (2)0:0x75 735 | new state: 0 736 | (2)0:0x6d 737 | new state: 0 738 | (2)0:0x62 739 | new state: 0 740 | (2)0:0x65 741 | new state: 0 742 | (2)0:0x72 743 | new state: 0 744 | (2)0:0x20 745 | new state: 0 746 | (2)0:0x73 747 | new state: 0 748 | (2)0:0x74 749 | new state: 0 750 | (2)0:0x72 751 | new state: 0 752 | (2)0:0x69 753 | new state: 0 754 | (2)0:0x6e 755 | new state: 0 756 | (2)0:0x67 757 | new state: 0 758 | (2)0:0x20 759 | new state: 0 760 | (2)0:0x62 761 | new state: 0 762 | (2)0:0x75 763 | new state: 0 764 | (2)0:0x66 765 | new state: 0 766 | (2)0:0x66 767 | new state: 0 768 | (2)0:0x65 769 | new state: 0 770 | (2)0:0x72 771 | new state: 0 772 | (2)0:0x20 773 | new state: 0 774 | (2)0:0x74 775 | new state: 0 776 | (2)0:0x6f 777 | new state: 0 778 | (2)0:0x20 779 | new state: 0 780 | (2)0:0x73 781 | new state: 0 782 | (2)0:0x61 783 | new state: 0 784 | (2)0:0x76 785 | new state: 0 786 | (2)0:0x65 787 | new state: 0 788 | (2)0:0x20 789 | new state: 0 790 | (2)0:0x74 791 | new state: 0 792 | (2)0:0x68 793 | new state: 0 794 | (2)0:0x65 795 | new state: 0 796 | (2)0:0x20 797 | new state: 0 798 | (2)0:0x72 799 | new state: 0 800 | (2)0:0x65 801 | new state: 0 802 | (2)0:0x73 803 | new state: 0 804 | (2)0:0x75 805 | new state: 0 806 | (2)0:0x6c 807 | new state: 0 808 | (2)0:0x74 809 | new state: 0 810 | (2)0:0x20 811 | new state: 0 812 | (2)2:0x2a 813 | new state: 2 814 | (3)1:0x2f 815 | new state: 1 816 | (0)0:0xa 817 | new state: 0 818 | 819 | (0)0:0x63 820 | new state: 0 821 | c(0)0:0x68 822 | new state: 0 823 | h(0)0:0x61 824 | new state: 0 825 | a(0)0:0x72 826 | new state: 0 827 | r(0)0:0x20 828 | new state: 0 829 | (0)0:0x6e 830 | new state: 0 831 | n(0)0:0x75 832 | new state: 0 833 | u(0)0:0x6d 834 | new state: 0 835 | m(0)0:0x73 836 | new state: 0 837 | s(0)0:0x74 838 | new state: 0 839 | t(0)0:0x72 840 | new state: 0 841 | r(0)0:0x5b 842 | new state: 0 843 | [(0)0:0x33 844 | new state: 0 845 | 3(0)0:0x32 846 | new state: 0 847 | 2(0)0:0x5d 848 | new state: 0 849 | ](0)0:0x5b 850 | new state: 0 851 | [(0)0:0x36 852 | new state: 0 853 | 6(0)0:0x34 854 | new state: 0 855 | 4(0)0:0x5d 856 | new state: 0 857 | ](0)0:0x3b 858 | new state: 0 859 | ;(0)0:0xa 860 | new state: 0 861 | 862 | (0)0:0xa 863 | new state: 0 864 | 865 | (0)5:0x0 866 | new state: 5 867 | 868 | -------------------------------------------------------------------------------- /Unit-3/Lesson-49/readfile.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | /* Test switch */ 9 | #define TEST 0 10 | 11 | #define READ_LINE 4096 12 | 13 | /* 14 | * read the file to buf 15 | * 16 | * Return value: file's length 17 | * 18 | */ 19 | int read_file(const char *filename, char buf[]) 20 | { 21 | /* open the file */ 22 | int fd = open(filename, O_RDONLY); 23 | if(fd < 0){ 24 | fprintf(stderr,"Open %s:%s\n",filename, strerror(errno)); 25 | exit(1); 26 | } 27 | fprintf(stdout, "Open %s Successed!\n", filename); 28 | 29 | /* read file to buf */ 30 | int len = 0, n; 31 | while((n = read(fd, &buf[len], READ_LINE)) > 0) 32 | len += n; 33 | buf[len] ='\0'; 34 | 35 | /* close file */ 36 | close(fd); 37 | 38 | return len; 39 | } 40 | 41 | 42 | /* Test */ 43 | 44 | #if TEST 45 | 46 | #define BUF_MAX 1024 47 | /* main function */ 48 | int main(int argc, char *argv[]) 49 | { 50 | char buf[BUF_MAX]; 51 | 52 | if(argc < 2){ 53 | fprintf(stderr, "Usage: %s \n", argv[0]); 54 | exit(1); 55 | } 56 | 57 | int n = read_file(argv[1], buf); 58 | printf("%s\n", buf); 59 | printf("%d\n", n); 60 | 61 | return 0; 62 | } 63 | #endif 64 | -------------------------------------------------------------------------------- /Unit-3/Lesson-49/readfile.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/Unit-3/Lesson-49/readfile.o -------------------------------------------------------------------------------- /Unit-3/Lesson-49/state.c: -------------------------------------------------------------------------------- 1 | /* 2 | * state.c - using FSM to delete comment in a C source file 3 | * 4 | * Copyright (C) 2010 li ming 5 | * 6 | * delete comment in C code of single line and multiple lines 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #ifdef DEBUG 17 | #define DPRINT printf 18 | #else 19 | #define DPRINT // 20 | #endif 21 | 22 | /* enough memory size for a whole C file < 100K */ 23 | char buf[102400]; 24 | /* record how many number string found */ 25 | int counter = 0; 26 | 27 | int i = 0; 28 | int pos = 0; 29 | 30 | char *begin, *end; 31 | 32 | void act_null(void) 33 | { 34 | } 35 | 36 | void act_print(void) 37 | { 38 | printf("%c", buf[i]); 39 | } 40 | 41 | void act_print2(void) 42 | { 43 | printf("%c", *begin); 44 | act_print(); 45 | } 46 | 47 | void act_mark(void) 48 | { 49 | begin = buf + i; 50 | } 51 | 52 | void act_print_mark(void) 53 | { 54 | printf("%c", *begin); 55 | act_mark(); 56 | } 57 | 58 | void act_print_space(void) 59 | { 60 | end = buf + i; 61 | 62 | while (begin != end) 63 | { 64 | if (*begin != '\n') 65 | printf(" "); 66 | else 67 | printf("\n"); 68 | 69 | begin++; 70 | } 71 | } 72 | 73 | void act_end(void) 74 | { 75 | printf("\n"); 76 | } 77 | 78 | /* 79 | * get_input_type - get the input char TYPE ID 80 | * 81 | * 0: [a-z] 82 | * 1: [/] 83 | * 2: [*] 84 | * 3: ['] 85 | * 4: ["] 86 | * 5: '\0' - string end 87 | * 88 | */ 89 | int get_input_type( char ch ) 90 | { 91 | if (ch == '/') 92 | return 1; 93 | else if (ch == '*') 94 | return 2; 95 | else if (ch == '\'') 96 | return 3; 97 | else if (ch == '\"') 98 | return 4; 99 | else if (ch == '\0') 100 | return 5; 101 | 102 | return 0; 103 | } 104 | 105 | /* input TYPE ID which is return from get_input_type */ 106 | int input; 107 | 108 | 109 | /* 110 | * FSM state 111 | * 112 | * 0: (a) start state or restart state without digit 113 | * 1: (/) get / 114 | * 2: (/ *) get / and * 115 | * 3: (/ * *) get / and * and * 116 | * 4: (') get ' 117 | * 5: (") get " 118 | * 6: (' ') get ' and ' 119 | * -1: end state 120 | * 121 | */ 122 | int state; 123 | 124 | /* state transition table */ 125 | int state_table[7][6] = 126 | {// a / * ' " \0 127 | 0, 1, 0, 4, 5, -1, 128 | 0, 1, 2, 4, 5, -1, 129 | 2, 2, 3, 2, 2, -1, 130 | 2, 0, 3, 2, 2, -1, 131 | 4, 4, 4, 6, 4, -1, 132 | 5, 5, 5, 5, 0, -1, 133 | 0, 1, 0, 0, 0, -1, 134 | }; 135 | 136 | void (*action[7][6]) (void) = 137 | { 138 | act_print, act_mark, act_print, act_print, act_print, act_end, 139 | act_print2, act_print_mark, act_null, act_print2, act_print2, act_end, 140 | act_null, act_null, act_null, act_null, act_null, act_end, 141 | act_null, act_print_space,act_null, act_null, act_null, act_end, 142 | act_print, act_print, act_print, act_print, act_print, act_end, 143 | act_print, act_print, act_print, act_print, act_print, act_end, 144 | act_print, act_mark, act_print, act_print, act_print, act_end, 145 | }; 146 | 147 | int main(int argc, char *argv[]) 148 | { 149 | int new_state; 150 | // printf( "please input a string : " ); 151 | // scanf( "%s", buf ); 152 | 153 | if(argc < 2){ 154 | fprintf(stderr, "Usage: %s \n", argv[0]); 155 | exit(1); 156 | } 157 | 158 | int n = read_file(argv[1], buf); 159 | printf("%s\n", buf); 160 | printf("%d bytes read from %s \n", n, argv[1]); 161 | 162 | DPRINT( "your input string is: %s \n", buf ); 163 | printf("-------------------------------------------\n"); 164 | 165 | i = 0; 166 | state = 0; 167 | while( state != -1 ) 168 | { 169 | input = get_input_type( buf[i] ); 170 | DPRINT( "(%d)%d:0x%x \n", state, input, buf[i] ); 171 | 172 | /* get new state from state transition table */ 173 | new_state = state_table[state][input]; 174 | DPRINT( "new state: %d \n", input ); 175 | //getchar(); 176 | 177 | /* call act to do something */ 178 | action[state][input](); 179 | 180 | state = new_state; 181 | 182 | i++; 183 | } 184 | 185 | return 0; 186 | } 187 | -------------------------------------------------------------------------------- /Unit-3/Lesson-49/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | /* 3 | * state.c - using FSM to find (+/-)number strings in buf 4 | * 5 | * Copyright (C) 2010 li ming 6 | * 7 | *//*8123*/// 8 | 9 | /* the string buffer to deal with */ 10 | char ch = '\''/*test* /00000*/; char buf[1024] = "abc /*test*/ 1234"; 11 | 12 | /* the result number string buffer to save the result */ 13 | char cc = '\"'/*abc*/; /*test* /222*/ 14 | 15 | -------------------------------------------------------------------------------- /Unit-3/README.md: -------------------------------------------------------------------------------- 1 | NCCL - New Concept C Language 2 | ============================= 3 | 4 | please use to run/test these C programs! 5 | 6 | # Unit Three 7 | ## Lesson 49 [Delete the comments in the C program](Unit-3/Lesson-49.md) C程序去注释问题 8 | ## Lesson 50 9 | ## Lesson 51 10 | ## Lesson 52 11 | ## Lesson 53 12 | ## Lesson 54 13 | ## Lesson 55 14 | ## Lesson 56 15 | ## Lesson 57 16 | ## Lesson 58 17 | ## Lesson 59 18 | ## Lesson 60 19 | ## Lesson 61 20 | ## Lesson 62 21 | ## Lesson 63 22 | ## Lesson 64 23 | ## Lesson 65 24 | ## Lesson 66 25 | ## Lesson 67 26 | ## Lesson 68 27 | ## Lesson 69 28 | ## Lesson 70 29 | ## Lesson 71 30 | ## Lesson 72 -------------------------------------------------------------------------------- /Unit-3/parser-tree.md: -------------------------------------------------------------------------------- 1 | 2 | ## Lesson 37 - Parse Tree 语法分析树 3 | 4 | ### 课程任务 5 | * 根据下面简化的BNF范式,实现对 Lesson 1 中最简单的 C 程序的语法分析,并生成一棵分析树(Parse Tree)。 6 | 7 | ### 最简单的 C 程序 8 | 9 | int main(void) 10 | { 11 | return 0; 12 | } 13 | 14 | 15 | ### 对应的简化版 BNF 范式 16 | 17 | program : function_definition 18 | 19 | function_definition : decl_specs declarator compound_stat 20 | 21 | decl_specs : type_spec 22 | 23 | type_spec : 'void' | 'int' 24 | 25 | declarator : id '(' type_spec ')' 26 | 27 | compound_stat : '{' stat '}' 28 | 29 | stat : 'return' number ';' 30 | 31 | ### 参考资料 32 | * http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm 33 | * http://academic.udayton.edu/saverioperugini/courses/cps343/lecture_notes/grammars.html 34 | 35 | -------------------------------------------------------------------------------- /Unit-4/README.md: -------------------------------------------------------------------------------- 1 | NCCL - New Concept C Language 2 | ============================= 3 | 4 | please use to run/test these C programs! 5 | 6 | # Unit Four 7 | ## Lesson 73 8 | ## Lesson 74 9 | ## Lesson 75 10 | ## Lesson 76 11 | ## Lesson 77 12 | ## Lesson 78 13 | ## Lesson 79 14 | ## Lesson 80 15 | ## Lesson 81 16 | ## Lesson 82 17 | ## Lesson 83 18 | ## Lesson 84 19 | ## Lesson 85 20 | ## Lesson 86 21 | ## Lesson 87 22 | ## Lesson 88 23 | ## Lesson 89 24 | ## Lesson 90 25 | ## Lesson 91 26 | ## Lesson 92 27 | ## Lesson 93 28 | ## Lesson 94 29 | ## Lesson 95 30 | ## Lesson 96 31 | 32 | -------------------------------------------------------------------------------- /enrollment.md: -------------------------------------------------------------------------------- 1 | ## 关于在线授课 2 | 3 | ### 学习内容 4 | * 《新概念C语言》[Unit 1](https://github.com/limingth/NCCL/blob/master/Unit-1/README.md) 和 [Unit 2](https://github.com/limingth/NCCL/blob/master/Unit-2/README.md) 5 | 6 | ### 学习时间 7 | * 3个月,其中 Unit 1 (1个月),Unit 2(2个月) 8 | * 每天至少确保晚上投入2-3个小时,周末投入4-6个小时 9 | 10 | ### 学习方式 11 | * Unit 1:视频教程42集,随时可以预约在线答疑 12 | * Unit 2:一对一授课,每周2次,1次理论,1次答疑 13 | * 全部授课在线进行,采用 Skype/QQ + 桌面共享方式 14 | 15 | ### 学习费用 16 | * 包月2000元,先付款后学习,不满意随时退全款 17 | * 可以免费体验一节课(1小时) 18 | 19 | ### 学习保障 20 | * 3个月后学不会,不再额外收费,学会为止 21 | 22 | ### 就业保障 23 | * Linux C 软件开发工程师,参考薪资 3000-6000元 24 | -------------------------------------------------------------------------------- /images/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/images/.DS_Store -------------------------------------------------------------------------------- /images/china-cities.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/images/china-cities.png -------------------------------------------------------------------------------- /images/dj-algorithm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/images/dj-algorithm.png -------------------------------------------------------------------------------- /images/heap-0-max-heapify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/images/heap-0-max-heapify.png -------------------------------------------------------------------------------- /images/heap-1-build-max.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/images/heap-1-build-max.png -------------------------------------------------------------------------------- /images/heap-2-swap-max-to-last.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/images/heap-2-swap-max-to-last.png -------------------------------------------------------------------------------- /images/heap-3-swap-max-to-next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/images/heap-3-swap-max-to-next.png -------------------------------------------------------------------------------- /images/heap-4-swap-to-first.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/images/heap-4-swap-to-first.png -------------------------------------------------------------------------------- /images/heap-array.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/images/heap-array.png -------------------------------------------------------------------------------- /images/heap-max-heapify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/images/heap-max-heapify.png -------------------------------------------------------------------------------- /images/heap-random.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/images/heap-random.png -------------------------------------------------------------------------------- /images/huffman-freq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/images/huffman-freq.png -------------------------------------------------------------------------------- /images/huffman-tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/images/huffman-tree.png -------------------------------------------------------------------------------- /images/nitrous.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/images/nitrous.jpg -------------------------------------------------------------------------------- /images/vector-graph.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/images/vector-graph.jpg -------------------------------------------------------------------------------- /slides/.gitignore: -------------------------------------------------------------------------------- 1 | main.* 2 | talk.tex 3 | !main.tex 4 | -------------------------------------------------------------------------------- /slides/Lesson-1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/slides/Lesson-1.pdf -------------------------------------------------------------------------------- /slides/Lesson-10.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/slides/Lesson-10.pdf -------------------------------------------------------------------------------- /slides/Lesson-11.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/slides/Lesson-11.pdf -------------------------------------------------------------------------------- /slides/Lesson-12.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/slides/Lesson-12.pdf -------------------------------------------------------------------------------- /slides/Lesson-13.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/slides/Lesson-13.pdf -------------------------------------------------------------------------------- /slides/Lesson-14.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/slides/Lesson-14.pdf -------------------------------------------------------------------------------- /slides/Lesson-2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/slides/Lesson-2.pdf -------------------------------------------------------------------------------- /slides/Lesson-3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/slides/Lesson-3.pdf -------------------------------------------------------------------------------- /slides/Lesson-4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/slides/Lesson-4.pdf -------------------------------------------------------------------------------- /slides/Lesson-5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/slides/Lesson-5.pdf -------------------------------------------------------------------------------- /slides/Lesson-6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/slides/Lesson-6.pdf -------------------------------------------------------------------------------- /slides/Lesson-7.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/slides/Lesson-7.pdf -------------------------------------------------------------------------------- /slides/Lesson-8.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/slides/Lesson-8.pdf -------------------------------------------------------------------------------- /slides/Lesson-9.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limingth/NCCL/2fae5f0ae70176922aa8772a421bfc1aff6aee59/slides/Lesson-9.pdf -------------------------------------------------------------------------------- /slides/Makefile: -------------------------------------------------------------------------------- 1 | # example 2 | # $ make Lesson-1 3 | # $ make Lesson-2 4 | 5 | %: 6 | make md 7 | -rm outline.tex talk.tex 8 | echo building $@ outline md files from README.md 9 | pandoc -t beamer --slide-level 2 $@-outline.md -o outline.tex 10 | grep -r "###" ../Unit-1/$@.md -A 100 > $@-talk.md 11 | pandoc -t beamer --slide-level 3 $@-talk.md -o talk.tex 12 | sleep 1 13 | xelatex main.tex 14 | mv main.pdf $@.pdf 15 | gnome-open $@.pdf 16 | 17 | md: 18 | grep -r Lesson-1.md ../Unit-1/README.md -A 13 > Lesson-1-outline.md 19 | grep -r Lesson-2.md ../Unit-1/README.md -A 16 > Lesson-2-outline.md 20 | grep -r Lesson-3.md ../Unit-1/README.md -A 9 > Lesson-3-outline.md 21 | grep -r Lesson-4.md ../Unit-1/README.md -A 8 > Lesson-4-outline.md 22 | grep -r Lesson-5.md ../Unit-1/README.md -A 12 > Lesson-5-outline.md 23 | grep -r Lesson-6.md ../Unit-1/README.md -A 8 > Lesson-6-outline.md 24 | grep -r Lesson-7.md ../Unit-1/README.md -A 9 > Lesson-7-outline.md 25 | grep -r Lesson-8.md ../Unit-1/README.md -A 9 > Lesson-8-outline.md 26 | grep -r Lesson-9.md ../Unit-1/README.md -A 6 > Lesson-9-outline.md 27 | grep -r Lesson-10.md ../Unit-1/README.md -A 9 > Lesson-10-outline.md 28 | grep -r Lesson-11.md ../Unit-1/README.md -A 11 > Lesson-11-outline.md 29 | grep -r Lesson-12.md ../Unit-1/README.md -A 8 > Lesson-12-outline.md 30 | grep -r Lesson-13.md ../Unit-1/README.md -A 10 > Lesson-13-outline.md 31 | 32 | clean: 33 | rm *.out *.log *.nav *.toc *.vrb *.aux *.snm 34 | rm Lesson*.md 35 | -------------------------------------------------------------------------------- /slides/README.md: -------------------------------------------------------------------------------- 1 | # Makefile # 2 | Now make will do everything, no need of md2pdf.sh 3 | make Lesson-1 4 | make Lesson-2 5 | 6 | 7 | # md2pdf.sh # 8 | use shell scripts `md2pdf.sh` to generate Lesson-x.pdf automatically 9 | 10 | ./md2pdf.sh Lesson-1 11 | 12 | then Lesson-1.pdf will be under slides/ 13 | 14 | # Introduction # 15 | Very good introduction started from here 16 | http://jeromyanglim.blogspot.com/2012/07/beamer-pandoc-markdown.html 17 | 18 | pandoc -t beamer --slide-level 3 Lesson-1.md -o talk.tex 19 | xelatex main.tex 20 | 21 | `main.tex` will include talk.tex automatically, main.tex defines the theme 22 | 23 | `slide-level 3` means `###` 24 | 25 | ## Reference # 26 | * http://www.casparant.com/posts/know-how-to-make-a-latex-beamer-template.html 27 | * http://www.hartwork.org/beamer-theme-matrix/ 28 | * http://en.wikibooks.org/wiki/LaTeX/Presentations#The_Built-in_solution 29 | -------------------------------------------------------------------------------- /slides/main.tex: -------------------------------------------------------------------------------- 1 | \documentclass[10pt]{beamer} 2 | \usetheme{Berlin} 3 | \usecolortheme{beaver} 4 | \setbeamertemplate{navigation symbols}{} 5 | \title{新概念C语言} 6 | \subtitle{NCCL - New Concept C Language} 7 | \author{@亚嵌李明老师} 8 | \date{技术交流QQ群: 275488078} 9 | \institute{www.akaedu.org} 10 | \usepackage{fontspec} 11 | \usefonttheme{serif} 12 | \setmainfont[Mapping=tex-text]{WenQuanYi Zen Hei Mono} 13 | \setromanfont[Mapping=tex-text,BoldFont=WenQuanYi Micro Hei]{AR PL SungtiL GB} 14 | \setmonofont[Mapping=tex-text]{WenQuanYi Zen Hei Mono} 15 | 16 | % enables straight single quote 17 | \makeatletter 18 | \let \@sverbatim \@verbatim 19 | \def \@verbatim {\@sverbatim \verbatimplus} 20 | {\catcode`'=13 \gdef \verbatimplus{\catcode`'=13 \chardef '=13 }} 21 | \makeatother 22 | 23 | % enables backticks in verbatim 24 | \makeatletter 25 | {\catcode`\`=13 26 | \xdef\@verbatim{\unexpanded\expandafter{\@verbatim}\chardef\noexpand`=18 } 27 | } 28 | \makeatother 29 | 30 | 31 | \begin{document} 32 | 33 | \begin{frame} 34 | \titlepage 35 | \begin{itemize} 36 | \item 课程资料 \url{https://github.com/limingth/NCCL/} 37 | \end{itemize} 38 | \end{frame} 39 | 40 | \input{"outline.tex"} 41 | 42 | \input{"talk.tex"} 43 | 44 | \begin{frame}\frametitle{Q\&A} 45 | \begin{itemize} 46 | \item 47 | 课程相关信息 48 | \begin{itemize} 49 | \item 50 | 课程技术交流QQ群: 275488078 51 | \item 52 | 课程多贝主页: \url{http://www.duobei.com/7402180380} 53 | \item 54 | 课程论坛主页: \href{http://www.linkedin.com/groups/Welcome-NCCL-group-4715078.S.185251633?qid=dce08638-0f74-4014-b9ad-ecab2ec33c5c&trk=group_most_popular-0-b-ttl&goback=.gsm_4715078_1_*2_*2_*2_lna_PENDING_*2.gmp_4715078.gde_4715078_member_185251633.gmp_4715078.gde_4715078_member_188465347.gmp_4715078} LinkedIn.com 的 NCCL 讨论群组 55 | \end{itemize} 56 | \item 57 | 如何搭建环境: 58 | \url{https://github.com/limingth/NCCL/blob/gh-pages/INSTALL.md} 59 | \item 60 | 在线网页编程: \url{http://ideone.com} 61 | \end{itemize} 62 | \end{frame} 63 | 64 | \end{document} 65 | -------------------------------------------------------------------------------- /slides/md2pdf.sh: -------------------------------------------------------------------------------- 1 | set -x 2 | echo $1 3 | make $1 4 | pandoc -t beamer --slide-level 3 ../Unit-1/$1.md -o talk.tex 5 | xelatex main.tex 6 | cp main.pdf $1.pdf 7 | rm main.pdf 8 | rm *.out *.log *.nav *.toc *.vrb *.aux *.snm 9 | -------------------------------------------------------------------------------- /slides/outline.tex: -------------------------------------------------------------------------------- 1 | \begin{frame}\frametitle{Lesson 7 \href{Lesson-7.md}{Find the max prime 2 | number within 100} 求100以内的最大素数} 3 | 4 | \begin{itemize} 5 | \item 6 | 循环中的条件分支 7 | \begin{itemize} 8 | \item 9 | break 和 goto 用法\\ 10 | \end{itemize} 11 | \item 12 | 数学库函数 math library 13 | \begin{itemize} 14 | \item 15 | 静态链接和动态链接 static \& dynamic linkage 16 | \end{itemize} 17 | \item 18 | 算法效率 19 | \begin{itemize} 20 | \item 21 | 算法的时间复杂度分析 O(n) 22 | \end{itemize} 23 | \item 24 | 结构程序设计 25 | \begin{itemize} 26 | \item 27 | 三种基本控制结构就可以写各种程序 28 | \end{itemize} 29 | \end{itemize} 30 | \end{frame} 31 | --------------------------------------------------------------------------------