问题分析
本题考察的是异常处理。优质的程序必须具备良好的异常处理机制,切不可马虎了事,这将直接决定程序的质量。
问题解答
先贴出分析目标代码:
1 #include <iostream> 2 #include <fstream> 3 #include <string> 4 5 using namespace std; 6 7 // 每个整数的位数 8 #define BITSPERWORD 32 9 // 每次位移量 10 #define SHIFT 5 11 // 取模掩码 12 #define MASK 0x1F 13 // 位向量的元素个数 14 #define N 10000000 15 16 // 模拟数组 17 int a[1 + N/BITSPERWORD]; 18 19 /* 20 * 函数功能:置位向量第i位为1 21 * 函数说明:" i>>SHIFT "等于" i/32 " 获取到位向量目标位对应的模拟数组元素的位置 22 " i & MASK "等于" i%32 " 获取到位向量目标位在对应的模拟数组元素中的位置 23 " 1<<(i & MASK) " 表示一个除了要设置的那位其他位都是0的整数 24 */ 25 void set (int i) { 26 a[i>>SHIFT] |= (1<<(i & MASK)); 27 } 28 29 /* 30 * 函数功能:置位向量第i位为0 31 * 函数说明:" i>>SHIFT "等于" i/32 " 获取到位向量目标位对应的模拟数组元素的位置 32 " i & MASK "等于" i%32 " 获取到位向量目标位在对应的模拟数组元素中的位置 33 " 1<<(i & MASK) " 表示一个除了要清空的那位其他位都是0的整数 34 */ 35 void clr (int i) { 36 a[i>>SHIFT] &= ~(1<<(i & MASK)); 37 } 38 39 /* 40 * 函数功能:获取位向量的第i位 41 * 函数说明:" i>>SHIFT "等于" i/32 " 获取到位向量目标位对应的模拟数组元素的位置 42 " i & MASK "等于" i%32 " 获取到位向量目标位在对应的模拟数组元素中的位置 43 " 1<<(i & MASK) " 表示一个除了要获取的那位其他位都是0的整数 44 */ 45 int tst (int i) { 46 return a[i>>SHIFT] & (1<<(i & MASK)); 47 } 48 49 50 int main() 51 { 52 /* 53 * 清空位向量 54 */ 55 for (int i=0; i < N; i++) { 56 clr(i); 57 } 58 59 string filename; 60 cout << "输入数据文件名( 当前目录下 ):"; 61 cin >> filename; 62 63 fstream io; 64 io.open(filename.c_str()); 65 if (!io) { 66 cout << "打开文件失败" << endl; 67 return 1; 68 } 69 70 /* 71 * 根据数据文件记录给位向量赋值 72 * 赋值完了以后其实已经" 完成排序了 " 73 */ 74 int data; 75 while (io >> data) { 76 set(data); 77 } 78 79 io.close(); 80 io.clear(); 81 io.open(filename.c_str(), fstream::out | fstream::trunc); 82 83 /* 84 * 从位向量获取数据并写回数据文件 85 */ 86 for (int i=0; i <N; i++) { 87 if ( tst(i) ) { 88 io << i << " "; 89 } 90 } 91 92 io.close(); 93 94 return 0; 95 }
1. 重复的数据将被丢失。
2. 可以在set函数中加入判断,如果待set位已经为1了则弹出错误并退出。
3. 如果数据大于等于N,位向量函数将会产生访问数组越界的错误;如果数据小于0,也会导致访问数组失败。
4. 如果不是数字,则位向量函数将会错误地控制非数据对应的位,从而使程序发生异常。
5. 对于 1-4 这类的输入异常,一方面可以在生成数据文件的时候加强检查,严禁非法数据写入数据文件;另一方面,具体排序时读取到非法数据应该弹出友好的错误提示并退出程序。
6. 我们应当在测试数据中加入重复数据,字符串数据,负数,大于N的数等各种能预料得到的异常数据进行测试,并编写异常处理代码。