user294664 user294664 - 14 days ago 5
C++ Question

unexpected exit of loop with ifstream getline

please look at the below code:

std::string s;
while(std::getline(m_File,s))
{
std::cout<<"running\n";
std::string upper(s);
std::transform(upper.begin(),upper.end(),upper.begin(),toupper);


if(upper.find("*NODE") != std::string::npos)
{
std::cout<<"start reading nodes\n";
readnodes();

}
std::cout<<"\n open? "<<m_File.is_open()<<"\n";

}


I'm trying to extract data from the below input file.(INPUT FILE)

*NODE
1 ,1.0,2.0
2, 2.6,3.4
3, 3.4, 5.6
*NODE
4, 4, 5
5, 5, 6


but when I run this, program find first instance of *NODE and calls readnode() function, but fail to recognize second instance of *NODE.
m_File is ifstream object of the same class where readnode() is defined as the private function.

readnode() :

void mesh::readnodes()
{
char c;
int id;
float x,y;

while(m_File>>id>>c>>x>>c>>y)
{
node temp(id,x,y);
m_nodes.push_back(temp);

// dummy string for reading rest of line.
std::string dummy;
std::getline(m_File,dummy);

}
}

Answer

Why the unexpected exit?

while(m_File>>id>>c>>x>>c>>y)
{
    node temp(id,x,y);
    m_nodes.push_back(temp);

    // dummy string for reading rest of line. 
    std::string dummy;
    std::getline(m_File,dummy);
}

In the code above, m_File>>id>>c>>x>>c>>y used to read id,x,y, but after read the first couple of node lines, it breaks when m_File>>id>>c>>x>>c>>y failed, which may also change m_File state. As a result, getline(m_File, s) return false, which cause the unexpected exit.

Solution:

I didn't come across a solution based on your original program. But since you want to extract value from string, then boost may be a better solution, check:

while (getline(m_File, s))
{
    if (boost::to_upper_copy(s) == "*NODE") continue;

    std::vector<std::string> SubStr;
    boost::algorithm::split(SubStr, s, boost::is_any_of(" ,"));

    SubStr.erase(std::remove(SubStr.begin(), SubStr.end(), ""), SubStr.end());
    m_nodes.push_back(node(atoi(SubStr[0].c_str()), atof(SubStr[1].c_str()), atof(SubStr[2].c_str())));
}

Fetch result:

for (auto Itr : m_nodes)
    std::cout << Itr.id << "," << Itr.x << "," << Itr.y << std::endl;

Output

1,1.0,2.0
2,2.6,3.4
3,3.4,5.6
4,4,5
5,5,6