UVa 1596 Bug Hunt (string::find && map && 模擬)
題意:給出幾組由數組定義與賦值構成的編程語句, 有可能有兩種BUG, 第一種為數組下標越界, 第二種為使用尚未定義的數組元素, 叫你找出最早出現BUG的一行並輸出, 每組以‘ . ‘號分隔, 當有兩組輸入都是‘ . ‘時結束程序
分析:由於錯誤的類型由題意所述的兩種組成, 所以我們需要知道每個數組的長度與每個已經被賦值定義過的數組元素大小, 因此可以定義map<string, int> Info 來存儲數組名和這個數組的大小兩個信息, 在定義一個map<string, map<int, int>> arr 來儲存數組內某個元素的具體的值。由於每一行的語句可以很復雜, 類似 a[B[a[0]]]=a[B[0]] 這樣, 所以需要分步處理!這裏的解決方案步驟如下, 都以 c[B[a[0]]]=a[B[0]] 為例
1、如果為定義語句, 則直接進行模擬和存儲即可
2、如果為賦值語句,則將其按等於號分為左右兩部分進行處理 (即 c[B[a[0]]] 和 a[B[0]] )
3、提取出左部分並且分為將要被賦值的數組名 和 其[ ]內的內容 (即 c 和 B[a[0]] )
4、提取出右部分全部 (即 a[B[0]])
5、如果需要處理的數組下標, 即[ ]裏的元素就是數字的話則直接判斷是否存在題目所述的兩種BUG, 不存在則模擬正常存儲過程
6、如果[ ]元素還是嵌套的數組, 可以發現這種情況的處理方法都是從裏往外一個個全部找BUG並且轉成對應的數字, 符合遞歸思想, 因此可以寫一個遞歸模塊check()來提取
7、將第三步提取出的[ ]中的內容丟進check()進行查錯和轉化 (即 check( B[a[0]] )
8、將第四步提取出的內容同樣丟進check()進行查錯和轉化
9、若所有的check()都沒毛病, 則復雜的語句將會變成——>數組名[數字] = 數字 這種形式, 進行模擬存儲即可
技巧:其中有些操作可能會比較麻煩, 下面介紹幾個函數
1、字符的分部可以使用string::find_first_of( 元素 )函數, 其返回的是在string中第一次找到元素的位置 和 string::substr(begin, len)來解決
2、判斷語句是否有‘ = ‘號可以使用string::find(), 如果 其!=string::npos則說明存在
瞎搞:在做這種模擬題前需要仔細斟酌, 否則打出來之後可能花了很多時間卻發現了重大的錯誤, 並且需要多想用什麽進行存儲能方便操作, 還有盡量進行模塊化編程, 否則打出來後一旦出現BUG, 對著又長又臭的代碼, 改錯難度肯定很大!因此三思而後行啊!
#include<bits/stdc++.h> #define in 0 #define out 0 using namespace std; map<string, int> info; map<string, map<int, int> > arr; bool Error; // check中的標誌,如果為true則說明已經存在BUG int check(string s) { if(isdigit(s[0])){ stringstream num(s); int k; num>>k; return k; }else{ string Inner = s.substr(s.find_first_of(‘[‘)+1, s.find_first_of(‘]‘)-s.find_first_of(‘[‘)-1); string name = s.substr(0, s.find_first_of(‘[‘)); int index = check(Inner); if(!info.count(name) || index==-1){ Error = true; return -1; }else{ if(index>=info[name]){ Error = true; return -1; }else{ if(!arr[name].count(index)){ Error = true; return -1; }else{ return arr[name][index]; } } } } } bool solve() { Error = false; string temp; int line = 0;//記錄行數 int error_line = 0;//記錄錯誤的行數 while(cin>>temp){ if(temp[0]==‘.‘){ if(!line) return false; else{ info.clear(); arr.clear(); printf("%d\n", error_line); return true; } } if(error_line != 0) continue;//如果已經找到錯誤的行數, 沒必要進行下去 line++; if(temp.find(‘=‘) != string::npos){ string Left = temp.substr(0, temp.find_first_of(‘=‘)); string Right = temp.substr(temp.find_first_of(‘=‘)+1); string A = Left.substr(0, Left.find_first_of(‘[‘)); string B = Right.substr(0, Right.find_first_of(‘[‘)); string InA = Left.substr(Left.find_first_of(‘[‘)+1, Left.find_last_of(‘]‘)-Left.find_first_of(‘[‘)-1); int L = check(InA);//丟進check進行數字的轉化 int R = check(Right); if(Error){//上面進行check後如果Error為true則說明找到BUG error_line = line; }else{ if(!info.count(A)){ error_line = line; }else{ map<int, int> temp2; if(L>=info[A] || L<0){ error_line = line; }else{ if(!arr.count(A)){ temp2[L] = R; arr[A] = temp2; }else{ arr[A][L] = R; } } } } }else{ string name = temp.substr(0, temp.find_first_of(‘[‘)); string index = temp.substr(temp.find_first_of(‘[‘)+1, temp.find_first_of(‘]‘)-1); stringstream num(index); int len; num>>len; info[name] = len; } } } int main(void) { #if in freopen("in.txt", "r", stdin); #endif #if out freopen("out.txt", "w", stdout); #endif while(solve()){} return 0; }View Code
UVa 1596 Bug Hunt (string::find && map && 模擬)