Thread: Parse function not reading through entire vector

  1. #1
    C++ Enthusiast jmd15's Avatar
    Join Date
    Mar 2005
    Location
    MI
    Posts
    532

    Parse function not reading through entire vector

    I've written this little member function to parse a vector's data, but it only parses the first LINE of data.
    See, the vector reads in a multi-line file, each line with 3 parameters separated by a semi-colon.
    The vector has all that unparsed data stored, so what this function does is read through it, and parse the data, placing the right segment of data in the correct array. My problem is my function doesn't seem to be iterating through the entire vector. ONLY the first line of the file that's stored in the vector is parsed (which I've checked and double checked by outputting the arrays the data is sent to, and outputting the data as it's parsed).
    I am a bit rusty, and I'm confused as to why it's not running through the entire vector, as it seems to me that it should. Code below is the function:
    Code:
    void Map::parse_data()
    {
      istringstream iss;
      string parsed;
      vector<string>::iterator iter;
      int counter=0;
      for(iter=data.begin();iter!=data.end();iter++)
        {
          iss.str((*iter));
          while(!iss.eof())
    	{
    	  getline(iss,parsed,';');
    	  if(!parsed.empty())
    	    switch(counter)
    	      {
    	      case 0:
    		xsprcrds[xpos]=atoi(parsed.c_str());
    		parsed.clear();
    		xpos++;
    		counter++;
    		break;
    	      case 1:
    		ysprcrds[ypos]=atoi(parsed.c_str());
    		parsed.clear();
    		ypos++;
    		counter++;
    		break;
    	      case 2:
    		sprname[npos]=parsed;
    		parsed.clear();
    		npos++;
    		counter=0;
    		break;
    	      }
    	}
        }
    }
    Any help's appreciated, thanks.
    Trinity: "Neo... nobody has ever done this before."
    Neo: "That's why it's going to work."
    c9915ec6c1f3b876ddf38514adbb94f0

  2. #2
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Try changing this:
    Code:
    void Map::parse_data()
    {
        istringstream iss;
        string parsed;
        vector<string>::iterator iter;
        int counter=0;
        for(iter=data.begin();iter!=data.end();iter++)
        {
            iss.str((*iter));
            while(!iss.eof())
            {
                getline(iss,parsed,';');
                if(!parsed.empty())
    To this:
    Code:
    void Map::parse_data()
    {
        string parsed;
        vector<string>::iterator iter;
        int counter=0;
        for(iter=data.begin();iter!=data.end();iter++)
        {
            istringstream iss;
            iss.str((*iter));
            while( getline(iss,parsed,';') )
            {
                if(!parsed.empty())
    ... and see if that helps.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Output the size of the vector before the for loop. Then output a message inside the for loop so you can see how many times the loop is run. Add another message inside the while loop to see how often that is run.

    >> while(!iss.eof())
    Don't think that this is the problem, but it might be. You should move the getline call into the while control: while(getline(iss,parsed,';'))

    Edit: hk_mp5kpdw is probably right. The stringstream needs to be cleared each time through. Declaring it locally to the loop does that and is better design.

  4. #4
    C++ Enthusiast jmd15's Avatar
    Join Date
    Mar 2005
    Location
    MI
    Posts
    532
    Thanks for the reply.
    That did help me a bit, now it reads through all the lines, but my problem's changed a bit.
    Here's what the file that's being parsed looks like:
    Code:
    5;20;MidGreen
    10;20;LeftGreen
    30;20;RightGreen
    ...
    And you get the picture.
    Well anyways, now when I run the function that looks like this:
    Code:
    void Map::parse_data()
    {
      string parsed;
      vector<string>::iterator iter;
      int counter=0;
      for(iter=data.begin();iter!=data.end();iter++)
        {
          istringstream iss;
          iss.str((*iter));
          while(getline(iss,parsed,';'));
            {
    	  cout<<parsed<<endl;
    	  if(!parsed.empty())
    	    {
    	    switch(counter)
    	      {
    	      case 0:
    		xsprcrds[xpos]=atoi(parsed.c_str());
    		parsed.clear();
    		xpos++;
    		counter++;
    		break;
    	      case 1:
    		ysprcrds[ypos]=atoi(parsed.c_str());
    		parsed.clear();
    		ypos++;
    		counter++;
    		break;
    	      case 2:
    		sprname[npos]=parsed;
    		parsed.clear();
    		npos++;
    		counter=0;
    		break;
    	      }
    	    }
    	}
        }
    }
    Notice the bolded line, I have this so I can see each piece of that file it parses.
    Now when I run it, it should output EVERYTHING in pieces, right?
    For example:
    5
    20
    MidGreen
    ...
    etc, right?
    Well, what's happening is this:
    MidGreen
    LeftGreen
    RightGreen
    ...
    and it's skipping all the numbers which are very crucial. This strikes me as very odd, but I'm sure I have a slip-up somewhere in my code.
    I appreciate your help greatly, and any future help as well!

    EDIT:
    Daved, the data vector size is 3 (I've cut the file it reads down to those three lines I've shown you above) and it runs the for loop 3 times, all seems in order there.
    Last edited by jmd15; 07-24-2007 at 01:25 PM.
    Trinity: "Neo... nobody has ever done this before."
    Neo: "That's why it's going to work."
    c9915ec6c1f3b876ddf38514adbb94f0

  5. #5
    Sweet
    Join Date
    Aug 2002
    Location
    Tucson, Arizona
    Posts
    1,820
    Code:
    #include <iostream>
    #include <string>
    #include <vector>
    #include <sstream>
    
    std::vector<std::string> ParseString(const std::string &parse);
    
    int main()
    {
    	std::string valueString = "5;20;MidGreen";
    
    	std::vector<std::string> parsedStrings = ParseString(valueString);
    
    	for(size_t i = 0; i < parsedStrings.size(); i++){
    		std::cout<<parsedStrings[i]<<std::endl;
    	}//for
    
    	std::cin.get();
    }
    
    std::vector<std::string> ParseString(const std::string &parse)
    {
    	std::istringstream iss(parse);
    	std::vector<std::string> retVal;
    	std::string value;
    
    	while(getline(iss, value, ';')){
    		retVal.push_back(value);
    	}//while
    
    	return retVal;
    }
    Works for me?

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    What happens if you add cout<< *iter <<endl; above the while loop to output the entire line?

  7. #7
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by jmd15 View Post
    Code:
    for(iter=data.begin();iter!=data.end();iter++)
    Just a little nit. It's inefficient to call vector<T>::end() in a loop condition. Unless data is going to change inside this loop, you should get the end iterator once and compare directly against it:

    Code:
    for(iter = data.begin(), end = data.end(); iter != end; ++iter)
    A very smart optimizing compiler MIGHT be able to determine that data can't change, and optimize away the call to end() -- but I wouldn't count on it.

  8. #8
    C++ Enthusiast jmd15's Avatar
    Join Date
    Mar 2005
    Location
    MI
    Posts
    532
    I'll incorporate that suggestion brewbuck, thanks for that.
    Also, I've found the problem.
    The problem was.... a stray semi-colon...
    Notice in my last post, with the code of the current function, the while loop:
    Code:
    while(getline(iss,parsed,';'));
    That single semi-colon prevent it from looping through and running more than just that first time because it ended that line.
    That goes to show how much a single misplaced character can throw off a program, eh?
    I feel really stupid right now, but I'm glad to have found and fixed the problem. Everything's working as it should. Thanks everybody!
    Trinity: "Neo... nobody has ever done this before."
    Neo: "That's why it's going to work."
    c9915ec6c1f3b876ddf38514adbb94f0

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Compiling sample DarkGDK Program
    By Phyxashun in forum Game Programming
    Replies: 6
    Last Post: 01-27-2009, 03:07 AM
  2. Seg Fault in Compare Function
    By tytelizgal in forum C Programming
    Replies: 1
    Last Post: 10-25-2008, 03:06 PM
  3. Calling a Thread with a Function Pointer.
    By ScrollMaster in forum Windows Programming
    Replies: 6
    Last Post: 06-10-2006, 08:56 AM
  4. Game Pointer Trouble?
    By Drahcir in forum C Programming
    Replies: 8
    Last Post: 02-04-2006, 02:53 AM
  5. <Gulp>
    By kryptkat in forum Windows Programming
    Replies: 7
    Last Post: 01-14-2006, 01:03 PM