0%

PGERRB – horizontal or vertical error bar

对应的C函数为

1
void cpgerrb(int dir, int n, const float *x, const float *y, const float *e, float t);
1
2
3
4
SUBROUTINE PGERRB (DIR, N, X, Y, E, T)
INTEGER DIR, N
REAL X(*), Y(*), E(*)
REAL T

绘制误差图,方向由DIR指定,这个函数只是绘制误差图,如果需要标注误差值的点,可以使用PGPT函数。

测试数据为:

1
2
3
static float xs[] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0 ,6.0,7.0,8.0,9.0,10.0};
static float ys[] = {0.5, 1.0, 1.5,2.0, 2.5, 3.0, 3.5 ,4.0,4.5,5.0,5.5,6.0};
static float err[] = {1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0};

参数说明

  • DIR (输入) : 绘制数据点误差图的方向。
  • 单方向:
  • DIR为1时,绘制+X (X to X+E);
  • DIR为2时,绘制+Y (Y to Y+E);
  • DIR为3时,绘制-X (X to X-E);
  • DIR为4时,绘制-Y (Y to Y-E);
  • 双方向:
  • DIR为5时,绘制+/-X (X-E to X+E);
  • DIR为6时,绘制+/-Y (Y-E to Y+E);
  • N (输入) :绘制误差图的数目
  • X (输入) : 数据的x坐标
  • Y (输入) : 数据的y坐标
  • E (输入) : 绘制数据误差图的值
  • T (输入) : 误差图终端的长度,如果T = 0.0,将不绘制终端

注: X, Y和E的维数必须大于或等于N. 如果 N 为1,那么 X, Y和E就应该是同等数量的变量或表达式。

C语言的标准(K&R C,ANSI C,C89,C90,C99)

历史

  • C语言:1973年由Dennis M. Ritchie设计和实现。

  • K&R C:1978年由Kernighan和Ritchie合写的书《The C Programming Language》,形成了C语言的事实的标准,简称为K&R C。

  • ANSI C(C89或C90):1989年,美国国家标准局(ANSI)颁布了第一个官方的C语言标准(X3.159-1989),简称为ANSI C或C89;1990年,它被国际标准化组织(ISO)采纳国际标准(ISO/IEC9899:1990),简称为C90。这个标准是目前广泛使用并完全支持的。

  • C99:1999年,ISO/ANSI又推出了新的标准(ISO9899:1999),简称C99。这个标准目前支持的可能还不太全面。

C89/C90标准的指导原则是

  • 相信程序员;
  • 不妨碍程序员做需要完成的事情;
  • 让语言保持短小简单;
  • 只提供一种方法来执行一种操作;
  • 使程序运行速度快,即使不能保证其可移植性。(不追求定义的抽象统一,更优先考虑运行效率)

C89/C90对K&R C的改变有:

  • 增加了函数原型(prototype),强调对函数的输入参数进行严格的类型检查;并补充定义了C语言的标准函数库
  • 删除了关键字:entry(条目/入口)
  • 增加了关键字:const(常型变量)、enum(枚举类型)、signed(有符号的,例如signed char)、void(空/无,可用于函数返回值和形参、通用指针类型)、volatile(易变变量,防止编译器错误的优化)
  • 传递结构:允许将结构本身作为参数传递给函数(原来只允许传地址)
  • 函数原型:增加了函数原型(便于编译器进行类型检查)
  • 增加了预处理指令:#elif(else if)、#error(错误,强制编译停止)、#line(修改当前行号和源文件名)、#pragma(附注/编译指令,编译器定义的与实现有关的指令)
  • 定义了固有宏:__LINE__(当前行号)、__FILE__(源文件名)、__DATE__(当前系统日期)、__TIME__(当前系统时间)、__STDC__(标准C版时为1)

C99的修订目标主要有三点:

  • 支持国际化编程,引入了支持国际字符集Unicode的数据类型和库函数;
  • 修正原有版本的明显缺点。如整数的移植方法,例如int8_t、int16_t、int32_t和int64_t等类型;
  • 针对科学和工程的需要,改进计算的实用性。例如添加了复数类型和新数学函数。

C99标准的新特性

C99是在C89(Ansi C)的基础上发展起来的,增加了基本数据类型,关键字 ,和一些系统函数等。目前完全支持的有这些:MinGW、Borland C++、dev-C++。

相对于c89的变化包括

  • 增加restrict指针
  • inline(内联)关键字
  • 新增数据类型 _Bool
  • 对数组的增强: 可变长数组
  • 可以单行注释
  • 分散代码与声明
  • 预处理程序的修改
  • 复合赋值
  • 柔性数组结构成员
  • 指定的初始化符
  • printf()和scanf()函数系列的增强

C89中标准的头文件

  • <assert.h> 定义宏assert()
  • <ctype.h> 字符处理
  • <errno.h> 错误报告
  • <float.h> 定义与实现相关的浮点值勤
  • <limits.h> 定义与实现相关的各种极限值
  • <locale.h> 支持函数setlocale()
  • <math.h> 数学函数库使用的各种定义
  • <setjmp.h> 支持非局部跳转
  • <signal.h> 定义信号值
  • <stdarg.h> 支持可变长度的变元列表
  • <stddef.h> 定义常用常数
  • <stdio.h> 支持文件输入和输出
  • <stdlib.h> 其他各种声明
  • <string.h> 支持串函数
  • <time.h> 支持系统时间函数

C99新增的头文件和库

  • <complex.h> 支持复数算法
  • <fenv.h> 给出对浮点状态标记和浮点环境的其他方面的访问
  • <inttypes.h> 定义标准的、可移植的整型类型集合。也支持处理最大宽度整数的函数
  • <iso646.h> 首先在此1995年第一次修订时引进,用于定义对应各种运算符的宏
  • <stdbool.h> 支持布尔数据类型类型。定义宏bool,以便兼容于C++
  • <stdint.h> 定义标准的、可移植的整型类型集合。该文件包含在<inttypes.h>中
  • <tgmath.h> 定义一般类型的浮点宏
  • <wchar.h> 首先在1995年第一次修订时引进,用于支持多字节和宽字节函数
  • <wctype.h> 首先在1995年第一次修订时引进,用于支持多字节和宽字节分类函数
限制 C89标准 C99标准
数据块的嵌套层数 15 127
条件语句的嵌套层数 8 63
内部标识符中的有效字符个数 31 63
外部标识符中的有效字符个数 6 31
结构或联合中的成员个数 127 1023
函数调用中的参数个数 31 127

不再支持隐含式的int规则etc…

Linux的tracepath命令

tracepath用于显示报文到达某一个地址的路由信息,能够发现其中的MTU信息。

在探测过程中,会使用UDP端口或随机端口。所以可以看到后面的?符号。与traceroute类似。

这对于长距离的数据传输分析有很明显的帮助作用。

官方的定义为:

tracepath, tracepath6 - traces path to a network host discovering MTU along this path

使用方法为:

1
$ tracepath [-n] [-b] [-l pktlen] [-m max_hops] [-p port] destination

其中选项如下所示:

  • -n:只显示IP地址信息(默认是显示域名的,这个选项将不显示域名了)
  • -b:同时显示主机名和IP地址(默认没有域名的只显示IP地址,这个选项即使没有主机名也会把IP地址作为主机名)
  • -l:设置初始化的数据包长度,默认tracepath为65535,而tracepaht6为128000
  • -m:设置最大的hops(或最大的TTL)为max_hops(默认为30)
  • -p:设置初始使用的目标端口

官网的一个例子及含义

1
2
3
4
5
6
root@mops:~ $ tracepath6 3ffe:2400:0:109::2
1?: [LOCALHOST] pmtu 1500
1: dust.inr.ac.ru 0.411ms
2: dust.inr.ac.ru asymm 1 0.390ms pmtu 1480
2: 3ffe:2400:0:109::2 463.514ms reached
Resume: pmtu 1480 hops 2 back 2

以其中一行为例:

TTL 探测信息
1?: [LOCALHOST] pmtu 1500
1: dust.inr.ac.ru 0.411ms
这一列显示探测的TTL,用分号来分割。
不过有些情况下信息不足以确认,就出现了猜测的?
显示网络探测信息:
如果未发送到网络,则为路由器地址或者localhost地址;
这里还会显示MTU、延迟等等等。

最后一行会总结整个链路的状态信息,显示了检测到的路径MTU、到达目的地的hops以及从目的地返回的hops数。

可以与ping配合使用,可以先用ping获取到具体的IP地址,然后使用tracepath进行进一步的分析。

1
2
3
4
5
6
7
8
9
10
11
12
13
$  ping www.bing.com
PING china.bing123.com (202.89.233.101) 56(84) bytes of data.
64 bytes from 202.89.233.101 (202.89.233.101): icmp_seq=1 ttl=116 time=28.1 ms
64 bytes from 202.89.233.101 (202.89.233.101): icmp_seq=2 ttl=116 time=27.9 ms
^C
--- china.bing123.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 27.964/28.072/28.181/0.199 ms
$ tracepath 202.89.233.101
1?: [LOCALHOST] pmtu 1500
1: no reply
2: 202.127.24.1 2.859ms
...

Linux的traceroute命令

..note::
少小离家老大回,乡音无改鬓毛衰。
贺知章《回乡偶书二首·其一》

Linux traceroute命令用于打印显示数据包到网络主机的路径。

traceroute会跟踪从IP网络发送到指定主机的路由包,并利用IP协议的生存时间(TTL)字段,试图在通往主机路径上的每个网关得到一个ICMP TIME_EXCEEDED响应,由此可得具体的路由信息。

官方的定义为:

traceroute - print the route packets trace to network host

语法

使用方法还挺复杂的,不过常用的不多:

1
2
3
4
5
6
7
$ traceroute [-46dFITUnreAV] [-f first_ttl] [-g gate,...]
[-i device] [-m max_ttl] [-p port] [-s src_addr]
[-q nqueries] [-N squeries] [-t tos]
[-l flow_label] [-w waittimes] [-z sendwait] [-UL] [-D]
[-P proto] [--sport=port] [-M method] [-O mod_options]
[--mtu] [--back]
host [packet_len]

最简单的一个实例

显示到达目的地的数据包路由

1
2
3
4
5
6
7
8
9
10
11
12
13
$ traceroute www.bing.com
traceroute to www.bing.com (202.89.233.101), 30 hops max, 60 byte packets
1 * * *
2 10.12.24.1 (202.127.24.1) 3.487 ms 3.490 ms 4.484 ms
3 * * *
4 192.168.1.53 (192.168.1.53) 4.437 ms 4.435 ms 4.426 ms
5 * * 211.102.30.10 (211.102.30.10) 4.358 ms
6 202.97.63.141 (202.97.63.141) 4.344 ms 202.97.53.117 (202.97.53.117) 3.892 ms 202.97.37.61 (202.97.37.61) 5.872 ms
7 202.97.87.121 (202.97.87.121) 3.902 ms 202.97.87.153 (202.97.87.153) 3.878 ms *
8 202.97.97.233 (202.97.97.233) 35.858 ms 40.803 ms 40.796 ms
9 * 36.110.248.146 (36.110.248.146) 26.951 ms *
10 * 220.181.81.82 (220.181.81.82) 26.931 ms 180.149.128.201 (180.149.128.201) 26.941 ms
11 220.181.17.86 (220.181.17.86) 33.956 ms 220.181.81.10 (220.181.81.10) 26.943 ms *

cpgconb 绘制等高线图

对应的C函数为

1
void cpgconb(const float *a, int idim, int jdim, int i1, int i2,  int j1, int j2, const float *c, int nc, const float *tr, float blank);

绘制出一个数组的等高线图。这个函数与PGCONS基本相同,除了多了一个有参数blank定义的“魔数”,可能会导致等高线图有缺口。这个函数对大部分的数据测量都是比较有用的,but not all of the points of a grid.

参数:

  • A (输入) : 数组.
  • IDIM (输入) :数组A的一维大小
  • JDIM (输入) : 数组A的二维大小
  • I1,I2 (输入) : 准备绘制成等高线的第一维索引的范围
  • J1,J2 (输入) : 准备绘制成等高线的第二维索引的范围.
  • C (输入) : 等高线水平数组(与数组A有相同的单位); 尺寸至少为NC.
  • NC (输入) : 等高线水平的数字(小于等于C的尺寸). 这个值的绝对值用于对函数PGCONT的兼容,所以这个值的符号是很重要的。
  • TR (输入) : 定义从I,J网格向世界坐标转换的数组。点A(I,J)的世界坐标由下列公式给出:
1
2
3
X = TR(1) + TR(2)*I + TR(3)*J
Y = TR(4) + TR(5)*I + TR(6)*J
通常TR(3) 和TR(5) 均为0,除非这个坐标变换包含旋转或者修剪。
  • BLANK (输入) : 数组A中精确等于这个值的元素将被忽略。

cpgconb

cpgcurs – 读取光标位置

对应的C函数为

1
int cpgcurs(float *x, float *y, char *ch_scalar);

读取光标位置和用户的输入。在用户移动光标时输入一个字符。PGCURS就可以返回当前的光标值和字符。

返回值:

  • PGCURS : 如果调用成功返回1;如果没有光标或其他错误返回0。

参数:

  • X (输入/输出) : 光标的x坐标
  • Y (输入/输出) : 光标的y坐标
  • CH (输出) : 用户输入的字符,如果没有光标或其他错误返回’\0’

交互式程序比较常用

PGCLOS – 关闭选定的图形设备

对应的C函数为

1
void cpgclos(void);

关闭当前选定的图形设备。在设备关闭后,如果需要再次绘图,需要用PGSLCT选择另一个设备或者使用PGOPEN重新打开一个设备。如果调用PGCLOS的请求被忽略,一些图像可能会丢失。
[这个函数实在PGPLOT 5.1.0.版本中添加了,老版本用PGEND 代替。]

参数: 无

cpgbin – 数据的直方图

对应的C函数为

1
void cpgbin(int nbin, const float *x, const float *data, Logical center);

绘制有NBIN个值的直方图。

参数:

  • NBIN (输入) : 显示直方图的个数
  • X (输入) : 直方图的横坐标
  • DATA (输入) : 直方图的数据值
  • CENTER (输入) : 如果为1,则X坐标位于直方图中间,为0,则坐标值位于直方图起始的位置。

cpgbox - 在视口周围的框架上标记标签

对应的C函数为

1
void cpgbox(const char *xopt, float xtick, int nxsub, const char *yopt, float ytick, int nysub);

给视口注释框架、轴线和数字标记等。

PGBOX 被PGENV调用,也可以独自使用。

参数:

  • XOPT   (输入)  : X坐标轴的选项字符串,选项可以使单个字符串或者多个字符串(没有顺序安排)
  • XTICK  (输入)  : X坐标轴的主要标记坐标间隔,如果XTICK=0.0,那么坐标间隔主要标记将有PGBOX自行选择,所以坐标轴上至少有三个主要的标记符号。
    -NXSUB  (输入)  : X坐标轴的坐标间隔之间有几个刻度值。同样如果XTICK=0.0或者NXSUB=0,这个数据将有PGBOX自行选择。
  • YOPT   (输入)  : Y坐标轴的选项字符串,选项可以使单个字符串或者多个字符串(没有顺序安排)
  • YTICK  (输入)  : Y坐标轴的主要标记坐标间隔,如果XTICK=0.0,那么坐标间隔主要标记将有PGBOX自行选择,所以坐标轴上至少有三个主要的标记符号。
  • NYSUB  (输入)  : Y坐标轴的坐标间隔之间有几个刻度值。同样如果YTICK=0.0或者NYSUB=0,这个数据将有PGBOX自行选择。

选项 (参数XOPT和YOPT):

  • A : 绘制坐标轴(X坐标轴为水平线条Y=0,Y坐标轴为水平线条X=0)
  • B : 绘制框架的左(Y)下(X)边缘
  • C : 绘制框架的右(Y)上(X)边缘
    • G : 绘制网格线条
    • I : 将刻度标记放置于视口的外部而不是内部
    • L : 对数形式标记坐标轴
    • N : 在主要的间隔上(X轴下方,Y轴左方)标记数值
    • P : 扩展主要间隔的刻度标记超出视口,如果选项中有I,这个就可以忽略
    • M : 在非常规的地方做出数值标记(X轴上方,Y轴右方)
    • T : 在主要坐标间隔上做出刻度标记
  • S : 画出主要间隔的分割的小的刻度标记
    • V : 垂直放置数值标记,只是用于Y轴,默认为平行于Y坐标轴
    • 1 : 强制十进制形式标记
    • 2 : 强制指数形式标记

为了得到一个完整的框架,XOPT和YOPT必须都指定选项BC。

在调用PGENV 是,通过调用PGBOX, 可以通过参数AXIS来设置XOPT和YOPT,两者关系如下:

-1: ‘BC’, 0: ‘BCNST’, 1: ‘ABCNST’, 2: ‘ABCGNST’.

对指数坐标轴而言,主要间隔一直为1.0。
如果希望坐标轴以时间或角度为单位,可以调用PGTBOX。

cpgbbuf – 开始批处理输出 (buffer)

对应的C函数为 void cpgbbuf(void);

开始保存图形的输出命令到一个内部的buffer;这个函数与PGEBUF成对使用(或者这个buffer被PGUPDT清空)。这个函数极大地改进了PGPLOT的效率。PGBBUF会增加一个内部计数器,而PGEBUF减少这个内部计数器,当这个计数器降到0的时候将把buffer中的内容输出到设备。

PGBBUF和PGEBUF 应成对出现。

参数: 无