2012-08-12 89 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 */ } 

这样你只有在读取成功时才进入循环体。