题目:实现如下功能,接收一个yyyymmdd形式的整数(例如20070412),确定相应的月、日和年的数值,并将年、月、日进行输出,要求实现异常处理。
分析:首先是如何将整数分离,这个是好办的,用一个数组接收,用指针操作就好。那么怎么实现异常处理呢?显然主要是控制输入的位数(用for实现)、控制月份和日期不越界。为了简单起见,默认每个月最大天数为31天。可以分别对月份和日期进行讨论,用if....else if....else...实现。但是最近在关注C语言的异常处理,想想何不用jmpset/longjmp来实现?于是动手写,最开始的代码如下:
- #include <STDIO.H>
- #include <STDLIB.H>
- #include "date.h"
- jmp_buf buf;
- void _error_month()
- {
- longjmp(buf,1);
- }
- void _error_day()
- {
- longjmp(buf,2);
- }
- void main()
- {
- int _da[8];
- const int* p = _da;
- _date mdate;
- for(int i = 0;i < 8;i ++)
- {
- printf("Please enter the ");
- printf("%d",i+1);
- printf(" number!\n");
- scanf("%d",&_da[i]);
- }
- mdate.year = *p * 1000 + *(p+1) * 100 + *(p+2) * 10 + *(p+3);
- mdate.month = *(p+4) * 10 + *(p+5);
- mdate.day = *(p+6) * 10 + *(p+7);
- int v = setjmp(buf);
- if (mdate.month <= 0 || mdate.month >= 13)
- {
- _error_month();
- }
- else if(mdate.day <= 0 || mdate.day >= 31)
- {
- _error_day();
- }
- if(v == 1)
- {
- printf("You enter a wrong month,Please shut down !!\n");
- return;
- }
- else if(v == 2)
- {
- printf("You enter a wrong day,Please shut down !!\n");
- return;
- }
- else
- {
- printf("The year is:");
- printf("%d\n",mdate.year);
- printf("The month is:");
- printf("%d\n",mdate.month);
- printf("The day is:");
- printf("%d\n",mdate.day);
- return;
- }
- }
一运行,发现竟然进入了死循环。百思不得其解。于是翻开了K&R的《C程序设计语言(第2版 . 新版)》第232页给出的关于标准库<setjmp.h>的说明。如下一段:
非局部跳转<setjmp.h> 头文件<setjmp.h>中的说明提供了一种避免通常的函数调用和返回顺序的途径,特别的,它允许立即从一个多层嵌套的函数调用中返回。 8.1 setjmp #include <setjmp.h> int setjmp(jmp_buf env); setjmp()宏把当前状态信息保存到env中,供以后longjmp()恢复状态信息时使用。如果是直接调用setjmp(),那么返回值为0;如果是由于调用longjmp()而调用setjmp(),那么返回值非0。setjmp()只能在某些特定情况下调用,如在if语句、 switch语句及循环语句的条件测试部分以及一些简单的关系表达式中。 8.2 longjmp #include <setjmp.h> void longjmp(jmp_buf env, int val); longjmp()用于恢复由最近一次调用setjmp()时保存到env的状态信息。当它执行完时,程序就象setjmp()刚刚执行完并返回非0值val那样继续执行。包含setjmp()宏调用的函数一定不能已经终止。所有可访问的对象的值都与调用longjmp()时相同,唯一的例外是,那些调用setjmp()宏的函数中的非volatile自动变量如果在调用setjmp()后有了改变,那么就变成未定义的。
其中尤其有一段话引起了我的注意:
setjmp()只能在特定情况下调用,比如if语句、switch语句以及循环语句的条件测试部分以及一些简单关系表达式中。 |
- #include <STDIO.H>
- #include <STDLIB.H>
- #include "date.h"
- jmp_buf buf;
- void _error_month()
- {
- longjmp(buf,1);
- }
- void _error_day()
- {
- longjmp(buf,2);
- }
- void main()
- {
- int _da[8];
- const int* p = _da;
- _date mdate;
- for(int i = 0;i < 8;i ++)
- {
- printf("Please enter the ");
- printf("%d",i+1);
- printf(" number!\n");
- scanf("%d",&_da[i]);
- }
- mdate.year = *p * 1000 + *(p+1) * 100 + *(p+2) * 10 + *(p+3);
- mdate.month = *(p+4) * 10 + *(p+5);
- mdate.day = *(p+6) * 10 + *(p+7);
- int v = setjmp(buf);
- if(v == 1)
- {
- printf("You enter a wrong month,Please shut down !!\n");
- return;
- }
- else if(v == 2)
- {
- printf("You enter a wrong day,Please shut down !!\n");
- return;
- }
- else
- {
- if (mdate.month <= 0 || mdate.month >= 13)
- {
- _error_month();
- }
- else if(mdate.day <= 0 || mdate.day >= 31)
- {
- _error_day();
- }
- printf("The year is:");
- printf("%d\n",mdate.year);
- printf("The month is:");
- printf("%d\n",mdate.month);
- printf("The day is:");
- printf("%d\n",mdate.day);
- return;
- }
- }
特地记下这个例子,以后再用到setjmp时,可以回忆一下这个例子,思考一下问题可能出在哪里。
转载于:https://blog.51cto.com/jodonchu/1079050