首先介绍下这3个文件的关系:可以说INPUT1.C的函数粒度最大,它的函数getdata()就完成了整个INPUT文件数据的读入,该函数又调用了INPUT2.C中的部分函数,INPUT2.C文件中的函数分为两类,一类是解析INPUT文件的函数;另一类是工具函数,包括将节点、管段数据存入哈希表中,构建哈希索引、字符串的匹配,从哈希表中查找数据等,该文件的粒度中等。而INPUT3.C的粒度是最细的,他是用于解析单行INPUT文件的对象内容并保存到内存中。INPUT3.C的组织结构也很简单,各个函数具有较大的相似性,分别是对INPUT文件中的不同段落数据的处理。
其中INPUT2.C文件中的unlinked()函数是检查孤立管点,这个数据检查的算法比较高效值得借鉴,该算法的巧妙之处可以参考代码中的注释:
1 int unlinked() 2 /* 3 **-------------------------------------------------------------- 4 ** Input: none ;输入:无 5 ** Output: returns error code if any unlinked junctions found ;输出:如果存在孤立点则返回错误代码 6 ** Purpose: checks for unlinked junctions in network ;目的:检查管网中的孤立点 7 ** 8 ** NOTE: unlinked tanks have no effect on computations. ;注意:没有连接的蓄水池对计算无效 9 **-------------------------------------------------------------- 10 */ 11 { 12 char *marked; 13 int i,err, errcode; 14 errcode = 0; 15 err = 0; 16 marked = (char *) calloc(Nnodes+1,sizeof(char)); //开辟连续的所有节点内存空间 17 ERRCODE(MEMCHECK(marked)); 18 if (!errcode) 19 { 20 memset(marked,0,(Nnodes+1)*sizeof(char));//给这块内存空间置0 21 for (i=1; i<=Nlinks; i++) /* Mark end nodes of each link */ 22 { 23 marked[Link[i].N1]++;//以marked的内存的逻辑地址从1、2、3...开始去一一对应管段节点在Node中的索引值,从而标记出所有被管段引用作为始末节点的索引值,而所有未标记成功的就是孤立的点。 24 marked[Link[i].N2]++; 25 } 26 for (i=1; i<=Njuncs; i++) /* Check each junction */ 27 { 28 if (marked[i] == 0) /* If not marked then error */ 29 { 30 err++; 31 sprintf(Msg,ERR233,Node[i].ID); 32 writeline(Msg); 33 } 34 if (err >= MAXERRS) break; 35 } 36 if (err > 0) errcode = 200; 37 } 38 free(marked); 39 return(errcode); 40 } /* End of unlinked */
在INPUT1.C这个文件中,我们重点看下getdata(),就知道了它的功能:
1 int getdata() 2 /* 3 **---------------------------------------------------------------- 4 ** Input: none ;输入:无 5 ** Output: returns error code ;输出:错误编号(大于100表示严重错误) 6 ** Purpose: reads in network data from disk file;作用:从磁盘文件(*.inp)中读入管网模型数据 7 **---------------------------------------------------------------- 8 */ 9 { 10 int errcode = 0; 11 setdefaults(); /* Assign default data values ;给vars.h中的部分全局变量赋值*/ 12 initreport(); /* Initialize reporting options ;初始化报表选项*/ 13 rewind(InFile); /* Rewind input file ;将INPUT文件的指针指向文件的开始*/ 14 ERRCODE(readdata()); /* Read in network data ;读取整个管网数据,该部分的具体实现是依赖INPUT2.C与INPUT3.C*/ 15 if (!errcode) adjustdata(); /* Adjust data for default values ;调整数据的默认值,当INPUT文件对部分关键参数缺少描述时,这里将重新赋值*/ 16 if (!errcode) initunits(); /* Initialize units on input data ;确定单位转换因子,EPANET中的单位体系就2种,一种是英美制US,一种是米制,根据确定的单位体系,来设置各节点、管段等的字段的转换参数*/ 17 ERRCODE(inittanks()); /* Initialize tank volumes ;初始化水库的容积*/ 18 if (!errcode) convertunits(); /* Convert units on input data ;在进行水力解算前对管段、节点、水泵、阀门的相关字段的单位数据进行转换*/ 19 return(errcode); 20 } /* End of getdata */