题意:输入并模拟执行一段程序,输出第一个BUG所在的行。每行程序有两种可能:
1.数组定义,格式为arr[size]。例如a[10]或者b[5],可用下标分别是0~9和0~4.定义之后所有元素均为未初始化状态。
2.赋值语句,格式为arr[index] = value。例如a[0] = 3或者a[a[0]] = a[1].
定义语句保证正确,赋值语句可能会出现两种bug:下标index越界;使用未初始化的变量(index和value都可能会出现这种情况)
数组名保证为一个字符(a~z,A~Z),题目中出现的常数保证在0 ~ 2^31 − 1 (= 2147483647)范围之内。
程序不超1000行,每行不超过80个字符,一共不超过1500行。
思路:用一个map保存数组名对应其长度,一个map保存一段字符串对应的值。数组定义,我们直接放入map对应长度即可。赋值语句,判断"="右边的值是否被定义,"="左边的第一个[]内的值是否被定义且小于数组长度。判断的时候因为有多重括号,所以我们要一层一层的判断,先递归进入到最后一层即只有一个括号或者没括号,然后一层一层的往外返回值,如果中间某一层该值不存在返回-1就可以,因为[-1]一定不存在所以后面一定返回的都是-1。
感觉这题的输入反人类。。。我是用一个vector先把每段程序的输入保存下来,然后再去处理。
#include<bits/stdc++.h>
using namespace std;
map<char, int> len;//数组名,长度
map<string, int> val;//字符串,对应值
vector<string> v;//代码
int get_val(string str)//递归求str这段字符串对应的值,不存在对应-1
{
if (str.find('[') == string::npos) return stoi(str);//没有括号
if (count(str.begin(), str.end(), '[') == 1)//还有一对括号
{
if (!val.count(str)) return -1;//该字符串没有出现过
return val[str];
}
if (count(str.begin(), str.end(), '[') >= 2)//还有两对及以上的括号
{
int v = get_val(str.substr(str.find('[') + 1, str.rfind(']') - str.find('[') - 1));//递归
if (!val.count(str.substr(0, 2) + to_string(v) + ']')) return -1;//该字符串没有出现过
return val[str.substr(0, 2) + to_string(v) + ']'];
}
}
int main()
{
string str;
while (getline(cin, str) && str[0] != '.')
{
v.clear(); len.clear(); val.clear();
v.push_back(str);
while (getline(cin, str) && str[0] != '.') v.push_back(str);
int bug = 1;//BUG行数
for (auto i: v)
{
if (i.find("=") == string::npos)//没有等号,定义数组
{
len[i[0]] = stoi(i.substr(2));
}
else
{
string l = i.substr(0, i.find('='));//左边
string r = i.substr(i.find('=') + 1);//右边
int lval = get_val(l.substr(l.find('[') + 1, l.rfind(']') - l.find('[') - 1));//左值
int rval = get_val(r);//右值
if (lval == -1 || rval == -1 || !len.count(i[0]) || lval >= len[i[0]]) break;
string name = i.substr(0, 2) + to_string(lval) + ']';
val[name] = rval;//该值放入map
}
bug++;
}
if (bug > v.size()) bug = 0;//如果最后一行都没有BUG
cout << bug << endl;
}
return 0;
}