C++中输入、输出用的是cin、cout,对应的有输入输出缓冲区,cin、cout都是对缓冲区中的数据进行操作,那么看下面代码: #include <iostream> using namespace std; int hello1(); int hello2(); int main() { int a, b; cout << "a=" << hello1() << endl << "b=" << hello2() << endl; return 0; } int hello1() { cout << "hello1" << endl; return 1; } int hello2() { cout << "hello2" << endl; return 2; } 它的输出顺序是什么呢,会是 a=hello1 继续阅读 >>


吕子健 17/09/27 21:39:42
这三种都是对表达式的记法,区别只在于运算符与操作数的相对位置的差异,中缀表达式就是我们一般使用的相对容易理解的表达式,但是对于计算机来说,就很麻烦了,而前缀和后缀表达式对于计算机来说才是容易理解的版本 举例: (3 + 4) * 5 - 6 就是中缀表达式 - * + 3 4 5 6 前缀表达式 3 4 + 5 * 6 - 后缀表达式 前缀表达式的计算机求值: 从右至左扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素 op 次顶元素),并将结果入栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果。 例如前缀表达式“- × + 3 4 5 6”: (1) 从右至左扫描,将6、5、4、3压入堆栈; (2) 遇到+运算符,因此弹出3和4(3为栈顶元素,4为次顶元素,注意与后缀表达式做比较),计算出3+4的值,得7,再将7入栈; (3) 接下来是×运算符,因此弹出7和5,计算出7×5=35,将35入栈; (4) 最后是 继续阅读 >>


吕子健 17/09/21 11:16:13
说到抽象数据类型,那么就得先提到数据类型 数据类型指的是一个值的集合以及定义在这个集合上的一组操作 为什么要有不同的数据类型呢 当我们计算1+1的时候,只需要很小的存储空间,但是当我们去计算10000+100000的时候,所需要的空间就会大许多,那么我们为了去区分这些类别的差异,就有了不同的数据类型来更精确的确定存储空间的划分 第一次看到 int a;的时候,可是一脸懵逼,以为只是告诉我们这是一个“int”型的数据,现在看来,还是太浅了 而抽象数据类型包含三个部分:数据对象(数据元素)、数据关系(数据关系二院组结合)、基本操作(操作函数的罗列)。 那么按我的理解用大白话来说: 1. ADT和数据类型的关系,是被包起来的,即ADT∈数据类型 2. ADT需要通过固有的数据类型来实现 3. 举个列子,就像定义一个结构体,里面有很多不同的类型,然后定义基本操作,也就是说定义的函数 作者:weixin_368 继续阅读 >>


吕子健 17/09/12 21:10:48
这次写项目,在实现聊天的遇到一个问题:两个人实现即时聊天意味着你要死循环不停输入信息 这意味着你需要判断什么时候结束死循环,输入特定字符串来结束死循环的话,如果就想给对面发这个字符串呢 所以我想到了用ctrl+c来结束死循环,这样就用到了signal这个函数 上代码: #include<stdio.h> #include<signal.h> int flag; void s( int sig ) { flag = 0; } int main() { flag = 1; while( flag ) { signal( SIGINT,s ); } return 0; } 简单来说,遇到SIGINT软中断信号后,不去执行默认退出的操作,而是执行指定的s函数 在main里执行死循环,直到收到软中断信号,执行s函数,使flag 变为0,退出死循环 s函数的int参数接受的是信号种类 这里关于s函数具体的定 继续阅读 >>


吕子健 17/08/18 20:38:02
之前写课设的时候读取文件内容到链表,明明感觉代码没有问题,但是尾节点却总是不能正常置空,还会多出来一个节点,当时百思不得解,这道这次写项目,又碰到相同问题,才想明白了 如图: 这是我之前的操作,while读取文件内容fscanf为EOF时停止读取 这时将P指向NULL 也但是因为已经给P开辟了一块空间,让P和head指向它,这时你让P指向空,并没有改变head指向2所以他会“多出来”一个节点 以后的链表操作还需要细心一些啊… 作者:weixin_36888577 发表于 2017/08/18 09:54:39 原文链接 https://blog.csdn.net/weixin_36888577/article/details/77363156 阅读:101 继续阅读 >>


吕子健 17/08/18 09:54:39
我们知道 一个进程内的所有线程继承其数据与环境变量,共享数据空间,但是有时候我们需要有的线程拥有独属于其自己的数据变量,让其只在某个线程内有效,比如最常见的errno,每个线程出错的原因大不相同。 这个时候就需要创建线程的私有数据(TSD)了 线程的私有数据可以被其他函数访问,但拒绝被其他线程屏蔽 TSD采用了一键多值的技术,即一个键对应多个不同的值,每个线程访问数据时通过访问该键来得到对应的数据,在不同的线程中它对应了不同的值 其实系统为每个进程维护了一个称之为Key结构的结构数组,如下图所示: (这里不介绍析构函数,图片来源网络) 如图,这个pthread_key_t(其实是unsigned int)类型的key,在进程中创建,一般为0~127 在上图中Key 结构的“标志”指示这个数据元素是否正在使用。在刚开始时所有的标志初始化为“不在使用”。当一个线程调用pthread_key_create创建一个新的线程特定数据元素时,系统会搜索Key结构数组,找出第一 继续阅读 >>


吕子健 17/08/05 09:40:01
(图片来源网络) 从图中可以看出,_exit 函数的作用是:直接使进程停止运行,清除其使用的内存空间,并清除其在内核的各种数据结构;exit 函数则在这些基础上做了一些小动作,在执行退出之前还加了若干道工序。exit() 函数与 _exit() 函数的最大区别在于exit()函数在调用exit 系统调用前要检查文件的打开情况,把文件缓冲区中的内容写回文件。也就是图中的“清理I/O缓冲”。 1> exit()和_exit()函数都是用来终止进程的。 当程序执行到exit或_exit时,系统无条件的停止剩下所有操作,清除包括PCB在内的各种数据结构,并终止本进程的运行。 2> exit()在头文件stdlib.h中声明,而_exit()声明在头文件unistd.h中声明。 exit中的参数exit_code为0代表进程正常终止,若为其他值表示程序执行过程中有错误发生。 3> exit()和_exit()的区别: a._exit()执行后立即返回给内核,而exit() 继续阅读 >>


吕子健 17/08/01 16:39:17
这一周的小项目是实现一个自己的she’ll:实现输入输出重定向,管道,支持shell的内置cd命令,支持后台运行,实现tab补全和历史记录上下翻,ctrl+c不能中断程序,设置环境变量(让其可以像bash,zsh一样运行) 各点的实现总结如下: 1.重定向:输出重定向,创建你想输出到的文件,然后用dup2(old_fd,new_fd)这个函数,将其的文件描述符置为1,因为 标准输入(stdin):代码为0 标准输出(stdout):代码为1 标准错误输出(stdeer):代码为2 所以,我们让这个我们创建的文件占据了标准输出的位置,本来要输出到屏幕上的信息就会输出到这个文件里,而输入重定向和管道思路基本相同 2.管道:管道我们将输入的数据存入文件(描述符改为0),在输出到制定文件(只要把该文件描述符置为1) 3.后台运行只要不让其父进程等待即可 4.而cd命令则是检测到有 cd 命令后在子函数或在main里用chdir函数更改当前工作目录 ***5.***ctrl+c不能中断只要我们 继续阅读 >>


吕子健 17/07/29 10:08:08
这一周的小项目是实现一个自己的she’ll:实现输入输出重定向,管道,支持shell的内置cd命令,支持后台运行,实现tab补全和历史记录上下翻,ctrl+c不能中断程序,设置环境变量(让其可以像bash,zsh一样运行) 各点的实现总结如下: 1.重定向:输出重定向,创建你想输出到的文件,然后用dup2(old_fd,new_fd)这个函数,将其的文件描述符置为1,因为 标准输入(stdin):代码为0 标准输出(stdout):代码为1 标准错误输出(stdeer):代码为2 所以,我们让这个我们创建的文件占据了标准输出的位置,本来要输出到屏幕上的信息就会输出到这个文件里,而输入重定向和管道思路基本相同 2.管道:管道我们将输入的数据存入文件(描述符改为0),在输出到制定文件(只要把该文件描述符置为1) 3.后台运行只要不让其父进程等待即可 4.而cd命令则是检测到有 cd 命令后在子函数或在main里用chdir函数更改当前工作目录 ***5.***ctrl+c不能中断只要我们 继续阅读 >>


吕子健 17/07/29 10:08:08
看书上的关于exec函数的部分有点然,百度了一下各个函数,总结如下 1.execv函数: #include <unistd.h> int exevc(const char *pathname,char *const argv[]); argv参数是一个以空指针结尾的数组,即该数组里面存放的是命令执行需要的参数,最后一个元素是NULL 并且测试过后,argv[0]里面存放什么对结果不影响,所以argv[0]应该存放的是名字,而参数在第二个及以后存放 2.execve函数 #include<unistd.h> int execve(const char * filename,char * const argv[ ],char * const envp[ ]); execve()用来执行参数filename字符串所代表的文件路径,第二个参数是利用指针数组来传递给执行文件,并且同样需要以空指针(NULL)结束,最后一个参数则为传递给执行文件的新环境变量数组。 该函数如果执 继续阅读 >>


吕子健 17/07/26 10:23:52