题目链接:https://cn.vjudge.net/problem/UVA-1596
输入并模拟执行一段程序,输出第一个bug所在行。每行程序有两种可能:
-
数组定义,格式为arr[size]。例如a[10]或者b[5],可用下标分别是0~9和0~4。定义之后所有元素均为未初始化状态。
-
赋值语句,格式为arr[index]=value。例如a[0]=3或者a[a[0]]=a[1]。
赋值语句可能会出现两种bug:下标index越界;使用未初始化的变量(index和value都可能出现这种情况)。 输入不超过1000行,每行不超过80个字符且所有常数均为小于2^31的非负整数。
输入格式: 输入包含多组数据,每组数据用“.”隔开。输入以连续输入两个“.”结束。详见样例。
输出格式: 每组数据你都应输出第一个bug所在行,如没有bug,则输出0。详见样例。
分析:细节题,考察对字符的切割。看到数组有嵌套,则一定会考虑递归,因为递归有进有出方便判断,也顺便练习了递归。定义了两个map
一个key为数组名称,value为数组长度,另一个key为“数组名称[下标”的形式储存例如a[3,value为对应的值。
写一个递归函数get,该函数对等号右边为取等号右边整体的值,对等号左边为取第一个中括号中内容,即数组名的整体下标。(递归途中若有未赋值的元素,返回-1,否则返回对应的值)
代码:
#include <bits/stdc++.h>
using namespace std;
vector<string> code;
map<char,int > mmax;
map<string,int > value;
int Get(string str) {
if(str.find('[')==string::npos)
return stoi(str);
if(count(str.begin(), str.end(), '[')==1) {
if(!value.count(str)) return -1;
return value[str];
}
if(count(str.begin(), str.end(), '[')>1) {
string temp = str.substr(2);
int t = Get(temp);
if(!value.count(str.substr(0, 2) + to_string(t)))
return -1;
return value[str.substr(0, 2) + to_string(t)];
}
}
int main(){
freopen("i.txt","r",stdin);
string str;
int flag;
while(1) {
flag = 0;
code.clear(), mmax.clear(), value.clear();
cin >> str;
if(str==".")
break;
else {
code.push_back(str);
while(cin >> str) {
if (str != ".")
code.push_back(str);
else break;
}
}
for(int i = 0; i < code.size(); i++) {
if(code[i].find("=")==string::npos)
mmax[code[i][0]] = stoi(code[i].substr(2));
else {
string strl = code[i].substr(0,code[i].find('='));
string strr = code[i].substr(code[i].find('=')+1);
//左边为第一个括号中
int nl = Get(strl.substr(2,strl.find(']')-2));
//右边为整体
int nr = Get(strr.substr(0, strr.find(']')));
if(nl==-1 || nr==-1) {
flag = i;
break;
}
if(nl>=mmax[code[i][0]]) {
flag = i;
break;
}
value[code[i].substr(0,2) + to_string(nl)] = nr;
}
}
if(flag)
cout << flag+1 << endl;
else cout << 0 << endl;
}
return 0;
}