未知题型

阅读以下说明及Visual Basic程序代码,将应填入(n)处的字句写在对应栏内。
[说明]
我国现行使用的公民身份证号码有两种,分别遵循两个国家标准:〖GB 11643-1989〗和〖GB 11643-1999〗。〖CB 11643-1989〗中规定的是15位身份证号码,排列顺序从左至右依次为:六位数字地址码,六位数字出生日期码,三位数字顺序码,其中出生日期码不包含世纪数。〖GB 11643 -1999〗中规定的是18位身份证号码,是特征组合码,它由十七位数字本体码和一位数字校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位校验码。其中,校验码C由本体码按如下过程求得:
(1)计算校验码和S=a18W18+a17W17+…+a2W2,其中i表示18位身份证号,码每一位的序号,从右至左,最左侧为18,最右侧为1;ai表示身份证号码第i位上的号码;wi表示第i位上的权值,其值为2i-1模11的结果;
(2)计算校验码值R,其值为校验和模11的结果;
(3)根据下面对应关系找出校验码C:

由上述计算过程可以看出,18位身份证号码中可能包含非数字的字母X(代表数字10)。下面的应用程序基于这一算法实现了身份证号码的升位查询:

在开发过程中,显示新旧两种身份证号码的文本框(TextBox)分别名为Text1和Text2,“号码升位”按钮(CommandButton)名为Command1。
代码中使用到的字符串函数及功能说明如下:
(1)Len(s):获取字符串s的长度;
(2)Left(s,1):返回字符串s左端长度为1的子串;
(3)Right(s,1):返回字符串s右端长度为1的子串;
(4)Mid(s,p,1):返回字符串s从第P个字符开始长度为1的子串。
[Visual Basic代码]
’计算18位身份证号码
Private Sub Commandl_Click()
Dim code As String
Dim S As Integer
code = Textl. Text '提取15位身份证号码
If Len(code) < > 15 Then
MsgBox 'ID 号码长度不正确,请检查!'
(1)
End If
code = Left(code, 6) + '19' + (2) (code, 9) '年份升位
S=0
For i = 18 To 2 Step -1 '计算校验码和
S = S + Clnf((3)) * (2 ^ (i - 1) Mod11)
Next i
(4) '计算校验码值
Select Case S '确定校验码
Case 0: code = code + '1'
Case 1: code = code + '0'
Case 2: code = code + 'X'
Case Else: code = code + CStr((5))
End Select
Text2. Text = code '显示18位身份证号码
End Sub

A.shangxueba.cn/images/ct_crppxm_crppxprogxvb1_00045(20093).jpg'
B.shangxueba.cn/images/ct_crppxm_crppxprogxvb2_00045(20093).jpg'
【参考答案】

(1)Exit Sub(2)Right(3)Mid(code19-i1) (4)S=S Mod 11 (5)12-S

(↓↓↓ 点击下方‘点击查看答案’看完整答案 ↓↓↓)

相关考题

未知题型 阅读以下说明和C语言函数,将应填入(n)处的字句写在对应栏内。【说明】下面一段程序从给定的数组b中找出值最小的元素,并输出该元素的数组下标、内存地址minaddr以及元素值本身。函数findmin负责在给定的数组中查找最小值,并返回最小值所在的内存地址,函数有三个参数:array是所要处理的数组;size是数组的大小;index负责从函数返回具有最大值的元素在数组中的数组下标。请填充空白,使其成为一个合乎要求的完整程序。【程序】//程序开始include<iostream.h>int *findmin(int *array, int size, int &index);void main(){/****** 变量定义部分 ***********/int b[10] = {34, 34, 23, 89, 1, 2, 13, 42, 5, 54};(1);int idx;/******* 寻找最小值 ************/minaddr = findmin(b, sizeof(b)/sizeof(int), idx);/******* 输出最小值的有关信息 ************/cout << 'Min value index: '<<idx<<end1<<'Min value address: '<<minaddr<<end1<<'Min value: '<<(2)<<end1;}/******* 函数findmin的定义部分 ************int *findmin(int *array, int size, int &index){int min = 0;//max 是当前具有最小值的数组元素下标值for(int i = 1;(3); i++){if(array[i]<(4))min = i;}(5);return array + min;//返回最小值所在内存地址}

未知题型 阅读以下说明和流程图,回答问题,并将解答填入对应栏内。【说明】求解约瑟夫环问题。算法分析:n个士兵围成一圈,给他们依次编号,班长指定从第w个士兵开始报数,报到第s个士兵出列,依次重复下去,直至所有士兵都出列。【流程图】【问题】将流程图中的(1)~(5)处补充完整。

未知题型 阅读以下说明和流程图,将应填入(n)处的字句写在对应栏内。[说明]下面的流程图用于计算一个英文句子中最长单词的长度(即单词中字母个数)MAX。假设该英文句子中只含字母、空格和句点“.”,其中句点表示结尾,空格之间连续的字母串称为单词。[流程图]

未知题型 请在“答题”菜单上选择相应的命令,完成下面的内容:接收并阅读由djks@djks.com发来的E-mail,并按E-mail中的指令完成操作。

未知题型 阅读下列C程序和程序说明,将应填入(n)处的字句写在答题纸的对应栏内。【说明】用克鲁斯卡尔算法求解给定图的最小生成树。include <stdio. h>include <stdlib. h>define MAXN 30typedef struct{ int v1,v2; /*一条边依附的两个顶点*/int weight; /*边上的权值*/}EDGE;typedef struct{ int Vnum; /*图中的顶点数目*/EDGE e[MAXN*(MAXN-1)/2]; /*图中的边*/}Graph;typedef struct node{ /*用链表存储同一个连通分量的顶点*/int v;struct node *next;}Alist;void heapadjust(EDGE data[], int s, int m){ /*将元素序列data[s..m]调整为小顶堆, 堆顶元素(最小元素)为data[s]*/int j;EDGE t;t=data[s]; /*备份元素data[s], 为其找到适当位置后再插入*/for(j=2*s+1; j<=m; j=j*2+1){/*沿值较小的子结点向下筛选*/if(j<m &&(1)) ++j;if(!(t. weight>data[j]. weight)) break;data[s]=data[j];s=j; /*用s记录待插入元素的位置(下标)*/}/*for*/data[s]=t; /*将备份元素插入由s所指出的插入位置*/}/*heapadjust*/int creat_graph(Graph *p) /*输入图中的顶点及边, 返回图中边的数目*/{ int k=0; /*记录图中边的数目*/int n;int v1,v2;int w;printf('vertex number of the graph:');scanf('%d', &n); /*输入图中的顶点数目*/if(n<1) return 0;p->Vnum=n;do{ printf('edge(vertex1,vertex2,weight):');scanf('%d %d %d', &V1, &v2, &w);if(v1>=0 && v1<n && v2>=0 && v2<n){p->e[k]. v1=v1; p->e[k]. v2=v2; p->e[k]. weight=w;k++;}/*if*/}while(!( (2) ));return k; /*返回图中边的数目*/}/*creat_graph*/int kruskal(Graph G, int enumber, int tree[][3]){ /*用kruskal算法求无向连通图G的最小生成树, 图中边所得数目为enumber, *//*数组tree[][3]中存放生成树中边的顶点和边上的权值, 函数返回生成树的代价*/int i, k, m, c=0;int v1, v2;Alist *p, *q, *a[MAXN];for(i=0; i<G.Vnum; ++i){ /*将每个连通分量中的顶点存放在一个单链表中*/a[i]=(Alist*)malloc(sizeof(Alist));if(!a[i]) {printf('/n mernory allocation error!');exit(0);}/*if*/a[i]->v=i; a[i]->next=NULL;}/*for*/for(i=enumber-1; i>=0; --i)/*按照边上的权值建立小顶堆*/heapadjust( (3) );k=G. Vnum; /*k用于计算图中的连通分量数目*/m=enumber-1;i=0;do{v1=G. e[0]. v1; v2=G. e[0]. v2;p=a[v1];while(p && p->v!=v2){ /*判断当前选择的边的顶点是否在一个连通分量中*/q=p; p=p->next;}if(!p){ /*当前边的顶点不在一个连通分量中*/p=q;p->next=a[G. e[0]. v2];&nb

未知题型 在“客人”表中添加如下数据。(2)将客人表的客人ID列隐藏,名字字段移动至最前,设置数据表按照“名字”和“性别”字段列升序排列。(3)将“城市”表的单元格效果设置为“凸起”。“城市”表如图所示。

未知题型 阅读以下说明和JAVA2代码,将应填入(n)处的字句写在对应栏内。【说明】以下程序实现了利用鼠标任意移动该圆形的位置,仔细阅读代码和相关注释,将程序补充完整。【代码6】import java.awt.*;import java.awt.event.*;public class CIUSAMPLE extends Frame. implements MouseMotionListener, MouseListener{static CIUSAMPLE frm=new CIUSAMPLE ();int x=70,y=60,posX=70,posY=60,dx,dy;public static void main ( String args[]){frm.setTitle ('Dragging a circle');frm.setSize ( 200,150 );(1)frm.addMouseMotionListener ( frm );frm. setVisible ( true );}public void mousePressed ( MouseEvent e ){(2)dy=e.getY () -posY;}public void mouseDragged ( MouseEvent e ){(3)y=e.getY () -dy;if ( dx>0 && dx<50 && dy>0 && dy<50 ) //如果指我落在正方形区域内{Graphics g=getGraphics ();(4)}}public void paint ( Graphics g ){g.setColor ( Color. pink ); // 设置绘图颜色为粉红g.fillOval ( x,y,50,50 ); //以基准点为图形的左上角绘出圆形(5)posY=y;}public void mouseMoved ( MouseEvent e ) { }public void mouseReleased ( MouseEvent e ) { }public void mouseEntered ( MouseEvent e ) { }public void mouseExited ( MouseEvent e ) { }public void mouseClicked ( MouseEvent e ) { }}

未知题型 完成下面的程序,使显示结果如下图所示。Private Sub Form_Click()FontSize=18Sample$s='【 】'x=(ScaleWidth-TextWidth(Sample$))/2y=(ScaleHeight-TextHeight(Sample$))/2CurrentX=xCurrentY=y【 】Sample$End Sub

未知题型 在考生文件夹下TEACHER文件夹中创建名为BSP.TXT的文件,并将属性设置为隐藏和存档。

未知题型 阅读以下关于网页制作和网页编程的说明,根据要求回答问题。[说明]某企业制作了一个电子商务网站,图7-10是网站向消费者收集反馈信息的反馈表。用户在填写反馈表时,需要正确地输入自己的相关信息,并且弹出提示信息,否则不能够提交成功。该功能通过调用外部JavaScript脚本checkinput.js文件实现。系统的数据库名为shangwu01,所在服务器IP地址为 123.254.198.67。以下给出的是提交按钮触发过程的部分代码,请根据图7-10所示内容填写下述HTML代码中空缺的部分。

未知题型 下面程序的输出结果是【】。char b[]='ABCD';main(){char b[30];strcpy(&b[0],'GH');strcpy(&am

未知题型 阅读以下说明,回答问题1~7。【说明】在IMail管理器中,选中MailUser邮件主机,然后在它右边的面板中选中'General'选项卡,出现一个邮件配置窗口,如图2-3所示。如果在IMail管理器中,选中User1用户,然后在它右边的面板中选中'General'选项卡,则会出现另外一个邮件配置窗口,如图2-4所示。限制MailUser邮件主机里每个用户的邮箱大小不超过10MB,如何配置?

未知题型 阅读以下说明和关系表,回答问题1~5,将解答填入对应的解答栏内。[说明]试用SQL查询语句表达下列对教学数据库中的3个基本表STUDENT,COURSE,SC的查询[关系表]查询全体学生的姓名和年龄。

未知题型 在考生文件夹下打开文档WDAl91.DOC,按照要求完成下列操作。1) 将文中所有错词“国书”替换为“果树”;将标题段“果树与谎话”设置为小二号蓝色空心宋体、加波浪线、居中、字符间距加宽2磅。2) 将正文各段文字“美国首任总统……一句谎话。”设置为小四号楷体_GB2312;各段落首行缩进0.85厘米、行距设置为16磅、段前间距0.5行。3) 设置正文各段落首字下沉2行、距正文0.1厘米:设置页面左右边距各为3.1厘米:在页面底端(页脚)居中位置插入页码;以原文件名保存文档。2.考生文件夹下打开文档WDA192.DOC,按照要求完成下列操作。1) 将表题段(“常用串行接口比较”)设置为五号宋体、倾斜、居中;将表格后7行转换为一个7行4列表格、表格居中;设置表格列宽为3厘米、行高0.6厘米,表格中的所有内容设置为小五号宋体且水平、垂直居中。2) 设置外框线为1.5磅双窄线、内框线为0.75磅单实线;并按“负载能力”列降序排列表格。以原文件名保存文档。文件WDA191.DOC内容如下:【文档开始】国书与谎话美国首任总统乔治&8226;华盛顿家里有许多国书,国书中还夹杂一些杂树,为让国书生长茂盛,应该将杂树除掉。一天,华盛顿给儿子一把斧头要他去砍伐杂树,他叮嘱儿子不能误砍一棵国书。然而一不小心,儿子误砍了一棵国书。前来检查的华盛顿得知后,来到正在继续砍杂树得儿子身边,故意问儿子:“没砍掉国书吧,孩子?”听了父亲得问话,儿子认真诚恳地对父亲说:“怪我粗心,砍掉了一棵国书!”儿子的诚实,令华盛顿感到莫大的欣慰。他用鼓励的口吻对儿子说:“好!你砍掉苹国书该批评,但你不说谎,我就原谅你了。因为,我宁可损失所有的国书,也不愿听到你说一句谎话。”【文档结束】文件WDA192.DOC内容如下:【文档开始】常用串行接口比较接口 格式 负载能力 速率(bit/s)USB 异步串行 127 1.5M/12M/40MRS-232 异步串行 2 115.2KRS-485 异步串行 32 10MIrDA 红外异步串行 2 115.2KIEEE-1394 串行 64 400M以太网 串行 1024 10M/100M/1G【文档结束】

未知题型 除了上述/etc/ftpaccess配置文件外,WU-FTP还有其他几个配置文件,其中:(1)文件的作用是指定某些用户登录不能登录本FTP服务器。(2)文件的作用是指定某些主机不能连接本FTP服务器。(3)文件的作用是定义用户从FTP服务器中下载文件时对文件进行格式转换的规则,如压缩、解压缩、打包和开包等操作。(1)

未知题型 对内存单元中连续存放的20个ASCII字符进行转换,大写的“A—Z”转换成小写,小写的“a-z”转换成大写,其他字符变为00,结果存放在RESULT开始的内存单元中。部分程序已经在PROG1.ASM中给出,请编写BEGIN到END之间代码。原有数据由过程LOAD从文件INPUT1.DAT中读入SOURCE开始的内存单元中,结果要求从RESULT开始存放,由SAVE保存到OUTPUT1.DAT文件。对程序必须进行汇编,并与10.OBJ连接产生PROG1.EXE执行文件,最终产生运行结果(无结果或结果不正确均不得分)。部分源程序如下:EXTRN LOAD:FAR,SAVE:FARN EQU 20STAC SEGMENT STACKDB 128DUP(?)STAC ENDSDATA SEGMENTSOURCE DB N DUP(?)RESULT DB N DUP(0)NAME0 DB 'INPUT1.DAT', 0NAME1 DB 'OUTPUT1.DAT', 0DATA ENDSCODE SEGMENTASSUME CS:CODE,DS:DATA,SS:STACSTART PROC FARPUSH DSXOR AX,AXPUSH AXMOV AX,DATAMOV DS,AXMOV ES,AXLEA DX,SOURCE ;数据区起始地址LEA SI,NAMED ;原始数据文件名MOV CX,N ;字节数CALL LOAD ;从'IArPUT1.DAT'中读取数据****BEGIN*********END*****LEA DX,RESULT ;结果数据区首地址LEA SI,NAME1 ;结果文件名MOV CX,N ;结果字节数CALL SAVE ;保存结果到文件RETSTART ENDPCODE ENDSEND START相关知识:●定义符号伪指令指令功能:给一个表达式分配一个符号名或给一个符号分配一个值。指令格式:(i)符号EQU表达式(不允许符号重定义)(ii)符号=表达式(允许符号重定义)●数据定义伪指令指令格式:(i)[名字]DB操作数1[,操作数2[,...]](为每个操作数分配1个字节的空间)(ii)[名字]DW操作数1[,操作数2[,...]](为每个操作数分配2个字节的空间)(iii)[名字]DD操作数1[,操作数2[,...))(为每个操作数分配4个字节的空间)(iV[名字]DQ操作数1[,操作数2[,...]](为每个操作数分配8个字节的空间)(v)[名字]DT操作数1[,操作数2[,...]](为每个操作数分配10个字节的空间)●段定义伪指令指令格式:段名 SEGMENT [定位方式] [联系方式] ['类别')使用段定义伪指令可以将程序和有关的数据信息定义在相应的段中。●循环的实现通过设置计数器初值,在完成一组操作后,修改计数器中的值,重新执行操作直到计数器中的值为0。例如:MOV CX,NLI:┆LOOP L1(短标号地址)或:DEC CXJNZ 11(短标号地址)注意:本书学习要点讲过的内容,本章节不予赘述。●字符的ASCII码十六进制数“0”~“F”是连续的,它们的ASCII码不是连续的,但仍然有规律可循,“0”~“9”的ASCII码为30H~39H,“A”~“F”的ASCII码为41H~46H,“A”~“Z”的ASCII是从41H开始连续的,“a”~“z”的ASCII是从61H开始连续的。编程方法:第一步:分析程序要求的功能。本程序要求完成以下功能:(1)从数据文件INPUT1.DAT中读取20个8位无符号整数存放在SOURCE开始的内存单元中。(2)将SOURCE开始的20个ASCII码进行判断,处理,并将结果存放在RESULT开始的内存单元中。(3)将处理结果存放在0UWUT1.DAT文件第二步:用相应的汇编程序来实现其功能。(1)数据的读取和存人文件部分的实现,题目中已经给出。(2)大小写判断转换处理,我们可根据英文大写字母“A~Z”和小写字母“a~z”的 ASCII码是连续的,并且同字母的大小写的ASCII码相差20H,可以直接在其ASCII码上加减20H进行大小写的转换。处理过程就是,从数组中取来一个元素,先判断它是否是大写,若为大写,则直接减 20H变为小写;否则判断它是否为小写,若为小写,直接减20H变为大写;若大小写均不是,就赋值为0。重复操作所有的元素。

未知题型 阅读以下说明和流程图,从供选择的答案中选出应填入流程图(n)处的字句写在对应栏内。[说明]以下是某图像二元树存储与还原算法的主要思想描述。设一幅2n×2n的二值图像,以:“1”表示黑像素点,以“0”表示白像素点。图像二元树结构表示依赖于图像的二元分割,即交替在X轴方向和Y轴方向上分割。先进行水平分割,分成两个2n-1×2n图像子块,然后进行垂直分割,分成4个2n-1×2n-1的正方形块,如此分割,直到子块只含同一像素点为止。如图8-8为一“E”字的二值图像,对其进行二元分割,相应的二元树如图8-9所示。根据图像二元树的0叶结点和1叶结点的数目,删除多者,保留少者。如“E”字图像的二元树0叶结点较多,裁剪后如图8-10所示。裁剪后图像二元树有4类结点,分别用二进制编码如下:◆ 左右儿子都有的结点,编码为11;◆ 仅有左儿子的结点,编码为10;◆ 仅有右儿子的结点,编码为01;◆ 叶结点,编码为00。存储时,先存储剩余叶结点的类型编码,二进制码00表示0叶结点,11表示1叶结点。再按层次顺序,自左至右存储裁剪后图像二元树各结点的编码。图像二元树的存储算法用C语言描述所定义的数据结构及函数如下:struct Node{ /*图像二元树结点*/street Node*Left;street Node*Righ t;char Pixel;}struct Node Queue[MaxLen]; /*队列*/InitQueue() /*初始化队列Queue的函数; */EmptyQueue () /*判断队列Queue是否为空的数,若空返回1,否则返回0; */AddQueue(Item) /*将Item加到队列Queue的数; */GetQueue() /*取队列Queue第一个元素的函数; */PutCode(Code) /*写2位二进制码Code到文件的函数*/还原算法是存储算法的逆过程,将文件中的二进制码序列转换成图像二元树。还原算法的数据结构与函数与存储算法的相同,还原算法新增了一个函数GetCode ()。GetCode() /*从文件中读2位二进制码的函数*/[C程序]存储算法void Backup (char CutPixel,st ruct Node ImageTree)'/*Cu tP ixel=0表示裁剪0叶结点*/{ InitQueue();AddQueue ( ImageTree ) ;PutCode ( 1-CutPixel ) ;While ( !EmptyQueue ( ) ){ TreeNode= GetQueue ( ) ;if (TreeNode→Left==NULL){ PutCode (0) ;continue:}Tl= TreeNode→Left;Tr= TreeNode→R igh t;if ( Tl→Left= = NULL && Tl→Pixel= = CutPixel )L=0;else{(1);AddQueue ( Tl ) ;}if ( Tr→Left= = NULL && Tr→Pixel= = CutPixel )R=0;else{(2)AddQueue (T) ;}(3)}}还原算法void Restore ( struct Node *TreeRoot ){ TreeRoot= ( strut Node*)malloc ( sizeof (struct Node)InitQueue ( );AddQueue ( TreeRoot ) ;CutPixel= 1- GetCode ( ) ;while ( ! EmptyQueue ( ) ){ TrecNode= GetQueue ( Queue ) ;NodeCode= GetCode ( ) ;switch ( NodeCode ){case 0:TreeNode→Left = NULL ;TreeNode→Right= NULL&

未知题型 阅读以下说明和流程图8-11,完成程序(n)处的语句写在对应栏内。[说明]对于数学上一个猜想:任何自然数平方的36倍等于两对孪生素数的和。初始的情形如下:12×36=(5+7)+(11+13)22×36=(29+31)+(41+43)32×36=(11+13)+(149+151)再往下,N取4,5,6,时,只要N不太大,也都可以找到N(上标)2×36等于两对孪生素数的和。但是当N是一个任意的正整数时,证明N2×36总是等于两对孪生素数的和,这还是一个目前尚未解决的问题。甚至当考察的数较大时,找出一组符合条件的两对孪生素数都是计算量相当大的工作。每尝试一次,都要作4次是否是素数的判断,要作许多次的尝试,才可能找到一组解。下面流程图设计了一种优化算法来对这个猜想进行验证。仔细阅读流程图8-11,完成程序部分。[程序部分]main (){int t, i, j, prime_index; is_p rime:long n, p, p1, p2, p3, p4, s, s1;long primes [ 16000 ];for (n=1; n<98; ++n){t=0;s= n* n* 36;prime_index= 2;primes[0]=2; primes[1]=3;for (p=5: p<=s/2; p=p+2){is_p rime= 1;for ( i=1;(1)++i)if ( p%primes [i] = = 0 ) is_p rime= 0;if ( is_p rime){(2)}}for ( i=1; (3)++i){(4)if ( p2=p1+ 2 ){s1=s- (p1+p2)p3=sl/2-1; p4=p3+2:for ( j=0; j<=prime_index-1; ++j )if ((5)){printf ( '%d* % d*36= (%d+ %d) + (%d+%d) /n', / n,n, p1, p2, p3, p4 ) ;++t;}}}if ( t! = 0 ) printf ('%d/n', t )elseprintf ( '%d* %d*36=no so lution/n ', n, n ) ; }}}

未知题型 阅读以下关于FTTC宽带接入Internet的技术说明,根据要求回答问题1至问题5。【说明】光纤接入网(Optical Access Network,OAN)是以光纤为传输媒体,并利用光波作为光载波传送信号的接入网。FTTC+LAN是实现居民宽带接入Internet的常用方案之一,基本结构如图3-6所示。光接入网(OAN)由ONU、ODN和OLT等三大部分组成。请将以下所提供的网络设备的序号填写到如图3-6所示的网络结构图中(1)~(5)空缺处对应的位置。【供选择的设备】①ONU ②OLT ③光分路器 ④光收发器 ⑤交换机

未知题型 阅读下列程序说明和C代码,将应填人(n)处的字句写在对应栏内。[程序5说明]下列文法可用来描述化学分子式的书写规则(例如,A12(CO3)3”Cu(OH)2):λ→β/βλβ→δ/δnδ→ξ/ξθ/(λ)其中:λ是—个分子式;δ或是一个元素,或是一个带括号的(子)分子式,元素或是一个大写字母(记为ξ),或是一个大写字母和一个小写字母(记为ξθ)β或是一个δ,或是在δ之后接上一个整数n,δn表示β有n个δ的元素或(子)分子式。—个完整的分子式由若干个β组成。当然一个正确的分子式除符合上述文法规则外,还应满足分子式本身的语义要求。下面的程序输入分子式,按上述文法分析分子式,并计算出该分子式的分子量。例如:元素H的原子量是1,元素O的原子量是16。输入分子式H2O,程序计算出它的分子量为18 (1×2+16)。程序中各元素的名及它的原子量从文件atom.dat中读入。[程序5]include < stdio. h >include < string. h >define MAXN 300define GMLEN 30struct elem { char name[ ]; /* 元素名*/double v;/*原子量*/} nTbl [MAXN];char cmStr [GMLEN], * pos;int c;FILE * fp;double factor( );double atom( ) /* 处理文法符号δ*/{char w [3];int i; double num;while((c = * pos++) =='||c =='/t'); /*略过空白字符*/if(c == '/n') return 0.0;if(c>='A' && C <='Z') {/*将元素名存入W */w[i =0]=c;c= * pos ++if(c >='a'&& c <='z')w[ ++i] =c;else pos--;w[ ++i] ='/0',for(i =0;nTbl [i]. v >0.0;i ++)if(strcmp (w,nTbl[i]. name) ==0) return nTbl [i]. v;printf (' /n元素表中没有所输入的无素: /t%s/n',w); retur n - 1.0;} elseif (c = ='(') {if((num=(1)) <0.0)return -l.0; /*包括可能为空的情况*/if( * pos ++ ! = ')') { printf (' 分子式中括号不匹配!/n') ;return - 1.0; }return num;}printf ('分子式中存在非法字符:/t%c/n' ,c);return - 1.0;}double mAtom( ) /* 处理文法符号β*/{ double num ;int n = ];if((num=(2)) <0.0)return-l.0;c= *pos++;if(c >='O'&&c <='9') {n = 0; while(c > = 0&&c < ='9'){n=(3);c= *poss ++;}}pos --;return num * n;}double factor( ) /*处理文法符号λ*/{ double num =0.0,d;if(( hum = mAtom ( )) < 0.0) return - 1.0;while( * pos >= 'A'&& * pos <= 'Z'||* pos == '(') {if((d=(4)) <0.0)return-1.0;(5);} return num;void main( ){ char fname[ ] ='atom. dst'; /*元素名及其原子量文件*/int i;double num;if((fp=fopon(fname,'r' )) == NULL) { /*以读方式打开正文文件*/prinff('Can net open%s file. /n' ,fname) ;return /*程序非正常结束 */i=0;while(i < MAXN&&fscanf (fp,' %s%lf,bTbl[i]. name,&nTbl[i]. v) ==2)i++;fclose(fp) ;nTbl[i]. v =-1.0;while(1) [/*输入分子式和计算分子量循环,直至输入空行结束*/printf(' /n 输入分子式! (空行结束) /n' ) ;gets(cmStr);pos = cmStr;if(cmStr[0] == '/0') break;if( (num = later( ) ) > 0.0)if( * pos! = '/0')printf('分子式不完整! /n' );else printf('分子式的分子量为%f/n',num);}