【算法入门经典】题解报告 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.遇到的问题

  1. 为什么会越界
  2. c++的自有变量
  3. 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;
}

 

posted @ 2018-04-26 00:29  adsk  阅读(180)  评论(0)    收藏  举报