Windows 内核编程并没有提供像 Ring3 层的 CopyFile 这样的 API,看了看书中的例子自己写了一份 MyCopyFile,以后用来备用。
boost 智能指针 shared_ptr
boost 库中不单单这一种智能指针类型。但只有 shared_ptr 是最接近普通指针的一种智能指针,他具有一些非常良好的特性,比如计数器等等,使用 shared_ptr 可以让我们不用花费精力在内存回收上。其他的一些指针与 shared_ptr 的区别如下表:
栈应用代码检测就近匹配
你在使用编辑器写代码的时候是否思考过这个问题:如果少写了一个大括号或中括号,编辑器就会提示错误,这种做法是怎么做到的呢?
其实这个检测就可以通过栈模型来实现,括号的数量总是匹配出现的,并且都是与最近的一个匹配。我们可以编写代码来实现这个检测的功能。具体实现思路如下:
从第一个字符开始扫描, 当遇见普通字符时忽略, 当遇见左符号时压入栈中 当遇见右符号时从栈中弹出栈顶符号,并进行匹配. 匹配成功:继续读入下一个字符 匹配失败:立即停止,并报错 结束. ------成功: 所有字符扫描完毕,且栈为空 ------失败:匹配失败或所有字符扫描完毕但栈非空
【实现代码】
以下代码需要用到栈模型链式存储的 LinkStack.h 和 LinkStack.c 头文件:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "LinkStack.h" /***************** 算法思路 ***************** 从第一个字符开始扫描, 当遇见普通字符时忽略, 当遇见左符号时压入栈中 当遇见右符号时从栈中弹出栈顶符号,并进行匹配. 匹配成功:继续读入下一个字符 匹配失败:立即停止,并报错 结束. ------成功: 所有字符扫描完毕,且栈为空 ------失败:匹配失败或所有字符扫描完毕但栈非空*/ int match(char left, char right) { int ret = 0; switch (left) { case '<': //左尖括号 ret = (right == '>'); break; case '(': //左小括号 ret = (right == ')'); break; case '[': //左中括号 ret = (right == ']'); break; case '{': //左大括号 ret = (right == '}'); break; case '\'': //左单引号 ret = (right == '\''); break; case '\"': //左双引号 ret = (right == '\"'); break; default: ret = 0; break; } //匹配成功返回1,不成功返回0 return ret; } int isRight(char right) { int ret = 0; switch (right) { case '>': //右尖括号 case ')': //右小括号 case ']': //右中括号 case '}': //右大括号 case '\'': //右单引号 case '\"': //右双引号 ret = 1; //是需要检测的符号返回1 break; default: ret = 0; //不是需要检测的符号返回0 break; } return ret; } int isLeft(char left) { int ret = 0; switch (left) { case '<': //左尖括号 case '(': //左小括号 case '[': //左中括号 case '{': //左大括号 case '\'': //左单引号 case '\"': //左双引号 ret = 1; //是需要检测的符号返回1 break; default: ret = 0; //不是需要检测的符号返回0 break; } return ret; } int read(const char* code) { int i = 0; LinkStack* stack = LinkStack_Create(); while (code[i]) { // 判断是否是左符号 if (isLeft(code[i])) { // 是的话就压如栈中 printf("push = %c\n", code[i]); LinkStack_Push(stack, (void*)&code[i]); //continue; } // 判断是否是右符号 if (isRight(code[i])) { // 如果是则取出栈顶的符号与这个右符号对比 char left = *(char*)LinkStack_Top(stack); if (match(left, code[i])) { // 匹配成功,从栈中弹出匹配过的左符号 printf("pop = %c\n", code[i]); LinkStack_Pop(stack); } else { // 匹配失败直接报错并终止循环 printf("数据异常,匹配失败! left = %c, right = %c\n", left, code[i]); break; } } i++; } // 最后判断栈中是否还有数据,如果还有证明缺少右符号 if (!LinkStack_Size(stack)) { printf("匹配成功!\n"); } else { char ch = *(char*)LinkStack_Top(stack); printf("缺少匹配 %c\n", ch); } // 销毁 LinkStack_Destroy(stack); return 0; } int main(int argc, char* argv[]) { const char* code = "#include <stdio.h> int main() { int a[4][4]; int (*p)[4]; p = a[0]; return 0;}"; read(code); return 0; }
Stack 栈模型的链式存储实现
栈模型使用顺序存储的方式就相当于在数组上进行操作,而本文介绍的则是通过链式存储来实现栈的模型,那么我们就要思考一个问题了。栈只是栈顶来做插入和删除操作,栈顶放在链表的头部还是尾部呢?
Stack 栈模型的顺序存储实现
栈(Stack)也是数据存储的一种方式,我们可以将其理解为一种线性的表,只不过他是前去后继的关系,他只能在线性表的尾部插入和取出数据,这个尾部所指的就是栈的栈顶,而最先被存入的数据则是栈底。它具有后进先出、先进后出的特性。表示图如下:
循环链表的增删改查
循环链表与单向链表十分相似,两者唯一不同之处就是,循环链表的尾节点的next属性指向了链表的首节点(非头节点,头节点是没有数据的,头节点的下一个有数据的节点我们称为首节点)。他的表现形式有常见的两种,如下图:
智能指针入门 auto_ptr
所谓智能指针,就是可以随便申请而无需管理自动释放,就像 java 或 C# 的垃圾回收机制一样。我们无需关心销毁只管尽情的申请,系统提供了一个 auto_ptr 类可以使用这样的功能。后面我们也会用简单的代码示例介绍 auto_ptr 内部是如何实现的。代码如下:
指向类数据成员的指针
在C++中,可以定义一个指针,使其指向类成员或成员函数,然后通过指针
来访问类的成员。这包括指向属性成员的指针和指向成员函数的指针。它类似与static成员函数或成员变量,具有共享的属性。每一个实例化的对象都可以借助指向类数据成员的指针来访问指向的数据。它的结构图如下:
值传参、指针传参、引用传参区别
在C中,我们只了解到有两种传参方式,一种是值传递,另外一种是传递指针,一般情况下我们选择使用指针传递参数。在C++中,又新增了一种传参方式,那就是引用(type &),引用传参给我们带来了更好的体验。那三者的具体区别在哪里呢?
自实现简单atoi功能
atoi这个库函数实在的太强大了,很多细节上的处理是我们无法想象的,不过最近也尝试做了一下这个练习,发现真的不是那么简单,只实现了一部分功能。如将字符串”123″转换为123,”-0123″转换为-123。代码功能比较简陋,还有诸多没有实现的功能,相比库函数atoi还差的很多,仅供参考。
练习题目“天生棋局”
1、传入一个n 在堆空间中产生n*n方格的棋盘
int ** createBoard(int n);
int createBoard1(int ***p,int n);
2、N颗棋子随机落在棋盘上<需要防止落在同一位置>
int initBoard(int **p,int n);
3、打印棋盘
int printBoard(int **p,int n);
如果有两颗棋子落同一行或者同一列则输出好棋,否则输出不是好棋。
将棋局中的棋子打印出来空位用O,有旗子的用X表示。随意就行。
4、销毁棋盘
int destroyBoard(int **p,int n);
int destroyBoard1(int ***p,int n);
练习题目“涨工资”
有一个员工文件salary_back.txt,salary_back.txt文件每行 为部门职员的姓名:工资(如tom:20000),题目要求:
- 求出该公司有多少人。
- 从工资文件salary_back.txt中读入全部工人,全部增加100元工资后并保存信息到文件salary.txt中。
- 将加工资之后的所有员工按工资进行降序排序,将排序后的结果选出工资最高TOP10在屏幕上输出。
求字符串中出现频次最高的字符
题目给出的函数原型如下:
char getMostCharFromString(const char *str);
具体要求为,若有多个相同的字符备选,返回其中最早出现的字符,比如字符串”wwwwwwdddaaabbbdddcccc”,w和d都出现过6次,但只返回第一个最早出现的w。
计算一个字符串不重复字符个数
题目给出的函数原型如下:
int getCountOfString(const char *str);
由于参数是const的,所以字符串本身肯定是不能被修改的,题目大致思路就是备份一份字符串到堆空间中(可修改),然后遍历堆空间将重复的字符串置成\0,最后遍历整个堆上的字符串将去除\0后得到的总数返回。