【算法入门经典】题解报告 5-9 Bug Hunt,Uva1596
现在我主要讲一下如何实现这段代码,以及在实现过程中遇到的问题。
1.基本思路
我解决这个问题的基本思路是这样的:
首先是输入,然后对输入进行判断,判断其是否合法,一旦不合法就退出。如果合法就继续进行下去,并且把已定义和赋值的数组(注意,实际上存的并不是数组,而是另一种实现的数据结构)存起来,然后在之后的判断过程中不断的去调用之前的存起来的数组。所以这里的关键是如何判断是否合法和数组数据的实现。
2.实现细节
- 首先要做的是数组数据的定义,根据可能出现的bug错误只有index越界和使用未初始化的变量,可以考虑在其内部定义一个(int)size表示该数组定义时的大小,用(map<int,int>) arr来表示已赋值的元素(刚开始我考虑用的是数组,但发现会越界,而且很占空间,因为大多数部分并不会被使用,这里还可以考虑用map<string,int>,也就是说直接把数字看做某种字符,这显然是可行的,事实上高精度数字就是这样实现的)。除此之外,还要定义一个构建函数和清除函数,构建函数似乎没有必要,而清除函数则是为了在每一组数据循环是初始化。数据的实现就是这样了,这里还要说一下自定义数据的数组形式,即Array arrays[128},刚开始我用的是array作为自定义数据名,但好像和c++本身的某些已定义字符冲突了,这告诉我们定义数据时最好用大写开头。
struct Array { int size; map<int,int> arr; Array() { remove(); } void remove() { size = 0; arr.clear(); } void clear() { size=0; arr.clear(); } }; const int maxn=128; Array m[maxn];
- 接下来是关于检查有无bug的程序check(string& s),这里我的想法是从每行输入的最后开始,不断的往前迭代,并根据不同的情况进行处理。刚开始我考虑的是要不要先判断是定义还是赋值,后来发现没有这个必要,只要在迭代的过程中增加一种情况,字符为=的情况,并用一个变量来保存这种状态,在最后进行分情况处理就行了,同理这之中的index等变量也可以共用,只要实时的更新值就行了(在遇到=的时候)。这样,每次都是单步景象,并且只需处理少数几种情况。每次处理的情况可能有三种,除了已经将的=外,还有字母和数字的检查,这个用isalpha() 和 isdigit()可以实现,数字检查是为了得到初始的index值,由于数字是连续的,如123,从后面开始检测的话,每次得到一个数字,并用一个变量更新它的位数,然后根据位数对每个数乘以10的位数次方,然后加起来就可以了。主要这种数的判断(指的是整个完整的数,如123)只会进行一次或两次,分别对应定义和赋值的情况。然后是字母的情况,在字母的时候,要做的就是,检测index是否越界,以及赋值是否存在,如果是的话,在之前已经储存的数据取出对应的值,并更新index。这里忘了说了,检测的时候是从字符串最后到1位,0位是在之后总的判断时进行处理的,因为必须要保持在检测时的一致性,首字母会根据是定义还是赋值而出现不同形式的处理,而其他的字母都只是取值而已。最后的总的判断就是根据是定义还是赋值而进行不同的处理。
int check(string& s) { int a=s[0]; int index=0,x=0,value=0; int len=s.size(),l=0; for(int i=len;i>0;i--) { char c=s[i]; if(isdigit(c)) { int num=c-'0'; index+=pow(10,x)*num; x++; } if(isalpha(c)) { if(index<m[c].size&&m[c].arr.count(index)) index=m[c].arr[index]; else return 0; } if(c=='=') { l=1;x=0; value=index; index=0; } } if(l) { if(index<m[a].size) { m[a].arr[index]=value; return 1; } return 0; } else { m[a].size=index; return 1; } }
主程序如下:
int main() { string s; int r=0,d=0; bool h=1; while(cin>>s) { if(s[0]=='.'&&d==1) break; d=0; if(h) { h=check(s); r++; } if(s[0]=='.') { d=1; if(h) cout<<"0"<<endl; else cout<<r<<endl; h=1;r=0; for(int i=65;i<123;i++) { m[i].clear(); } } } return 0; }
一目了然,不用多说了
3.遇到的问题
- 为什么会越界
- c++的自有变量
- Array的初始化和赋值操作
下面是全部代码:
#include <bits/stdc++.h> using namespace std; struct Array { int size; map<int,int> arr; Array() { remove(); } void remove() { size = 0; arr.clear(); } void clear() { size=0; arr.clear(); } }; const int maxn=128; Array m[maxn]; int check(string& s) { int a=s[0]; int index=0,x=0,value=0; int len=s.size(),l=0; for(int i=len;i>0;i--) { char c=s[i]; if(isdigit(c)) { int num=c-'0'; index+=pow(10,x)*num; x++; } if(isalpha(c)) { if(index<m[c].size&&m[c].arr.count(index)) index=m[c].arr[index]; else return 0; } if(c=='=') { l=1;x=0; value=index; index=0; } } if(l) { if(index<m[a].size) { m[a].arr[index]=value; return 1; } return 0; } else { m[a].size=index; return 1; } } int main() { string s; int r=0,d=0; bool h=1; while(cin>>s) { if(s[0]=='.'&&d==1) break; d=0; if(h) { h=check(s); r++; } if(s[0]=='.') { d=1; if(h) cout<<"0"<<endl; else cout<<r<<endl; h=1;r=0; for(int i=65;i<123;i++) { m[i].clear(); } } } return 0; }
参考代码:
// Bug Hunt, ACM/ICPC Tokyo 2007, UVa1596 // 闄堥攱 #include<cassert> #include<iostream> #include<cstdio> #include<cmath> #include<functional> #include<algorithm> #include<cstring> #include<string> #include<sstream> #include<map> using namespace std; struct Array { int size; map<int, int> values; void init(int sz) { assert(sz>=0); // printf("init size = %d\n", sz); size = sz; values.clear(); } Array(){ remove(); } void remove() { size = -1; values.clear(); } bool exists() { return size >= 0; } bool getValue(int idx, int& v) { assert(exists()); if(values.count(idx)) { v = values[idx]; return true; } return false; } bool setValue(int idx, int v) { assert(exists()); assert(idx >= 0); if(idx >= size) return false; values[idx] = v; return true; } }; const int MAXA = 128; Array arrays[MAXA]; bool eval(const char* s, int len, int& v) { // printf("eval %s, len = %d,\n", s, len); if(isdigit(s[0])) { sscanf(s, "%d", &v); return true; } char a = s[0]; assert(len > 3); assert(isalpha(a)); assert(s[1] == '['); assert(s[len-1] == ']'); Array& ary = arrays[a]; if(!ary.exists()) return false; int idx; if(!eval(s+2, len-3, idx)) return false; return ary.getValue(idx, v); } int main() { char line[128]; int lineNum = 0, bugLine = 0; while(scanf("%s", line) == 1){ // printf("e : %s\n", line); int expLen = strlen(line); if(line[0] == '.') { if(lineNum) printf("%d\n", bugLine); for(int i = 0; i < MAXA; i++) arrays[i].remove(); lineNum = 0; bugLine = 0; continue; } if(bugLine > 0) continue; const char *pEq = strchr(line, '='); if(pEq) { Array& ary = arrays[line[0]]; int rv, index, lLen = pEq - line; if(ary.exists() && eval(pEq+1, expLen-lLen-1, rv) && eval(line+2, lLen-3, index) && ary.setValue(index, rv)) lineNum++; else bugLine = lineNum+1; } else { char name; int sz; sscanf(line, "%c[%d]", &name, &sz); arrays[name].init(sz); lineNum++; } } return 0; }

浙公网安备 33010602011771号