2012-08-12 69 views
0

這是我的部分代碼這個矢量分裂:C++中什麼是錯在While循環

if(action=="auth") 
{ 


myfile.open("account.txt"); 
    while(!myfile.eof()) 
    { 
     getline(myfile,sline); 

     vector<string> y = split(sline, ':'); 
    logincheck = ""; 
    logincheck = y[0] + ":" + y[3]; 

    if (sline==actionvalue) 
    { 
    sendClient = "login done#Successfully Login."; 
    break; 
    } 
    else 
    { 
    sendClient = "fail login#Invalid username/password."; 
    } 

    y.clear(); 
    } 
    myfile.close(); 

} 

如果我沒有這個

logincheck = y[0] + ":" + y[3]; 

的代碼將不會有任何的分割核心轉儲錯誤,但是當我添加該行時,它將完全錯誤。

我account.txt是如下:

admin:PeterSmite:hr:password 
cktang:TangCK:normal:password 

分割功能:

std::vector<std::string> split(std::string const& str, std::string const& delimiters = "#") { 
    std::vector<std::string> tokens; 

    // Skip delimiters at beginning. 
    string::size_type lastPos = str.find_first_not_of(delimiters, 0); 
    // Find first "non-delimiter". 
    string::size_type pos = str.find_first_of(delimiters, lastPos); 

    while (string::npos != pos || string::npos != lastPos) { 
    // Found a token, add it to the vector. 
    tokens.push_back(str.substr(lastPos, pos - lastPos)); 
    // Skip delimiters. Note the "not_of" 
    lastPos = str.find_first_not_of(delimiters, pos); 
    // Find next "non-delimiter" 
    pos = str.find_first_of(delimiters, lastPos); 
    } 
    return tokens; 
} 



std::vector<std::string> split(std::string const& str, char const delimiter) { 
    return split(str,std::string(1,delimiter)); 
} 
+1

您是否在調試器中檢查了分離器是否正常工作? – Dani 2012-08-12 14:04:21

+0

在碰撞時y是什麼?我的猜測是你的文件在最後有一個空行,所以你的split函數不會返回那行的4個元素。如果發生這種情況,那麼您正在訪問不存在的矢量元素。 – cbranch 2012-08-12 14:07:03

回答

3

你應該做一些基本的輸入檢查,然後漫不經心地假設載體含有至少4個元素,否則y[3]會在解析一行不含三個冒號的輸入時發生爆炸:

if (y.size >= 4) { 
    // Do login check 
} else { 
    // Invalid input 
} 

我猜你可能在你的輸入中有一個空行。

裹的代碼的整個部分,它依賴於讀出「A:B:C:d」行輸入的:

if(action=="auth") { 
    myfile.open("account.txt"); 
    while(getline(myfile,sline)) 
    { 
    vector<string> y = split(sline, ':'); 
    if (y.size >= 4) { 
     logincheck = ""; 
     logincheck = y[0] + ":" + y[3]; 

     if (sline==actionvalue) { 
     sendClient = "login done#Successfully Login."; 
     break; 
     } else { 
     sendClient = "fail login#Invalid username/password."; 
     } 
    } 
    } 
    myfile.close(); 
} 
+0

包裝不起作用。仍然有相同的錯誤 – user1587149 2012-08-12 14:12:35

+0

崩潰時'y'的價值是什麼?那麼'logincheck'的類型是什麼?它是一個'std:string'還是一個C字符串? – Doches 2012-08-12 14:26:12

0

的問題是,在調用函數getline拉動的最後一個可用的線ISN不設置EOF,所以在獲得最後一個可用行後,您需要執行一次額外的循環迭代。該循環操作在一個空的sline上運行,這會導致不好的事情發生,即split不會返回包含四個元素的向量,但是您嘗試訪問這些元素。

你可以使用

while (getline(myfile,sline)) 
{ 
    // do stuff 
} 

代替

while(!myfile.eof()) 
{ 
    getline(myfile,sline); 
    // do stuff 
} 
1

的問題是你的循環結構:

while(!myfile.eof()) 
    { 
     getline(myfile,sline); 

istream::eof()不保證返回true,直到您嘗試讀過結束o流。那麼,發生什麼事是你讀了2行,eof()仍然沒有返回true。然後你第三次進入循環。由於您不會在getline調用後檢查錯誤,因此您可以在未指定其內容時快樂地訪問sline - 它可能爲空,它仍可能包含上一次迭代中的內容,也可能包含其他內容。

在嘗試訪問字符串之前,您總是需要檢查getline()調用是否成功。慣用的方式是把它放在循環的條件下:

while (getline(myfile, sline)) { /* do your stuff */ } 

這樣你只有在讀取成功時才進入循環體。