problems with pointers

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • olf
    New Member
    • Jan 2007
    • 5

    problems with pointers

    Hello all,
    I have very recently trying to make a small program in c++ and I am having problems with pointers.

    I want to read a line from a file, send that line to a function that parses and stores the lines content.
    So I have my

    getline (myfile,line,'\ n');
    fillData(line);

    functions, where fillData obviously is the parser/storing function and line is a simple string.

    fillData is declared as: void fillData(string line);

    All fillData does at the moment is: string first = strtok(line, ' ');.
    But even these simple things give me errors. And I am assuming it is because I have to use pointers and references to acctually make it work but I just cant seem to figure it out.
    So Im hoping that I can get some help here.

    Thanks in advance.
    /Olle
  • Banfa
    Recognized Expert Expert
    • Feb 2006
    • 9067

    #2
    It would be helpful if you could post a more complete version of your code as well as saying what platform (computer/OS) and compiler you are using.

    Comment

    • olf
      New Member
      • Jan 2007
      • 5

      #3
      Of course, sorry for leaving less information than needed.
      Im sitting on WinXp and using Visual c++ 6.0.
      The complete code looks like the following at the moment:

      Code:
      #include "stdafx.h"
      #include <iostream>
      #include <fstream>
      #include <string>
      #include <list>
      #include <map>
      
      using namespace std;
      
      class Io{
      	public:	
      		void readFile();
      	private:
      		void fillData(string * line);
      };
      
      void Io::fillData(string * line){
      	char * first = strtok(line.c_str(), ' ');
      }
      
      void Io::readFile() {
      	string line;
      	ifstream myfile;
      	myfile.open ("data.txt");
      
      	if (myfile.is_open()){
      		while (! myfile.eof() ){
      			getline (myfile,line,'\n');
      			fillData(line);
      			cout << line << endl;
      		}
      		myfile.close();
      	}
      	else cout << "Unable to open file"; 
      }
      
      int main(int argc, char* argv[]){
      	Io io;
      	io.readFile();
      	return 0;
      }
      I hope this clears things up a bit, and thanks for taking the time to reply.

      /Olle
      Last edited by Banfa; Jan 25 '07, 02:19 PM. Reason: Added [code]...[/code] round the code

      Comment

      • Banfa
        Recognized Expert Expert
        • Feb 2006
        • 9067

        #4
        Sofar all your problems are related to the method fillData

        Code:
        void Io::fillData(string * line){
        	char * first = strtok(line.c_str(), ' ');
        }
        
        void Io::readFile() {
        	string line;
        ...
        	fillData(line);
        ...
        }
        fillData takes a string * as its parameter, in read file you call it with a string, this causes an error the line that calls fillData should be

        fillData(&line) ;

        The you can a similar mistake in fillData using

        line.c_str()

        where you should have

        line->c_str()

        (BTW I thing fillData would be better if it took a reference to a string as a parameter string &, in this case neither of these other changes are required.)

        Even if you fix those 2 problems you still have one more problem. strtok (unlike many other string library functions) has a char * parameter because it actually alters the string that it points to. string::c_str() returns const char * because it is not will to release control of its buffers.

        You can not pass the return of string::c_str() directly to strtok because of this const qualifier difference.

        What you will need to do is copy the data out of the string first into a modifiable character array. To make sure the array is big enough you will need to dynamically allocate it on the fly.

        logically fillData needs to do this

        Code:
        fillData(string *line){
            Allocate char array buffer large enough to hold string in line
            Copy from line to the char array
            Use strtok to tokenise the char array and store the data
            Free the allocated char array
        }

        Comment

        • RedSon
          Recognized Expert Expert
          • Jan 2007
          • 4980

          #5
          Originally posted by Banfa
          Code:
          fillData(string *line){
              Allocate char array buffer large enough to hold string in line
              Copy from line to the char array
              Use strtok to tokenise the char array and store the data
              Free the allocated char array
          }
          But wait Banfa, that code doesnt compile!!!! Help!

          Comment

          • olf
            New Member
            • Jan 2007
            • 5

            #6
            Thank you very much for the help, I got that part to work now.

            /Olle

            Comment

            • olf
              New Member
              • Jan 2007
              • 5

              #7
              A few more problems have arised and I hope that it is ok if I ask more questions.
              I have now read and tokenized the strings. What I want to do know is to create numerous structures that hold the information that I have read.
              The thing that I am working on involves trains in a train network. So I want to store information about the trains in one type of struct and information about the tracks in another type.
              So basically I want two separate lists of structures.
              Am I right in assuming that I will have to pass along these lists throughout the functions? Ie create them in main, pass them to readFile and then pass them to fillData where each train/node is assigned values.

              The whole program now looks like
              Code:
              #include "stdafx.h"
              #include <iostream>
              #include <fstream>
              #include <sstream>
              #include <string>
              #include <list>
              #include <map>
              
              using namespace std;
              
              //The segment information, one or more located inside each node
              struct segInf{
              	string name;
              	int oneDist;
              	int length;
              	int maxSpeed;
              };
              
              //junction information, connections between nodes may contain junctions
              struct junction{
              	string name;
              	int maxSpeed;
              };
              
              //the nodes that make up the graph
              struct Node{
              	list <segInf> segList;
              	map < string , list < junction > > zerolist;
              	map < string , list < junction > > onelist;
              };
              
              struct Train{
              	string name;
              	string currnode;
              	string ednstation;
              	int maxspeed;
              };
              
              class Io{
              	public:	
              		void readFile(Train* trainlist[], Node* nodelist[]);
              	private:
              		void fillData(string& line);
              };
              
              void Io::createTrain(string name, string currnode, string endstn, int maxspeed){
              	Train train;
              	train.name = name;
              	train.currnode = currnode;
              	train.ednstation = endstn;
              	train.maxspeed = maxspeed;
              }
              
              void Io::fillData(string& line){
              	char temp[30];
              	memset( temp, '\0', 30 );
              	line.copy(temp, 30);
              	string first = strtok(temp, " ");
              	//find out what type of line we read - train or node
              	if(first.compare("train") == 0){
              		cout << "train" << endl;
              		string name = strtok(NULL, " ");
              		string currnode = strtok(NULL, " ");
              		string endstn = strtok(NULL, " ");
              		string max = strtok(NULL, " ");
              		std::istringstream i(max);
              		int maxspeed;
              		i >> maxspeed;
              		//assign values to a train struct
              	}
              	else if(first.compare("node") == 0){
              		cout << "node" << endl;
              	}
              }
              
              void Io::readFile(Train* trainlist[], Node* nodelist[]) {
              	string line;
              	ifstream myfile;
              	myfile.open("data.txt");
              
              	if (myfile.is_open()){
              		while (! myfile.eof() ){
              			getline (myfile,line,'\n');
              			fillData(line);
              		}
              		myfile.close();
              	}
              	else cout << "Unable to open file";
              }
              
              int main(int argc, char* argv[]){
              	Train trainlist[];
              	Node nodelist[];
              	Io io;
              	io.readFile(trainlist, nodelist);        
              	return 0;
              }
              There are several things that are both wrong and that bothers me. Lets start with the temp-array in fillData, it feels horribly wrong to declare it with a static size. I think I should be able to read the length of line and declare it with that size but I just cant get that to work.
              The same problem arises with the trainlist and the nodelist in main.
              The other problem is how I pass the two lists in main correctly through to the other functions. Since I want to use the data later on I thought I would take them as references in readFile and fillData, but that turns out to be impossible as "arrays of references are illegal".

              Turned out to be a very long post, I hope its not as confusing for you guys as it is for me and I hope that you might be able to help me, at least with some parts of it.
              If you could do as Banfa did and provide explanations it would also be great as I get the feeling that these things are very basic and are bound to turn up again. So I want to try and learn how things work and not just get a quick solution.

              Thanks for taking the time to read and reply.

              /Olle

              Comment

              • Banfa
                Recognized Expert Expert
                • Feb 2006
                • 9067

                #8
                Originally posted by RedSon
                But wait Banfa, that code doesnt compile!!!! Help!
                You had better be joking...

                <looks round for pointy stick>

                Comment

                • Banfa
                  Recognized Expert Expert
                  • Feb 2006
                  • 9067

                  #9
                  Originally posted by olf
                  A few more problems have arised and I hope that it is ok if I ask more questions.
                  Absolutly not, we have a strict quota of 1 question per poster per week...


                  oh hang on that's not right, we don't have any quota at all :p

                  OK sarcasm aside please ask as many questions as you like generally we will attempt to answer them all.

                  Originally posted by olf
                  I have now read and tokenized the strings. What I want to do know is to create numerous structures that hold the information that I have read.
                  The thing that I am working on involves trains in a train network. So I want to store information about the trains in one type of struct and information about the tracks in another type.
                  So basically I want two separate lists of structures.
                  Am I right in assuming that I will have to pass along these lists throughout the functions? Ie create them in main, pass them to readFile and then pass them to fillData where each train/node is assigned values.
                  Well sort of, however at this point I am not sure you have a good class hierarchy and you need to get that right first.

                  You have an IO class, this reads the file and creates trains. This is not good, trains are nothing to do with file IO, additionally you have your train and node lists in main. You have trains, nodes (not clear to me exactly what this represents), junctions and segments (track segments?). What you don't have is a Network class.

                  In my mind the network would be the top level, every train, junction, node and segement must belong to a rail network and this should be represented. The network would then contain the lists of trains etc and in main you would have a single declaration of a single network instance.

                  The network would contin the functions to load the data from a file but because it also contains the lists of trains etc there would then be no need to pass these around so you could write straight to them.

                  I would re-write functions like void Io::createTrain (...) as a constructor of the train struct (I might make a class to).

                  What you are aiming for is each class/structure accessing its own data and a reduction of class/structure data access externally to the clss/structure.

                  Remember the only difference between a class and a struct is that a class members have a default access of private and a struct memebers have a default access of public.

                  The IO class is not helpful because it does not excapsulate anything real.



                  Originally posted by olf
                  There are several things that are both wrong and that bothers me. Lets start with the temp-array in fillData, it feels horribly wrong to declare it with a static size. I think I should be able to read the length of line and declare it with that size but I just cant get that to work.
                  It feels horrible because it is horrible, and it is also asking for trouble. Dynamically allocating the data is not hard
                  Code:
                  void Io::fillData(string& line){
                  	char *temp = new char[line.length()+1];// +1 for terminator
                  
                  	if (temp != NULL) // Just check the memory allocation worked
                  	{
                  		// Copy line totemp and then terminate the string
                  		line.copy(temp, line.length());
                  		temp[line.length()] = '\0';
                  
                  		// <snipped tokenising code>
                  
                  		delete[] temp;
                  	}
                  	else
                  	{
                  		// Memory allocation failure handling code
                  	}
                  }
                  Originally posted by olf
                  The same problem arises with the trainlist and the nodelist in main.
                  Look up the C++ standard containers vector, deque, list, map, set. These handle dynamically sized lists for you and are well worth learning because once you know them you will use them all the time. I would have thought either list or map would suit this application.

                  Originally posted by olf
                  The other problem is how I pass the two lists in main correctly through to the other functions. Since I want to use the data later on I thought I would take them as references in readFile and fillData, but that turns out to be impossible as "arrays of references are illegal".
                  As I explained above a "Network" class contining the train etc lists will solve this as its member functions will have access to its member data so there will be no need to pass the data around.

                  Comment

                  • olf
                    New Member
                    • Jan 2007
                    • 5

                    #10
                    Once again, thanks for the help, explanations and opinions.
                    Its very appreciated and now I have something to read and do.
                    I will very likely get back with more questions during or after the weekend.

                    Thanks alot!

                    /Olle

                    Comment

                    Working...