1、覆盖率(白盒)测试(一)及答案解析(总分:84.00,做题时间:90 分钟)一、选择题(总题数:18,分数:54.00)1.程序的流程图如下图所示,采用路径覆盖法进行测试,则至少需要几个测试用例可以覆盖所有可能的路径_。(分数:3.00)A.B.C.D.2.下列逻辑覆盖测试中,最强的是_。(分数:3.00)A.语句覆盖B.条件覆盖C.路径覆盖D.条件组合覆盖3.设有一段程序如下:if(a=b) and (c=d) or (e=f) do S1else if(p=q) or (s=t)do S2else do S3满足判定/条件覆盖的要求下,最少的测试用例数目是_。(分数:3.00)A.6B.8
2、C.3D.44.关于逻辑覆盖,说法错误的是_。(分数:3.00)A.DDP 覆盖是判定覆盖的一个变体B.满足条件覆盖一定也满足判定覆盖C.指令块覆盖属于语句覆盖D.若判定覆盖率达 100%,则语句覆盖率一定也是 100%5.下列属于变量异常的是_。(分数:3.00)A.变量被定义,但没有被使用B.所使用的变量未被定义C.变量在使用前被重复定义D.以上全部6.如果一个判定巾的复合条件表达式为(A1)or(B3),则为了达到 100%的条件覆盖率,至少需要设计多少个测试用例_。(分数:3.00)A.1B.2C.3D.47.对于具有串联型分支结构的程序,若有 4 个判定语句,则采用正交实验设计法,至
3、少需要的测试用例数应为_。(分数:3.00)A.4 个B.16 个C.8 个D.5 个8.下列指导选择和使用测试覆盖率的原则中错误的是_。(分数:3.00)A.覆盖率不是目的,仅是一种手段B.不要追求绝对 100%的覆盖率C.不可能针对所有的覆盖率指标来选择测试用例D.只根据测试覆盖率指标来指导测试用例的设计9.数据流覆盖关注的是程序中某个变量从其声明、赋值到引用的变化情况,它是下列哪一种覆盖的变种_。(分数:3.00)A.语句覆盖B.控制覆盖C.分支覆盖D.路径覆盖10.程序的流程图如下图所示,采用路径覆盖法进行测试,则至少需要几个测试用例可以覆盖所有可能的路径_。(分数:3.00)A.B.
4、C.D.11.对于一个嵌套型分支结构的程序,若有 4 个判定语句则要覆盖它的每一条路径至少需要的测试用例数为_。(分数:3.00)A.4 个B.3 个C.5 个D.6 个12.下图是一个判定路径覆盖图,其中用“ ”表示判定语句,用“ ”表示处理语句,用“”表示判定汇合点,用“”表示判定路径,若有一个测试用例覆盖了判定路径 A、B、E、H,则判定路径覆盖率为(分数:3.00)A.B.C.D.13.下列语句通常不是作为定义结点的是_。(分数:3.00)A.输入语句B.输出语句C.赋值语句D.过程调用语句14.关于数据流测试,说法正确的是_。(分数:3.00)A.数据流测试是一种路径测试B.执行定义
5、结点不会改变变量在存储单元中的内容C.执行使用结点会改变变量在存储单元中的内容D.定义/使用路径往往不是存在潜在错误的地方15.如果程序通过了 100%的代码覆盖率测试,则说明程序满足了_。(分数:3.00)A.语句覆盖B.编程规范C.设计规格D.功能需求16.下面有关逻辑覆盖的说法中错误的是_。(分数:3.00)A.DDP 覆盖是判定覆盖的一个变体B.满足条件覆盖一定也满足判定覆盖C.指令块覆盖属于语句覆盖D.若判定覆盖率达到 100%,则语句覆盖率一定也达到 100%17.如果程序中有两个判定条件,其复合条件表达式分别为(a=3) and (b=6)和(a0) or (c2),则为了达到
6、100%的判定覆盖率,至少需要没计的测试用例个数为_。(分数:3.00)A.1B.2C.3D.418.对于具有串联型分支结构的程序,如果有七个判断语句串联,则使用正交实验设计法,至少需要的测试用例数应为_。(分数:3.00)A.23B.24C.25D.27二、论述题(总题数:8,分数:30.00)已知 C 源程序如下:/*Input todays date,output tomorrows date*/*version 2*/#includestdio.hstruct ydateint day;int month;int year;int leap(struct ydate d)if(d.ye
7、ar%4=0elsereturn 0;int numdays(struct ydate d)int day;static int daytab=31,28,31,30,31,30,31,31,30,31,30,31);if(leap(d)elseday=daytabd.month-1;return day;int main(void)struct ydate today,tomorrow;printf(“format of date is:year,month,day 输入的年、月、日之间应用逗号隔开/n“);printf(“today is:“);scanf(“%d,%d,%d“,while
8、(0=today.year| today.year65535 | 0=today.month | today.month12) |0=today.day | today.daynumdays(today)printf(“input date error!reenter the day!/n“);printf(“today is:“);scanf(“%d,%d,%d“,if(today.day!=numdays(today)tomorrow.year=today.year;tomorrow.month=today.month;tomorrow.day=today.day+1;else if(to
9、day.month=12)tomorrow.year=today.year+1;tomorrow.month=1;tomorrow.day=1;elsetomorrow.year=today.year;tomorrow.month=today.month+1;tomorrow.day=1;printf(“tomorrow is:%d,%d,%d/n/“,tomorrow.year,tomorrow.month,tomorrow.day);(分数:4.00)(1).画出程序中所有函数的控制流程图;(分数:2.00)_(2).设计一组测试用例,使该程序所有函数的语句覆盖率和分支覆盖率均能达到 10
10、0%。如果认为该程序的语句或分支覆盖率无法达到 100%需说明为什么。(分数:2.00)_已知 C 源程序如下:/*A simple mailing list example using an array of structures. */# includestdion.h# includestdlib.hdefine MAX 4struct addrchar name30;char street40;char city20;unsigned long int zip;addr_listMAX;void init_list(void),enter(void);void deleteAddr(v
11、oid),list(void);int menu_select(void),find_free(void);int main(void)char choice;init_list();/*initialize the structure array*/for(;)choice=menu_select();switch(choice)case 1:enter();break;case 2:deleteAddr();break;case 3:list();break;case 4:exit(0);return 0;/*Initialize the list.*/void initlist(void
12、)register int t;for(t=0;tMAX; +t)addr_listt, name0=/0;/*Get a menu selection. */int menu_select(void)char s80. ;int c;printf(“1Enter a name/n“);printf(“2Delete a name/n“);printf(“3List the file/n“);printf (“4Quit/“)doprintf(“/nEnter your choice:“);gets(s);c= atoi(s);while(c1 | c4);return c;/*Input a
13、ddresses into the list. */void enter(void)int slot;char s80;slot=find_free();if(slot=-1)printf(“/nList Full“);return;printf(“Enter name:“);gets(addr_listslot.name);printf(“Enter street:“);gets(addr_listslot.street);printf(“Enter city:“);gets(addr listslot.city);printf(“Enter zip:“);gets(s);addr_list
14、slot.zip=strtoul(s,/0,10);/*Find an unused structure. */int find_free(void)register int t;for(t=0; addr_listt. name0 +t);if(t=MAX)return-1; /*no slots free*/return t;/*Delete an address. */void deleteAddr(void)register int slot;char s80;printf(“enter record#: “);gets(s);slot=atoi(s);if(slot=0 /*Disp
15、lay the list on the screen. */void list(void)register int t;for(t=0; tMAX; +t)if(addr_listt. name0)printf(“%s/n“, addr_listt. name);printf(“%s/n“, addr_listt. street);printf(“%s/n“,addr_listt. city);printf(“%lu/n/n“, addr_listt. zip);printf(“/n/n“);(分数:4.00)(1).画出 main 函数的控制流程图;(分数:2.00)_(2).设计一组测试用
16、例,使该程序所有函数的语句覆盖率尽量达到 100%。如果认为该程序的语句覆盖率无法达到 100%,需说明原因。(分数:2.00)_针对以下 C 语言程序,请按要求回答问题。已知 link. c 源程序如下:/*link. c 程序对单向链表进行操作,首先建立一个单向链表,然后根据用户的选择可以对其进行插入结点、删除结点和链表反转操作*/#includestdio.h#includestdlib.htypedef struct list_node*list_pointer; /定义链表指针typedef struct list_node /定义链表结构int data;list_pointer
17、link; list_node;/用到的操作函数list_pointer create(); /建立一个单向链表void insert(list_pointer*p_ptr, list_pointer node);/在 node 后加入一个新的结点void delete_node(list_pointer*p_ptr, list_pointer trail, list_pointer node);/删除前一个结点是 trail 的当前结点 nodevoid print(list_pointer*p_ptr); /打印链表结点中的值list_pointer invert(list_pointer
18、 lead); /反转链表int main()list_pointer ptr=NULL;list_pointer node, trail;list_pointer * p=int choose, location, i;printf(“you should create a link first:/n“);prt=create(); /*ptr 指向链表的第一个结点*/print(ptr);/根据用户的不同选择进行相应的操作;printf(“input number 0, you can quit the program/n“);printf(“input number 1, you can
19、 insert a new node to link/n“);printf(“input number 2, you can delete a node from the linkkn“);printf(“input number 3, you can invert the link/n“);printf(“please input you choicekn“);scanf(“ %d“, while(ilocation)node=node-link;i+;insert(p,node); /*p 为指向 ptr 的指针*/print(ptr);break;case 2:printf(“you w
20、ill delete a node from the link/n“);printf(“please input the location of the node:/n“);scanf(“%d“, node=ptr;if(location=1)trail=NULL;trail=ptr;i=1;whileilocation)trail=trail-link;i+;node=trail-link;delete_node(p, trail, node);print(ptr);break;case 3:printf(“you will invert the link/n“);ptr=invert (p
21、tr)print(ptr);break;default :breakreturn -1:printf(“please input you choice/n“);scanf(“%d“,return 0;/根据用户的输入值建立一个新的单向链表:list_pointer create()int i, current, length;list_pointer p1, p2, head;printf(“please input the node number of the link:/n“);scanf(“%d“, printf(“the number of the link is: %d“, leng
22、th);printf(“please input the data for the link node: /n“);i=0;p1=p2=(list_pointer)malloc(sizeof(list_node);head=p1;for(i=1; ilength; i+)scanf(“%d“, p1-data=current;p2-link=p1;p2=p1;p1=(list_pointer)malloc(sizeof(list_node);p2-link=NULL;return head;(分数:4.00)(1).画出主函数 main 的控制流程图。(分数:2.00)_(2).设计一组测试用
23、例,尽量使 main 函数的语句覆盖率能达到 100%。如果认为该函数的语句覆盖率无法达到 100%,需要说明原因。(分数:2.00)_考虑一个根据以下简单规格确认输入数有效性的应用程序:(1)输入数由数字、符号“+”或“-”开始。(2)该数字或符号后面可接任意位数的数字。(3)这些数字可以有选择地后接用英文句号表示的小数点。(4)任何输入数,不管是否有小数点,都应该以空格结束。请根据以上处理规则:(分数:6.00)(1).画出相应的状态转换图。(分数:2.00)_(2).根据状态转换图,列出相应的状态转换表,给出“当前状态”、当前状态允许的“输入”和对应每一个输入下的“下一个状态”。(分数:
24、2.00)_(3).根据状态转换图和状态转换表,导出基本路径测试的测试用例及其覆盖的测试路径。(分数:2.00)_下图为对 4 个已知数字进行排序的程序流程图。(分数:4.00)(1).计算它的环路复杂度。(分数:2.00)_(2).为完成基本路径测试,求它的一组独立路径。(分数:2.00)_19.用基本路径测试法为下列程序设计测试用例。1 Void sort(int iRecordNum, int itype)2 3 int x=0; y=0;4 while(iRecordNtum0)5 6 if(itype=0)7 x=y+2; break; )8 else9 if (itype=1)10
25、 x=y+10;11 else12 x=y+20; 13 14 15 (分数:2.00)_20.用基本路径测试法说明以下 C 程序的用例设计过程。void selectSort(int V, int n)for(int i=0; in-1; i+)int k=i; for(int j=i+1; jn; j+)if(Vjvk)k=j; if(k!=i)int work=Vi; Vi=vk; Vk=work; (分数:2.00)_已知 C 源程序如下:#includestdio.h#includestring.hvoid reverse(char s)int C, i, J;for(i=0, j=
26、strlen(s)-1; ij; i+, j+)c=si; si=sj; sj=c; void getHex(int number, char s)int I; i=0; while(number0)if(number%1610)si+=number%16+0; elseswitch(number%16)case 10: si+=A; break; case 11: si+=B; break; case 12: si+=C; break; case 13: si+=D; break; case 14: si+=E; break; case 15: si+=;F; break; default:
27、 printf(“Error“); break; number/=16; si=/0; reverse(S); int main()unsigned int nmnber; int i=0; char s50; printf(“%s“, “please input number: /n“); scanf(“%d“, getHex(number, s); i=0; while(si)printf(“%c“, si+); return 0; (分数:4.00)(1).画出程序中所有函数的控制流程图;(分数:2.00)_(2).设计一组测试用例,使该程序所有函数的语句覆盖率和分支覆盖率均能达到 10
28、0%。如果认为该程序的语句覆盖率或分支率无法达到 100%,需说明为什么。(分数:2.00)_覆盖率(白盒)测试(一)答案解析(总分:84.00,做题时间:90 分钟)一、选择题(总题数:18,分数:54.00)1.程序的流程图如下图所示,采用路径覆盖法进行测试,则至少需要几个测试用例可以覆盖所有可能的路径_。(分数:3.00)A. B.C.D.解析:解析 上图是表示 3 个顺序执行的分支结构,即采用结构化分解的方法,可以把程序流程图分为3 层,最上面一层有 3 个判定结点,由上面例子可知该层的测试用例数至少为 4,同样,中间一层仅有一个判定结点,故测试用例数至少需要 2 个,最下面一层判定结
29、点数为 2,故至少需要 3 个,综合上面可以得到预完成整个程序的测试,至少需要 423=24 个测试用例才可以覆盖所有路径。2.下列逻辑覆盖测试中,最强的是_。(分数:3.00)A.语句覆盖B.条件覆盖C.路径覆盖 D.条件组合覆盖解析:解析 逻辑覆盖是以程序内部的逻辑结构为基础的设汁测试用例的技术,属于白盒测试。由于覆盖率的不同,又可以分为语句覆盖、判定覆盖、条件覆盖、判定/条件覆盖、条件组合覆盖和路径覆盖。其中最强的是路径覆盖,即测试用例能够执行程序中所有的路径;最弱的是语句覆盖,即设计的测试用例使得程序中每一可执行语句至少执行一次。3.设有一段程序如下:if(a=b) and (c=d)
30、 or (e=f) do S1else if(p=q) or (s=t)do S2else do S3满足判定/条件覆盖的要求下,最少的测试用例数目是_。(分数:3.00)A.6B.8C.3 D.4解析:解析 判定/条件覆盖,就是设计足够的测试用例,使得判定语句中每个条件的所有可能取值至少评价一次,同时每个判定语句本身所有可能分支也至少评价一次。本程序一共有两个判定语句,三条路径。若以 1 代表某一个条件为真,0 代表为假,则对于(a=b)、(c=d)、(e=f)、(p=q)、(s=t)这 5 个条件,取不同的真值组合,即可设计出相应的测试用例,达到判定/条件覆盖的要求。在这里,先取(a=b)
31、、(c=d)、(e=f)为 101,(p=q)、(s=t)为任意值,然后取全部 5 个条件为 010 11 和 010 00,即能达到判定/条件覆盖的要求。4.关于逻辑覆盖,说法错误的是_。(分数:3.00)A.DDP 覆盖是判定覆盖的一个变体B.满足条件覆盖一定也满足判定覆盖 C.指令块覆盖属于语句覆盖D.若判定覆盖率达 100%,则语句覆盖率一定也是 100%解析:解析 条件覆盖是指设计若干个测试用例,运行被测程序,使得程序中每个判定的每个条件的可能取值至少评价一次。而判定覆盖是设计测试用例,使得程序中每个判定的取真分支和取假分支至少评价一次。二者没有必然的联系,故满足条件覆盖的未必会满足
32、判定覆盖,选项 B 错误。而满足判定覆盖一定会满足语句覆盖是容易理解的,因为每个判定的取真分支和取假分支都至少评价一次必然预示着每个可执行语句至少评价了一次,即满足了语句覆盖。另外指令块覆盖是语句覆盖的一个变体而 DDP 覆盖(判定路径覆盖)是判定覆盖的一个变体。5.下列属于变量异常的是_。(分数:3.00)A.变量被定义,但没有被使用B.所使用的变量未被定义C.变量在使用前被重复定义D.以上全部 解析:解析 数据流测试是路径测试的一种,它主要关注一条路径上变量在何时定义、何时使用,通过变量的定义和使用异常来检查程序错误。通常将变量异常分为三类:第一类定义与使用异常变量被定义,但没有被使用;第
33、二类定义与使用异常所使用的变量未被定义;第三类定义与使用异常变量在使用前被重复定义。6.如果一个判定巾的复合条件表达式为(A1)or(B3),则为了达到 100%的条件覆盖率,至少需要设计多少个测试用例_。(分数:3.00)A.1B.2 C.3D.4解析:解析 由条件覆盖定义:设计若干测试用例,运行被测程序,使得每个判定的每个条件的可能取值至少评价一次。针对该题取 A=3、B=3 和 A=0、B=5 两组测试用例即可达到 100%的条件覆盖率,故本题选择 B。7.对于具有串联型分支结构的程序,若有 4 个判定语句,则采用正交实验设计法,至少需要的测试用例数应为_。(分数:3.00)A.4 个B
34、.16 个C.8 个 D.5 个解析:解析 对于具有串联型分支结构的程序,若有 4 个判定语句,则存在 16 条不同的测试路径,因此需要设计 16 个测试用例来覆盖它的每一条路径。但为了减少测试用例的数目,可以采用正交实验设计法,该方法原则上是抽取了部分路径进行测试,由方法中要求计算满足关系式 n+12 m的最小自然数 m,针对本题 n=4,可得 m=3,t=2 m=8,故本题目采用正交实验设计法,至少需要设计的测试用例数应为 8 个。8.下列指导选择和使用测试覆盖率的原则中错误的是_。(分数:3.00)A.覆盖率不是目的,仅是一种手段B.不要追求绝对 100%的覆盖率C.不可能针对所有的覆盖
35、率指标来选择测试用例D.只根据测试覆盖率指标来指导测试用例的设计 解析:解析 在选择和使用覆盖率时,应该注意以下原则:覆盖率只是一种手段,不是测试的最终目的。不可能针对所有的覆盖率进行测试,但如果只考虑一种覆盖率也是不妥的不要追求绝对 100%的覆盖率设计测试用例时,不仅要考虑到覆盖率,还应综合考虑其他方面,如成本等。根据以上原则,A、B、C 三个选项的说法均正确,而 D 说法不当,覆盖率不是唯一的参考指标。9.数据流覆盖关注的是程序中某个变量从其声明、赋值到引用的变化情况,它是下列哪一种覆盖的变种_。(分数:3.00)A.语句覆盖B.控制覆盖C.分支覆盖D.路径覆盖 解析:解析 数据流测试也
36、可以看成是一种路径测试,它主要关注一条路径上变量在何时定义、何时使用,所以数据流覆盖也可以看成是路径覆盖的一种,关注变量在某条路径中的变化情况。10.程序的流程图如下图所示,采用路径覆盖法进行测试,则至少需要几个测试用例可以覆盖所有可能的路径_。(分数:3.00)A.B. C.D.解析:解析 根据上面的程序流程图,可以导出程序的控制流图,然后利用环路复杂性的计算方法,最简单的是看该程序控制流图中有 5 个判定结点数,便可得到该控制流图的环路复杂性为 5+1=6,这样便可以确定 6 个线性无关的基本路径集,然后根据这些基本集对应找出 6 个测试用例,确保基本路径集中每一条路径都可以被执行到,即满
37、足题目中的路径覆盖,由此知若要满足路径覆盖,至少需要设计 6 个测试用例。11.对于一个嵌套型分支结构的程序,若有 4 个判定语句则要覆盖它的每一条路径至少需要的测试用例数为_。(分数:3.00)A.4 个B.3 个C.5 个 D.6 个解析:解析 程序中判定多于一个时,形成的分支结构可以分为两类:一类是嵌套型的分支结构,另一类是串联型的分支结构。对于嵌套型的分支结构,若有 n 个判定语句,则将会存在 n+1 条不同的测试路径,故至少需要设计 n+1 个测试用例方可覆盖每一条路径。对于本题为 n=4 的情况,故至少需要设计 4+1=5 个测试用例来分别覆盖 5 条不同的测试路径。12.下图是一
38、个判定路径覆盖图,其中用“ ”表示判定语句,用“ ”表示处理语句,用“”表示判定汇合点,用“”表示判定路径,若有一个测试用例覆盖了判定路径 A、B、E、H,则判定路径覆盖率为(分数:3.00)A. B.C.D.解析:解析 覆盖率公式:DDP 覆盖率=被评价到的判定路径数量/程序中判定路径总数100%=4/7100%=57.1%。13.下列语句通常不是作为定义结点的是_。(分数:3.00)A.输入语句B.输出语句 C.赋值语句D.过程调用语句解析:解析 结点 n 是变量 v 的定义结点,当且仅当变量 v 的值在结点 n 对应的语句中定义,记为DEF(v,n)。通常对应定义结点的语句有:输入语句、
39、赋值语句、循环控制语句和过程调用语句等。输出语句对应的是使用结点。14.关于数据流测试,说法正确的是_。(分数:3.00)A.数据流测试是一种路径测试 B.执行定义结点不会改变变量在存储单元中的内容C.执行使用结点会改变变量在存储单元中的内容D.定义/使用路径往往不是存在潜在错误的地方解析:解析 数据流测试主要关注一条路径上变量在何时定义(赋值),何时使用(引用),通过变量的定义和使用异常来检查程序错误,数据流测试可以看成是路径测试的一种,故选项 A 正确。执行定义结点就会改变变量在存储单元中的内容,而执行使用结点往往不会改变变量在存储单元中的内容,故选项 B 和选项 C 说法颠倒。定义/使用
40、路径与定义/清除路径描述了数据流,它在源程序中从定义变量值的结点流到使用该变量值的结点。定义/使用路径往往是存在潜在错误的地方。15.如果程序通过了 100%的代码覆盖率测试,则说明程序满足了_。(分数:3.00)A.语句覆盖 B.编程规范C.设计规格D.功能需求解析:解析 语句覆盖就是设计若干测试用例,运行被测程序,使得每一可执行语句至少执行一次。16.下面有关逻辑覆盖的说法中错误的是_。(分数:3.00)A.DDP 覆盖是判定覆盖的一个变体B.满足条件覆盖一定也满足判定覆盖 C.指令块覆盖属于语句覆盖D.若判定覆盖率达到 100%,则语句覆盖率一定也达到 100%解析:解析 条件覆盖是指设
41、计若干个测试用例,运行被测程序,使得程序中每个判定的每个条件的可能取值至少评价一次。而判定覆盖是设计测试用例,使得程序中每个判定的取真分支和取假分支至少评价一次。两者没有必然的联系,故满足条件覆盖的未必会满足判定覆盖,选项 B 错误。而满足判定覆盖一定会满足语句覆盖是容易理解的,因为每个判定的取真分支和取假分支都至少评价一次,必然预示着每个可执行语句至少评价了一次,即满足了语句覆盖。另外指令块覆盖是语句覆盖的一个变体,而 DDP 覆盖(判定路径覆盖)是判定覆盖的一个变体。17.如果程序中有两个判定条件,其复合条件表达式分别为(a=3) and (b=6)和(a0) or (c2),则为了达到
42、100%的判定覆盖率,至少需要没计的测试用例个数为_。(分数:3.00)A.1B.2 C.3D.4解析:解析 判定覆盖的定义:设计若干测试用例,运行被测程序,使得程序中每个判定的取真分支和取假分支至少评价一次。针对该题取 a=3、b=5、c=1 和 a=-1、b=5、c=3 两组测试用例即可达到 100%的判定覆盖率,故本题选择 B。18.对于具有串联型分支结构的程序,如果有七个判断语句串联,则使用正交实验设计法,至少需要的测试用例数应为_。(分数:3.00)A.23 B.24C.25D.27解析:解析 设串联型分支结构中有 n 个判定语句,计算满足关系式 n+12m 的最小自然数 m;设t=
43、2m,取正交表 Lt,并利用它设计测试数据,其中 t 为最少需要的测试用例数。二、论述题(总题数:8,分数:30.00)已知 C 源程序如下:/*Input todays date,output tomorrows date*/*version 2*/#includestdio.hstruct ydateint day;int month;int year;int leap(struct ydate d)if(d.year%4=0elsereturn 0;int numdays(struct ydate d)int day;static int daytab=31,28,31,30,31,30,31,31,30,31,30,31);if(leap(d)elseday=daytabd.month-1;return day;int main(void)struct ydate today,tomorrow;printf(“format of date is:year,month,day 输入的年、月、日之间应用逗号隔开/n“);printf(“today is:“);scanf(“%d,%d,%d“,while(0=today.year| today.year65535 | 0=