Show 80 post(s) from this thread on one page
Page 1 of 2 12 Last
• 09-18-2004
alvifarooq
hi guys...ok i have a .txt file like this:

city canberra 149.0 145.0
city hobart 142.0 137.0
start sydney
goal hobart

you get the structure...the numbers are the x,y coordinates of the cities...and conn indicated which cities are connected together...

i need to read in all this and make a node for each city...save its corresponding info. into the node...i can read the file...my code is give below...im using a vector of nodes to save all the nodes generated...could someone help me correct this...i get runtime errors...ive just tried the first part which is making nodes corresponding to cities and storing their x, y valyes...

This is my node class:

Code:

``` class Node         {         public:                                 Node *parent;                 float g; // cost of this node + its parents                 float h; // heuristic estimate                 float f; // g + h                                 string CityName;                                 int x,y;         }; //this is the readfile function i have so far:         //Reads the contents of the input file         void readFile()         {           char check[6];           int counter1 = 0;           int counter2 = 0;           float cords[20];           vector <string> mystring(200);           vector <Astar::Node *> CityNode;  //Node is in Astar class           ifstream fin ("inputfile.txt");           while (! fin.eof() )           {               fin >> check;       if (strcmp(check, "city") == 0)       {           fin >> mystring[counter1];           CityNode[0] -> CityName = mystring[counter1];           counter1++;           fin >> cords[counter2];           CityNode[counter1] -> x = cords[counter2];           counter2++;           fin >> cords[counter2];           CityNode[counter1] -> y = cords[counter2];           counter2++;           counter1++;       }       if (strcmp(check, "conn") == 0)       {           fin >> mystring[counter1];           counter1++;           fin >> mystring[counter1];           counter1++;       }       if (strcmp (check, "start") ==0)       {           fin >> mystring[counter1];           counter1++;       }       if (strcmp (check, "goal") ==0)       {           fin >> mystring[counter1];           counter1++;       }     }     //to test the vector contents     for (int i = 0; i<counter1; i++)     {       Form1->ListBox1->Items->Add((CityNode[counter1] -> CityName).c_str());     }     return; }```

Error: When I run it, it says access violation at some address...i think it's because of the line:

Code:

``` CityNode[0] -> CityName = mystring[counter1];```
• 09-18-2004
sean
Post your errors and use [code] tags. See the sticky at the top of the forum for instructions.
• 09-18-2004
alvifarooq
it's actually a runtime error...so i need to know how to update the vector of nodes and store the name of the city in the string i have defined in the Node class...

also you can see the structure of the text file...can you suggest a better way of getting all of this data in the Node, meaning:

the new Node should have:
-city name
-corresponding x and coordinates
-type should include whether it is a start or goal node...

and additionally maybe someone can suggest whether i should make a separate edge class or somehow store the connections between cities in a vector of strings in the new Node...

Thanks!!!
• 09-18-2004
always check that the file is open before trying to use it.

to pinpoint the problem, display each variable as it is read from file. Assuming you know the contents of the file you are reading check that the value read in is what you expected. When you've pinpointed the problem the best you can, repost where the error seems to be happening, if you can't figure it out by yourself at that point.

Comment excessively so you know exactly what you are expected a given line to do. I'm suspicious that you are incrementing counters incorectly and end up accessing invalid elements of a vector, leading to the good compile, but run time errors. Without knowing exactly what you are trying to do this can be difficult to pin down though.

Once you fix the errors you can remove all the debugging code/comments you use.
• 09-18-2004
alvifarooq
ya that's what i usually do...i did the commenting thing and the program still gives the same error...i think im messing up in the way i access strings or smth...this is the specific line which causes trouble:

Code:

``` fin >> CityNode[0] -> CityName ;```

in case you don't get it i removed the counters and stuff...now i'm just checking this line...what it is supposed to mean is that: take input from the file and then store it in the CityName string of the 0th vector of nodes...

btw i checked and the file input is correct...i used normal strings to check all that...but why isn't it updating the CityName string in the new Node in the CityNode vector...?

Idea: is it possible that i have to declare the new node first before the fin >> CityNode[0] -> CityName line? or is it already defined...

Regards,

Farooq
• 09-18-2004
jlou
Quote:

Originally Posted by alvifarooq
Idea: is it possible that i have to declare the new node first before the fin >> CityNode[0] -> CityName line? or is it already defined...

I think this is your problem. You declare the CityNode vector, but you don't create any new elements inside it. Then you try to access the first element of an empty vector.

Use push_back to add on a new Node class for each Node you read in. You will probably want to use new to allocate memory for the new Node, and you will have to remember to delete the Nodes that you push_back when you are done to avoid a memory leak.
• 09-18-2004
alvifarooq
ya u're right...this is what i do now and there's this new error which u can identify:

Code:

``` Astar::Node *newNode = new Astar::Node; fin >> newNode -> x; CityNode.push_back ( newNode );```
this works perfectly...i checked and the number of elemnts inside the vector is the same as it should be...BUT i now try printing them out on a list and this is what i use:

Code:

``` for( vector< Astar::Node * >::iterator i = CityNode.begin(); i != CityNode.end(); i ++ )     {         Form1->ListBox1->Items->Add(((*i)->x).c_str());     }```
The error i get has to do with:

Code:

``` (*i)->x)```

The error is: E2294 Structure required on left side of . or .*

What coluld be the problem?

Regards,

Farooq
• 09-18-2004
jlou
You are calling .c_str() on x, which is an int. You should be calling it on CityName.
• 09-18-2004
alvifarooq
thanks works fine now...
one last thing...any suggestions on my initial query...how should i extract the data to nodes effectively from the file...as in names and coordinates of cities is straightforward...

but for connections i think ill have to read from file...loop through all the Nodes in my vector and check against their CityNames and then if i find a match i store it in a string perhaps in my Node class...

do u think this is a good way...seems like a lot of looping to me...any other suggestions?

Regards,

Farooq
• 09-18-2004
jlou
It all depends on how the input file is structured. If all the cities with their coordinates are at the top, then you can load them all in using an overloaded operator >> for you Node class. I'm not sure why the coordinates have their own array. Is there some reason you need the coordinates separate? I would just store them in the Node using the operator>>.

Since the connections use city names, I would use a map instead of a vector to store the Nodes. (A set would be more appropriate, but it is slightly more complicated and I doubt you need the benefits of saved memory). So once you read in all the cities into the map, you can look up the correct Node based on the city name without having to loop through the entire container. This will make it easier to save the connection information.

As far as storing connections, it will depend on what you are trying to do and whether the connections are directed, or whether there can be multiple connections per city. One possible solution is to have a list (or vector or map) of all the cities connected to the current Node. So when you read in a connection, you look up both cities, and add the other city name to the Node's list of connected cities.

Anyway, just some ideas. Like I said, it depends a lot on what you will do with the data after you read it in.
• 09-18-2004
alvifarooq
thanks a lot...i do read using >> and yes there can be multiple connections between cities and the graph is undirected...i'm implementing all of this for an Astar search...

can u elucidate further how i might use a MAP in my program...given the following:

- i need to have a node for each city with its coordinates
- i will need an efficient way to check during looping later, which node is connected to which other node and be able to access both of them at the same time (e.g. to calculate the length between them using their coordinates)...

i read up on MAPs and it says that it's not the best choice for problems in which time is a factor...time is a factor in my application! what're ur ideas about the above...

Thanks...
• 09-18-2004
jlou
I don't know what you read, but the reason a map is a better choice in this situation is because it is faster than just looping through a vector. There are other solutions that might be faster/better than an STL map, including a hash_map if your library has one, or using a vector and then sorting the data after reading it in, but since this is "Urgent", I doubt you have time to figure those out.

The way I would suggest implementing the map is to have the name as the key and the Node as the value. Since the name is already part of the Node, it is a bit of duplication of data, but unless you want to write your own comparison function for Nodes (or Node pointers) it isn't that big of a deal. The string class already has a compare function that works, so using that as the key to the map is easy.

So when you read in each node, insert a new pair into the map with the string name as the key and the Node* pointer that you were putting into the vector as the value instead.

I would then have inside the Node class either a vector or a map (depending on whether you need to lookup specific connected cities or just have a list of them), that holds the names of the connected cities as I mentioned above.

You can still loop through the map of Nodes like you did with the vectors, and for each Node you can see what it is connected to by looking in its list of connected city names. You can then go directly to that city's Node by looking it up in the map. That is the benefit - the lookup of a particular city in the container of Nodes is much faster if you store them in a map than if you store them in a vector.

I hope that helps a little.
• 09-18-2004
alvifarooq
thanks a lot for the advice...following is the code without the use of MAPS for now...i have a vector of strings to store the connections in the Node class and a vector of Nodes to store all the nodes...

you are right...there is a lot of unecessary looping involved through the vector of nodes and since the example i use right now is small it's ok...but if i were given a map with 500 cities...and i would have to do this for all of them, my program would have serious issues...

Code:

``` void readFile() {   char check[20];   string Conn1;   string Conn2;             vector <Astar::Node *> CityNode;   ifstream fin ("inputfile.txt");   while (! fin.eof() )   {       fin >> check;       //IF THE FIRST WORD IN THE FILE IS A CITY       if (strcmp(check, "city") == 0)       {           Astar::Node *newNode = new Astar::Node;           fin >> newNode -> CityName;           fin >> newNode -> x_cord;           fin >> newNode -> y_cord;           CityNode.push_back(newNode);       }       //IF THE FIRST WORD IN THE FILE IS A CONN       if (strcmp(check, "conn") == 0)       {           fin >> Conn1;           fin >> Conn2;           for( vector< Astar::Node * >::iterator i = CityNode.begin(); i != CityNode.end(); i ++ )           {             if (strcmp(((*i)->CityName).c_str(), Conn1.c_str()) == 0)             {                 ((*i)->CityConnections).push_back(Conn2);             }             if (strcmp(((*i)->CityName).c_str(), Conn2.c_str()) == 0)             {                 ((*i)->CityConnections).push_back(Conn1);             }           }       }       //IF THE FIRST WORD IN THE FILE IS START       if (strcmp (check, "start") ==0)       {           fin >> Conn1;           for( vector< Astar::Node * >::iterator i = CityNode.begin(); i != CityNode.end(); i ++ )           {             if (strcmp(((*i)->CityName).c_str(), Conn1.c_str()) == 0)             {                 (*i)->StartGoal = "start";             }           }       }       //IF THE FIRST WORD IN THE FILE IS GOAL        if (strcmp (check, "goal") ==0)       {           fin >> Conn1;           for( vector< Astar::Node * >::iterator i = CityNode.begin(); i != CityNode.end(); i ++ )           {             if (strcmp(((*i)->CityName).c_str(), Conn1.c_str()) == 0)             {                 (*i)->StartGoal = "goal";             }           }       }   } //end of while       return; }```

later on in the Astar search this is what i have to do:

1) begin using the startnode (means i loop once to check which node in my vector has the start attribute)

2) do the search etc etc...

3) now look for the successors of this node (means i go through all the nodes again in the vector to check which nodes are connected to this node)

4) basically ill keep looping between step 2 and 3 until a solution is found...this means that my vector of nodes will be looped through once every time!!!

where does the MAP structure come in...maybe u'll have a better understanding now with the code already there...

thanks a lot again...

Regards,

Farooq
• 09-18-2004
alvifarooq
retracted...
• 09-18-2004
jlou
Might want to start a new thread on that one... I'm not familiar with Borland or its forms and some who are might not see this question down here.
Show 80 post(s) from this thread on one page
Page 1 of 2 12 Last