节长为为止.错误返回NULL
,此函数使用DOS的PATH变量,未找到文件返回NULL
并异常终止程序。无返回值
int exec…装入和运行其它程序
exec函数族装入并运行程序pathname,并将参数
在exec函数族中,后缀l、v、p、e添加到exec后,
所指定的函数将具有某种操作能力
有后缀 p时,函数可以利用DOS的PATH变量查找子程序文件。
l时,函数中被传递的参数个数固定。
v时,函数中被传递的参数个数不固定。
e时,函数传递指定参数envp,允许改变子进程的环境,
无后缀e时,子进程使用当前程序的环境。
并调用任何寄存器的"出口函数",无返回值
mode为 P_WAIT 表示在子程序运行完后返回本程序 P_NOWAIT 表示在子程序运行时同时运行本程序(不可用) P_OVERLAY表示在本程序退出后运行子程序 所指定的函数将具有某种操作能力 有后缀 p时, 函数利用DOS的PATH查找子程序文件 l时, 函数传递的参数个数固定. v时, 函数传递的参数个数不固定. e时,
指定参数envp可以传递给子程序,允许改变子程序运行环境. 当无后缀e时,子程序使用本程序的环境.
将浮点数value转换成字符串并返回该字符串
将浮点数value转换成字符串并返回该字符串
将数value转换成字符串并存于buf中,并返回buf的指针
将无符号整型数value转换成字符串并返回该字符串,radix为转换时所用基数
将长整型数value转换成字符串并返回该字符串,radix为转换时所用基数
将整数value转换成字符串存入string,radix为转换时所用基数
就显示一个信息并异常终止程序,无返回值
字符串str:错误信息
用户修改数学错误返回信息函数(没有必要使用)
用户修改数学错误返回信息函数(没有必要使用)
int fgetchar()从控制台(键盘)读一个字符,显示在屏幕上
int getch() 从控制台(键盘)读一个字符,不显示在屏幕上
int getchar() 从控制台(键盘)读一个字符,显示在屏幕上
int getche() 从控制台(键盘)读一个字符,显示在屏幕上
赋值,使用BIOS进行输出
赋值,直接对控制台作操作,比如显示器在显示时字符时即为直接写频方式显示
直接对控制台作操作,比如显示器即为直接写频方式显示
直接对控制台作操作,比如显示器即为直接写频方式显示
直接对控制台作操作,比如显示器即为直接写频方式显示,
将字符串string的内容重新写为格式化后的字符串
将字符串string的内容重新写为格式化后的字符串,参数从Valist param中取得
本函数是用来控制输入/输出设备的,请见下表:
┌───┬────────────────────────────┐
├───┼────────────────────────────┤
│ 0 │取出设备信息 │
│ 1 │设置设备信息 │
│ 6 │取输入状态 │
│ 7 │取输出状态 │
│ 11 │置分享冲突的重算计数;只对DOS3.x │
└───┴────────────────────────────┘
按后按access来确定是读文件还是写文件,access值见下表
┌──────┬────────────────────┐
├──────┼────────────────────┤
│O_NOINHERIT│若文件没有传递给子程序,则被包含 │
│O_DENYALL │只允许当前处理必须存取的文件 │
│O_DENYWRITE│只允许从任何其它打开的文件读 │
│O_DENYREAD │只允许从任何其它打开的文件写 │
│O_DENYNONE │允许其它共享打开的文件 │
└──────┴────────────────────┘
按后按access来确定是读文件还是写文件,access值见下表
┌────┬────────────────────┐
├────┼────────────────────┤
│O_APPEND│即读也写,但每次写总是在文件尾添加 │
│O_CREAT │若文件存在,此标志无用;若不存在,建新文件 │
│O_TRUNC│若文件存在,则长度被截为0,属性不变 │
│O_BINARY│此标志可显示地给出以二进制方式打开文件 │
│O_TEXT │此标志可用于显示地给出以文本方式打开文件│
└────┴────────────────────┘
permiss为文件属性,可为以下值:
读写性。permiss为文件读写性,可以为以下值
属性。attrib为文件属性,可以为以下值
属性。attrib为文件属性,可以为以下值
属性。attrib为文件属性,可以为以下值
存入buf中,直接调用MSDOS进行操作.
并将文件时间存于ftime结构中,成功返回0,ftime结构如下:
┌─────────────────┐
└─────────────────┘
新时间在结构ftime中.成功返回0.结构ftime如下:
┌─────────────────┐
└─────────────────┘
成功返回0否则返回-1,可用于UNIX系统 成功返回0否则返回-1,只能用于MSDOS系统
并返回这个文件指针,type可为以下字符串加上后缀
┌──┬────┬───────┬────────┐
│type│读写性 │文本/2进制文件│建新/打开旧文件 │
├──┼────┼───────┼────────┤
│r │读 │文本 │打开旧的文件 │
│w │写 │文本 │建新文件 │
│a │添加 │文本 │有就打开无则建新│
│r+ │读/写 │不限制 │打开 │
│w+ │读/写 │不限制 │建新文件 │
│a+ │读/添加│不限制 │有就打开无则建新│
└──┴────┴───────┴────────┘
可加的后缀为t、b。加b表示文件以二进制形式进行操作,t没必要使用
例: ┌──────────────────┐
└──────────────────┘
个长度为size的字符串存入ptr中
个长度为size的字符串,字符串在ptr中
串写给指定的流stream
┌───┬───────────────────────────────┐ │type值│意义 │ ├───┼───────────────────────────────┤ │_IOFBF│文件是完全缓冲区,当缓冲区是空时,下一个输入操作将企图填满整个缓│ │ │冲区.在输出时,在把任何数据写到文件之前,将完全填充缓冲区. │
│_IOLBF│文件是行缓冲区.当缓冲区为空时,下一个输入操作将仍然企图填整个缓│ │ │冲区.然而在输出时,每当新行符写到文件,缓冲区就被清洗掉. │ │_IONBF│文件是无缓冲的.buf和size参数是被忽略的.每个输入操作将直接从文 │ │ │件读,每个输出操作将立即把数据写到文件中. │ └───┴───────────────────────────────┘
处理即对读的流,将流内内容读入缓冲区;
对写的流,将缓冲区内内容写入流。成功返回0
int fflushall() 关闭所有流,并对流各自的缓冲区作处理
处理即对读的流,将流内内容读入缓冲区;
对写的流,将缓冲区内内容写入流。成功返回0
函数将属性存于amode中,amode由以下位的组合构成
06可以读、写 04可以读 02可以写 01执行(忽略的) 00文件存在
如果filename是一个目录,函数将只确定目录是否存在
函数执行成功返回0,否则返回-1
本函数用于读取或设定文件filename的属性,
当func=0时,函数返回文件的属性;当func=1时,函数设定文件的属性
若为设定文件属性,attrib可以为下列常数之一
函数分析一个字符串,通常,对一个文件名来说,是由cmdline所指的一个命令行.
文件名是放入一个FCB中作为一个驱动器,文件名和扩展名.FCB是由fcbptr所指
定的.option参数是DOS分析系统调用时,AL文本的值.
辑扇区号,buffer为保存所读数据的保存空间 辑扇区号,buffer为保存所写数据的所在空间 ┌───────────────────┐ └───────────────────┘
本函数返回指定驱动器drive(0=当前,1=A,2=B等)的文件分配表信息
并存入结构fatblkp中,结构如下:
┌──────────────────┐
└──────────────────┘
并存入结构fatblkp中,结构如下:
┌──────────────────┐
└──────────────────┘
执行intr_num号中断,用户定义的寄存器值存于结构inregs中,
执行完后将返回的寄存器值存于结构outregs中.
结构inregs中和结构segregs中,执行完后将返回的寄存器值存于结构outregs中.
本函数执行DOS中断0x21来调用一个指定的DOS函数,用户定义的寄存器值
存于结构inregs中,执行完后函数将返回的寄存器值存于结构outregs中
本函数执行DOS中断0x21来调用一个指定的DOS函数,用户定义的寄存器值
存于结构inregs和segregs中,执行完后函数将返回的寄存器值存于结构outregs中
它能产生一个由参数intr_num指定的8086软件中断.函数在执行软件中断前,
从结构preg复制用户定义的各寄存器值到各个寄存器.软件中断完成后,
函数将当前各个寄存器的值复制到结构preg中.参数如下:
preg为保存用户定义的寄存器值的结构,结构如下
┌──────────────────────┐
└──────────────────────┘
函数执行完后,将新的寄存器值存于结构preg中
用空间由size决定.
每当出现错误时就调用fptr所指的程序
函数将fcbptr所指的FCB中的reccnt个记录写到磁盘上
value为0表示关闭检验,为1表示打开检验
int getcbrk()本函数返回控制中断检测的当前设置
错误信息填入eblkp所指的DOSERR结构中.该结构定义如下:
┌──────────────┐
└──────────────┘
0置通讯参数为字节byte值 1 发送字符通过通讯线输出 2从通讯线接受字符 3 返回通讯的当前状态 byte为传送或接收数据时的参数,为以下位的组合: ┌───┬─────┬───┬─────┬───┬─────┐ │byte值│意义 │byte值│意义 │byte值│意义 │ │ ├───┼─────┼───┼─────┼───┼─────┤ │0x04 │2停止位
│0x00 │无奇偶性 │0x08 │奇数奇偶性│ │ └───┴─────┴───┴─────┴───┴─────┘ 函数返回值为一个16位整数,定义如下: 第14位 传送移位寄存器空 第13位 传送固定寄存器空 第 9位 过载运行错误 第 7位 接收线信号检测 第 5位 数据设置就绪 第 3位 δ接收线信号检测器 第 2位 下降边环形检测器 第 1位 δ数据设置就绪
本函数用来对驱动器作一定的操作,cmd为功能号, 0 重置软磁盘系统.这强迫驱动器控制器来执行硬复位.忽略所有其它参数. 1 返回最后的硬盘操作状态.忽略所有其它参数 2 读一个或多个磁盘扇区到内存.读开始的扇区由head、track、sector给出。 扇区号由nsects给出。把每个扇区512个字节的数据读入buffer 3
从内存读数据写到一个或多个扇区。写开始的扇区由head、track、sector 给出。扇区号由nsects给出。所写数据在buffer中,每扇区512个字节。 4 检验一个或多个扇区。开始扇区由head、track、sector给出。扇区号由 5 格式化一个磁道,该磁道由head和track给出。buffer指向写在指定track上 的扇区磁头器的一个表。
以下cmd值只允许用于XT或AT微机: 6 格式化一个磁道,并置坏扇区标志。 7 格式化指定磁道上的驱动器开头。 8 返回当前驱动器参数,驱动器信息返回写在buffer中(以四个字节表示)。 9 初始化一对驱动器特性。 10 执行一个长的读,每个扇区读512加4个额外字节 11 执行一个长的写,每个扇区写512加4个额外字节 12 执行一个磁盘查找 16 检查指定的驱动器是否就绪
函数返回由下列位组合成的状态字节: 0x02 地址标记找不到 0x07 驱动参数活动失败 0x0B 检查坏的磁盘标记 0x11 ECC校正的数据错误(注意它不是错误) 0x80 响应的连接失败 0xBB 出现无定义错误 0xFF 读出操作失败
int biodquip()检查设备,函数返回一字节,该字节每一位表示一个信息,如下:
00为1号驱动器,01为2号驱动器,10为3号驱动器,11为4号驱动器 第 1位 浮点共用处理器 第 0位 从软磁盘引导 0 返回敲键盘上的下一个键。若低8位为非0,即为ASCII字符;若低8位为0, 则返回扩充了的键盘代码。 1 测试键盘是否可用于读。返回0表示没有键可用;否则返回下一次敲键之值。 敲键本身一直保持由下次调用具的cmd值为0的bioskey所返回的值。 2 返回当前的键盘状态,由返回整数的每一个位表示,见下表: ┌──┬───────────┬───────────┐ │ 位│为0时意义 │为1时意义 │ ├──┼───────────┼───────────┤ │ 7 │插入状态 │改写状态 │ │ 6 │大写状态 │小写状态 │ └──┴───────────┴───────────┘ 0 打印字符,将字符byte送到打印机 函数返回值由以下位值组成表示当前打印机状态 0x01 设备时间超时 0 函数返回计时器的当前值
本函数用来控制某一国家的相关信息,如日期,时间,货币等.
所指向的country结构用下列的国家相关信息填充:
┌────────────────────┐
└────────────────────┘
co_date的值所代表的日期格式是:
0 月日年 1日月年 2 年月日
co_currstrle的值所代表的货币显示方式是
0 货币符号在数值前,中间无空格
1 货币符号在数值后,中间无空格
2 货币符号在数值前,中间有空格
3 货币符号在数值后,中间有空格
这些函数,mem…系列的所有成员均操作存贮数组.在所有这些函数中,数组是n字节长.
memcpy从source复制一个n字节的块到destin.如果源块和目标块重迭,则选择复制方向,
以例正确地复制覆盖的字节.
memset将s的所有字节置于字节ch中.s数组的长度由n给出.
memcmp比较正好是n字节长的两个字符串s1和s2.些函数按无符号字符比较字节,因此,
memicmp比较s1和s2的前n个字节,不管字符大写或小写.
memchr对字符ch检索s数组的前n个字节.
├─若s1=s2返回值等于0 memccpy若复制了ch,则返回直接跟随ch的在destin中的字节的一个指针; memchr返回在s中首先出现ch的一个指针;如果在s数组中不出现ch,就返回NULL. 本函数从source处复制一块长len字节的数据到destin.若源地址和目标地址字符串
重迭,则选择复制方向,以便正确的复制数据.
本函数把addr所指的块的第一个字节置于字节value中.
str…字符串操作函数
将字符串src添加到dest末尾
检索并返回字符c在字符串s中第一次出现的位置
比较字符串s1与s2的大小,并返回s1-s2
扫描s1,返回在s1中有,在s2中也有的字符个数
将字符串s复制到最近建立的单元
将字符串s中的大写字母全部转换成小写字母,并返回转换后的字符串
将字符串src中最多maxlen个字符复制到字符串dest中
比较字符串s1与s2中的前maxlen个字符
比较字符串s1与s2中的前maxlen个字符
将字符串s的前n个字符置于ch中
扫描字符串s1,并返回在s1和s2中均有的字符个数
扫描最后出现一个给定字符c的一个字符串s
将字符串s中的字符全部颠倒顺序重新排列,并返回排列后的字符串
将一个字符串s中的所有字符置于一个给定的字符ch
扫描字符串s1,并返回在s1和s2中均有的字符个数
扫描字符串s2,并返回第一次出现s1的位置
检索字符串s1,该字符串s1是由字符串s2中定义的定界符所分隔
将字符串s中的小写字母全部转换成大写字母,并返回转换后的字符串
size为分配内存大小,seg为分配后的内存指针
seg为已分配内存的内存指针,newsize为新的长度
本函数用来改变分配给调用程序的数据段的空间数量,新的空间结束地址为endds
本函数用来增加分配给调用程序的数据段的空间数量,增加incr个字节的空间
并返回所分配内存的指针
存区域的指针,newsize为新的长度,返回分配好的内存指针.
long farcoreleft()本函数返回远堆中未用的存储区的长度,以字节为单位
从远堆分配units个长度为unitsz的内存空间,并返回所分配内存的指针
所要释放的远堆内存的指针为block
存的大小,block为已分配有内存区域的指针,newzie为新的长度,返回分配好
在时间日期函数里,主要用到的结构有以下几个:
总时间日期贮存结构tm
┌──────────────────────┐
└──────────────────────┘
┌───────────────┐
└───────────────┘
┌────────────────┐
└────────────────┘
本函数把clock所指的时间(如由函数time返回的时间)转换成下列格式的
本函数把指定的tm结构类的时间转换成下列格式的字符串:
计算结构time2和time1之间的时间差距(以秒为单位)
转换成格林威治时间,并以tm结构形式返回
转换成当地标准时间,并以tm结构形式返回
本函数将dateptr所指的日期,timeptr所指的时间转换成UNIX格式,并返回
自格林威治时间1970年1月1日凌晨起到现在的秒数
本函数将自格林威治时间1970年1月1日凌晨起到现在的秒数utime转换成
long time(long*tloc)本函数给出自格林威治时间1970年1月1日凌晨至现在所经 过的秒数,并将该值存于tloc所指的单元中.
作为一位 Excel 发烧友,花了一个周末的时间整理了甘特图的绘制技巧,借着这个话题直接分享 6 种超全的甘特图绘制技巧,每一种都有自己的特色+保姆级的制作教程,希望对你有所帮助呀~
先来看 6 种甘特图的高清不同实现效果,另外前方多图多GIF,请放心食用:
另外回答中演示的这 6 种甘特图源文件,我也整理出来分享给大家了,希望对你有帮助呀~
首先是最基础的「甘特图」,功能上只展示了项目/活动的工期,并无其他功能,这也是最简单的甘特图,先来看下整体的实现效果,如下所示:
虽然非常简单,但是在某些只需要看到工期安排的场合下,非常好用,接下来我们来看下是如何制作的。
首先是「作图数据」预处理,共有 3 个步骤:
只要满足上面的 3 个需求,就可以到「作图」这一步,作图总共被我划分成了 ⑤ 个步骤。
① 首先,选中「所有数据」,直接插入「堆积条形图」,如下:
② 条形图默认会将Y轴的顺序颠倒,右击「垂直坐标轴」,设置「逆序类别」,调正Y轴的顺序。
③ 现在「甘特图」的整体模型就已经出来了,接下来设置「间隙宽度」为「30%」,将不需要的数据系列设置为「无填充」。
④ 看着还是比较奇怪,因为 Excel 的横坐标时间轴没有调整对,接下来调整下「X轴的范围」,只需要将「起点&终点」分别手动输入「项目的起点&终点日期」即可。
⑤ 现在甘特图的整体结构已经出来了,接下来只需要调整配色、插入标题、设置线框、添加脚注/数据标签,这些都属于比较基础的,就不录制动图演示了。
现在就完成了一个最基础的甘特图图表,当我们更改工期的时候,图表也会联动,如下:
来总结一下「数据预处理」和「作图」两个阶段的 ⑥ 步骤汇总:
是不是非常简单呢?好了,可以说所有的“堆积条形图制作的甘特图”都差不多基于以上步骤。
现在我们已经学会了 1+1,接下来要来尝试制作“原子弹”了(开玩笑,开始升级甘特图)
当然如果我们想看到“带任务进度”的甘特图呢?方法一分享的图表就不再适用了,不过我们可以对其进行升级,实现效果如下:
步骤和「基础甘特图」非常接近,不过不一样的就是「数据结构」。
我们需要将“计划工期”拆分成“已完成工期”和“剩余工期”,其中“已完成工期”手动录入,“剩余工期”使用 Excel 公式:
然后选中除「计划工期」的所有列,绘制「堆积条形图」,框选不同的列也有技巧,选择的时候按住「Ctrl键」即可,如下:
接下来几乎所有的步骤都和基础甘特图一模一样,这里就不再演示了。
另外如何将「剩余工期」单独填充成「虚线」呢?只需要将数据系列中「填充」设置为「图案填充」,选择想要的图案即可。
同样这个图表也是可以动态联动的,当我们修改「计划工期」或者「已完成工期」时,图表会自动更新,是不是非常强!
整理下「带任务进度甘特图」的整体制作步骤:
好啦,基于基础图表,已经衍生出第一种图表了,想想也不难,接下来我们来对它再次升级。
在某些复杂的情况下,部分任务/项目可能会存在跨越多个时间段的情况,上面的两种技巧又不能直接使用了,不过可以继续升级改造。
例如下图演示的“项目A和项目D”,共分成 2 个阶段来完成,如下所示:
恰好这个图也是提问者想要实现的图表,我称之为“跨阶段甘特图”,绘制起来其实也非常简单。
本质上也是利用了“辅助列”设置为“无填充”的方式来实现的。
首先我们来升级下数据结构,这里由于最多被划分成了 2 个阶段,所以:
数据结构如下所示,当最多划分成 3 个阶段乃至 N 个阶段时,也以此类推:
接下来选中所有除「工期」字段的数据,例如:一阶段工期和二阶段工期不要选中,然会绘制「堆积条形图」:
绘制完图表之后,是不是发现和前面的步骤非常接近,没错,我们又回到了「带任务进度甘特图」的操作技巧。
唯一多的操作就是,我们需要将「辅助」列设置为「无填充」。
对于没有「二阶段」分配的项目,后面所有的数据只需要设置为 0 即可,如果需要新增二阶段,则需要修改这几个字段的数据:辅助、二阶段工期、二阶段完成,同样也是联动的。
简单吧!但是功能是不是非常多,这些都是由基础的「堆积条形图」衍生出来的,不过上面这些还不完善,因为工期没有统一,而且需要通过手动来修改。
能否实现通过按钮点击来增加或者减少工期呢?答案是可以,接下来我们继续升级图表。
在实际的工作中,通过手动来修改“已完成工期”的数据,非常容易出错,特别是在数据比较多的i情况下,其实针对这点,可以插入「Excel控件」,通过控件来控制任务进度。
例如:通过「滚动条」控件来实现任务进度的修正,如下所示:
这里我们用了「带任务进度甘特图」的数据来进行演示,不过多添加了几个辅助单元格:
数据结构如下,其中「一阶段完成」字段也是使用公式计算的,一会来介绍:
首先我们插入一个控件,选择「开发工具」选项卡下的「滚动条」,如下:
然后右击「滚动条」,选择「设置控件格式」,配置如下参数:
简单解释下这两个字段的含义:
现在我们操作滚动条,当前天数和当前日期就会发生变化了, 接下来我们设置「一阶段完成」的单元格公式如下,并向下填充:
含义也很简单,即判断「当前日期」是否超过了各个项目的「计划开始时间+计划工期」。
最后将滚动条放置到合适位置,就完成了这幅带控件的甘特图了。
简单吧,不过这个技巧只能在 Excel 上完成,而且对 Excel 的兼容性非常强(Excel 2007或者以上均支持),WPS对控件的支持能力较差,可能会出现不兼容的情况。
另外部分小伙伴的「开发工具」选项卡默认是没有开启的,可以点击「文件-选项-自定义功能区」,勾选上「开发工具」即可开启了。
另外如果觉得这些甘特图还不够美观,其实利用「单元格+函数+条件格式」同样也可以绘制出非常专业的甘特图,小北平时也收集+制作了几个。
不过由于制作难度比较大,这里就不先分享详细的教程,如果需要用到这么专业的图表,除非特殊情况,否则一般推荐用专业的甘特图工具。
例如:下方的「项目规划表」,即使用函数+条件格式制作而成的,交互功能也非常强:
或者是这种更加复杂,带有滚动条控件+日历的甘特图,利用:控件+函数+条件格式制作,交互功能会更强,而且功能更多,不过制作起来太复杂了。
亦或者是带有「关键路径分析」功能的甘特图,如下:
或者是将「Todo列表+任务优先级」加入到甘特图中,形成功能更加丰富的工具,如下:
当然,Excel作为一个超复杂的电子表格管理系统,本身还有 VBA 的加持,早就可以算是一个图灵完备的工具了,几乎你能想到的甘特图功能,都能利用 Excel 开发出来,就是难度大小的问题。
另外在 Office 内置的模板库里就能找到不少的甘特图模板,操作技巧也很简单,点击「文件」-「新建」,直接搜索“甘特图”即可:
看到回答中有知友分享了用「散点图」来模拟甘特图,虽然也能实现,但是缺陷也很大:
所以放到了最后才推荐,例如下图,即使用「散点图+误差线」的方式来模拟:
首先来看下数据结构,共有 4 个字段,分别是:项目名称、计划开始时间、Y、计划工期,这里的 Y 固定是从 1~N,总共有 N 个项目,就到 N。
然后选中「计划开始时间」和「Y」,直接插入散点图,如下:
然后为「散点图」添加 X 轴的误差线,并设置误差线为「特定的值」,选择 E 列数据,结果如下:
最后为误差线设置粗细为「13磅」,添加数据标签、标题、脚注、logo 等元素,一幅基于「散点图」的甘特图就制作完毕了。
同样这一份图表也是支持联动的,不过误差线默认没法设置多段,所以没法直接通过分段来设置进度(如果需要设置进度,需要继续添加辅助散点数据,和方法二类似)。
好了,以上就是本次要分享的 6 种甘特图绘制技巧了,你学会了么?如果对你有帮助,在收藏浏览的同时不要忘记点个「赞」+「关注」哦,下次还能收到知乎推荐的更多优质回答。
暂时先分享到这里了,作图花了一个周末,写回答花了 3 个小时,持续更新中,另外这篇回答的练习文件稍后我也会整理上来分享给大家。
如果你还有其他想学的技巧,可以 ,我会更新上来,我的其他高赞回答,也是非常有用的学习资料,希望对你有帮助~