I am writing a program to compute the fastest/shortest path between locations (stored in a directed graph represented by an adjacency list). I am trying to create this adjacency list ("al") as an array of pointers to Vertex class objects, but I get the error " 'al' was not declared in this scope". Any suggestions on where I should create the adjacency list to avoid scope problems would be greatly appreciated.

Description of the files:

  • main.cpp - Reads in input files
  • vertex.cpp and vertex.h - Define the Vertex class
  • segment.cpp and segment.h - Define the Segment class
  • locations.txt - Input file containing the number and names of locations, each of which should be a vertex
  • segments.txt - Input file containing information about the segments connecting the vertices. Each line has four values: vertex number where segment begins, vertex number where segment ends, distance of segment, traffic speed on segment
  • trips.txt - Trip requests

The text files must be input to the program in this order: locations.txt segments.txt trips.txt

Attachments
# LOCATIONS

# number of locations
15

# intersections
1st St & 101st Ave
1st St & 102nd Ave
1st St & 103rd Ave
2nd St & 101st Ave
2nd St & 102nd Ave
2nd St & 103rd Ave
3rd St & 101st Ave
3rd St & 102nd Ave
3rd St & 103rd Ave

# Freeway North locations
I-94 North @ 101st Ave
I-94 North @ 102nd Ave
I-94 North @ 103rd Ave

# Freeway South locations
I-94 South @ 101st Ave
I-94 South @ 102nd Ave
I-94 South @ 103rd Ave
#include "iostream"
#include "fstream"

#include "vertex.h"
// segment.h is not included because it is included in vertex.h

using namespace std;

int main(int argc, char** argv)
{
  if(argc != 4) // check for the correct number of inputs
    {
      cerr << "Incorrect number of inputs." << endl;
      return -1;
    }

  // Read the location file
  int numLocations = 0;
  int vertexNumber = 0;
  ifstream myLocations(argv[1]);
  if(myLocations) 
    {
      string locLine;
      string junkR;
      while(getline(myLocations, locLine, '\r')) // break the file into lines 
	{
	  getline(myLocations, junkR, '\n'); // remove the first character (\n) from each line
	  char * convline = new char[locLine.size() + 1]; // convert string to char *
	  strcpy(convline, locLine.c_str());
	  if(locLine.empty() == 1) // ignore empty strings
	    {
	      cout << "Empty line ignored." << endl;
	    }
	  else
	    {
	       if(convline[0] != '#') // add locations to the graph
	       {
	         if(numLocations == 0) // check for the line containing the number of locations
	           {
		     numLocations = atoi(convline);
		     cout << "numLocations = " << numLocations << endl;

		     // create the adjacency list
		     Vertex ** al; 
		     al = new Vertex * [numLocations];
		   }
	         else
	           {
		     cout << "Add the line to the graph: \t" << convline  << endl;
		     
		     // set the first value of the adjacency list to a new vertex
		     Vertex *  v; // should this be a pointer or not?
		     v = new Vertex;
		     v->changeName(convline);
		     cout << "vertex v made" << endl;

		     // set the ID of the vertex
		     v->changeID(vertexNumber);

		     /*
		     // "insert" the vertex into the adjacency list (with pointers)
		     al[vertexNumber] = v;

		     vertexNumber++;
		     */
	
		     }
	       }
	      else // ignore comments
	         {
	           cout << "Comment ignored." << endl;
	         }
	    }
	  cout << endl;
	}
    }

  else if(!myLocations)  // if the location file can't be read, error and exit
    {
      cerr << "The locations file could not be read." << endl;
      exit(2);
    }

  // Read the segment file

  int numSegments = 0;
  ifstream mySegments(argv[2]);
  if(mySegments)
    {
      string segLine;
      string junkR;
      while(getline(mySegments, segLine, '\r')) // break the file into lines 
	{
	  getline(mySegments, junkR, '\n'); // remove the first character (\n) from each line
	  char * csegline = new char[segLine.size() + 1]; // convert string to char *
	  strcpy(csegline, segLine.c_str());
	  if(segLine.empty() == 1) // ignore empty strings
	    {
	      cout << "Empty line ignored." << endl;
	    }
	  else
	    {
	       if(csegline[0] != '#') // add locations to the graph
	       {
	         if(numSegments == 0) // check for the line containing the number of locations
	           {
		     numSegments = atoi(csegline);
		     cout << "numSegments = " << numSegments << endl;
		   }
	         else
	           {
		     cout << "Add the segment to the graph: \t" << csegline  << endl;
		   }
	       }
	      else // ignore comments
	         {
	           cout << "Comment ignored." << endl;
	         }
	    }
	  cout << endl;
	}
  
    }
  else if(!mySegments) // if the segment file can't be read, error and exit
    {
      cerr << "The segments file could not be read." << endl;
      exit(3);
    }

  // Read in the trip request file

  int numTrips = 0;
  ifstream myTrips(argv[3]);
  if(myTrips) 
    {
      string tripLine;
      string junkR;
      while(getline(myTrips, tripLine, '\r')) // break the file into lines 
	{
	  getline(myTrips, junkR, '\n'); // remove the first character (\n) from each line
	  char * ctripline = new char[tripLine.size() + 1]; // convert string to char *
	  strcpy(ctripline, tripLine.c_str());
	  if(tripLine.empty() == 1) // ignore empty strings
	    {
	      cout << "Empty line ignored." << endl;
	    }
	  else
	    {
	       if(ctripline[0] != '#') // add locations to the graph
	       {
	         if(numTrips == 0) // check for the line containing the number of locations
	           {
		     numTrips = atoi(ctripline);
		     cout << "numTrips = " << numTrips << endl;
		   }
	         else
	           {
		     cout << "Processing this trip request: \t" << ctripline  << endl;
		   }
	       }
	      else // ignore comments
	         {
	           cout << "Comment ignored." << endl;
	         }
	    }
	  cout << endl;
	}
    }

  else if(!myTrips)  // if the trip request file can't be read, error and exit
    {
      cerr << "The trip request file could not be read." << endl;
      exit(4);
    }


  return 0;
}
#include "segment.h"
#include <iostream>

Segment::Segment()
{
  // do something
}

Segment::~Segment()
{
  // destruct things
}
#ifndef _SEGMENT_H
#define _SEGMENT_H

class Segment
{
 public:
  Segment();
  ~Segment();

 private:
  // something
};

#endif
# ROAD SEGMENTS

# number of road segments
40

# 1st St
0 1 1.5 30.0
1 0 1.5 27.5
1 2 2.0 30.5
2 1 2.0 27.5

# 2nd St
3 4 1.5 26.5
4 3 1.5 28.0
4 5 2.0 30.2
5 4 2.0 24.5

# 3rd St
6 7 1.5 29.0
7 6 1.5 28.5
7 8 2.0 35.2
8 7 2.0 32.5

# 101st Ave
0 3 2.3 37.5
3 0 2.3 37.4
3 6 2.5 39.2
6 3 2.5 38.5

# 102nd Ave
1 4 2.3 30.3
4 1 2.3 32.5
4 7 2.5 31.5
7 4 2.5 30.9

# 103rd Ave
2 5 2.3 42.6
5 2 2.3 40.5
5 8 2.5 42.8
8 5 2.5 43.2

# I-94 North
11 10 2.75 57.6
10 9 3.2 59.3

# I-94 on and off ramps
0 9 0.05 40.1
9 0 0.05 39.5
4 10 0.1 37.1
10 4 0.1 39.0
8 11 0.07 35.4
11 8 0.07 37.6

# I-94 South
12 13 2.75 60.0
13 14 3.2 59.5

# I-94 on and off ramps
0 12 0.06 40.0
12 0 0.06 40.5
4 13 0.09 38.5
13 4 0.09 39.0
8 14 0.08 41.5
14 8 0.08 37.5
# TRIPS

# number of trips to analyze
4

# the trips
0 8 D
1 8 T
2 7 T
12 14 D
#include "vertex.h"
#include <iostream>

using namespace std;

Vertex::Vertex()
{
  // do something
}

Vertex::~Vertex()
{
  // destruct things
}

int Vertex::changeName(char * inputname)
{
  int length;
  length = strlen(inputname);
  Vertex::name = (char *) malloc (length);
  strcpy(Vertex::name, inputname);
  return 0;
}

char * Vertex::returnName()
{
  char * namecopy; 
  int length;
  length = strlen(Vertex::name);
  namecopy = (char *) malloc (length);
  strcpy(namecopy, Vertex::name); 
  cout << "returnName() called" << endl;
  return namecopy;
}

int Vertex::changeID(int IDinput)
{
  Vertex::ID = IDinput;
  return 0;
}

int Vertex::returnID()
{
  return Vertex::ID;
}
#ifndef _VERTEX_H
#define _VERTEX_H

#include "segment.h"

class Vertex
{
 public:
  Vertex(); // constructor
  ~Vertex(); // destructor
  int changeName(char *);
  char * returnName();
  int changeID(int IDinput);
  int returnID();

 private:
  char * name;
  int ID; // is this necessary or does the location in the adjacency list serve as ID?
  Segment * edgeList; // pointer to first node in a list of outgoing edges

};

#endif

You didn't include <string> header in main.cpp (for std::getline declaration). Change "iostream" and "fstream" to <iostream> and <fstream> (standard headers).

You declare al variable in the if alternative block. Of course, this local variable is out of scope outside this block. Declare al at the main function body level - that's all.

Now you have:

if (numLocations == 0)
  { // it's a new scope
    Vertex ** al; // al is local in if alternative
    al = new Vertex * [numLocations]; // to breath al's last
  } // al is out of scope and is discarded.
  // and you have memory leak because can't free this memory

Thanks a lot, ArkM! So even though the line

al = new Vertex * [numLocations];

is declared on a local level, I can still free the memory from outside that level?

You can deallocate dynamically allocated memory here, there and everywhere:

int main()
{
  al = new Vertex*[numLocations];
  ...
  delete [] al; // al is visible
  ...
  // or
  f(al); // al as argument
  ...
}
...
void f(Vertex* p)
{
  delete [] p; // array of Vertex is deallocated
  ...
}

Name scope (name visibility) and storage duration (span of life) are different notions. In actual fact to deallocate memory obtained from operator new you need not al variable per se but the pointer value which refers to the memory chunk.

Comments
helpful, clear, concise
This question has already been answered. Start a new discussion instead.