1

I am trying to make a city distance calculator using the longitude and latitude of a city. The problem I am having is putting the cities into an array. My array attempt is commented out in the main method. Please let me know what I am doing wrong.

#include <iostream>
#include <math.h>
#define pi 3.14159265358979323846

using namespace std;

double distance(double lat1, double lon1, double lat2, double lon2, char unit);
double deg2rad(double deg);
double rad2deg(double rad);

class City
{
public:
    //declare variables
    string name;
    double latitude;
    double longitude;

    City(string, double, double); //constructor
    double distance(string, string);
};

double cityDistance(City a, City b);

int main() {

    //construct cities
    City Providence("Providence", 41.8239890, -71.4128340);
    City Cranston("Cranston", 41.7798230, -71.4372800);
    City NewYork("NewYork", 40.7143530, -74.0059730);
    City Boston("Boston", 42.3584310, -71.0597730);
    City Killington("Killington", 43.6775680, -72.7798250);
    City Springfield("Springfield", 42.1014830, -72.5898110);
    City Bridgeport("Bridgeport", 41.1865480, -73.1951770);
    City Cambridge("Cambridge", 42.3736160, -71.1097340);
    City Norwalk("Norwalk", 41.1175970, -73.4078970);
    City Quincy("Quincy", 42.2528770, -71.0022710);

    //put city into array
//  City cityArray[] = { };
//  cityArray[0] = {"Providence", 41.8239890, -71.4128340};
//  cityArray[1] = {"Cranston", 41.7798230, -71.4372800};
//  cityArray[2] = {"NewYork", 40.7143530, -74.0059730};
//  cityArray[3] = {"Boston", 42.3584310, -71.0597730};
//  cityArray[4] = {"Killington", 43.6775680, -72.7798250};
//  cityArray[5] = {"Springfield", 42.1014830, -72.5898110};
//  cityArray[6] = {"Bridgeport", 41.1865480, -73.1951770};
//  cityArray[7] = {"Cambridge", 42.3736160, -71.1097340};
//  cityArray[8] = {"Norwalk", 41.1175970, -73.4078970};
//  cityArray[9] = {"Quincy", 42.2528770, -71.0022710};

    //calculate distance
    cout << "Distance between Providence and Cranston: " << distance(41.8239890, -71.4128340, 41.7798230, -71.4372800, 'M') << endl;
    cout << "Distance between NewYork and Boston: " << distance(40.7143530, -74.0059730, 42.3584310, -71.0597730, 'M') << endl;
    cout << "Distance between Killington and Norwalk: " << distance(43.6775680, -72.7798250, 41.1175970, -73.4078970, 'M') << endl;

    //print distance using city name
    cout << endl;
    cout << "Distance between Providence and Cranston: " << cityDistance(Providence, Cranston) << endl;
    cout << "Distance between NewYork and Boston: " << cityDistance(NewYork, Boston) << endl;
    cout << "Distance between Killington and Norwalk: " << cityDistance(Killington, Norwalk) << endl;

    //end
    return 0;
}

City::City(string n, double lt, double lg)
{
    name = n;
    latitude = lt;
    longitude = lg;
}

double deg2rad(double deg)
{
    return (deg * pi / 180);
}

double rad2deg(double rad)
{
      return (rad * 180 / pi);
}

double distance(double lat1, double lon1, double lat2, double lon2, char unit)
{
    double theta, dist;
    theta = lon1 - lon2;
    dist = sin(deg2rad(lat1)) * sin(deg2rad(lat2)) + cos(deg2rad(lat1)) * cos(deg2rad(lat2)) * cos(deg2rad(theta));
    dist = acos(dist);
    dist = rad2deg(dist);
    dist = dist * 60 * 1.1515;
    switch(unit) {
        case 'M':
            break;
        case 'K':
            dist = dist * 1.609344;
            break;
        case 'N':
            dist = dist * 0.8684;
            break;
      }
      return(dist);
}


double cityDistance(City a, City b)
{
    return distance(a.latitude, a.longitude, b.latitude, b.longitude, 'M');
}
2
  • 2
    You should use std::vector for this. I also suggest creating an enum for unit. Commented Jan 31, 2014 at 20:13
  • <math.h> already defines pi as M_PI for you. Commented Jan 31, 2014 at 20:57

4 Answers 4

4

The way you do it now is you create an array of size 0. Then you try to put your cities in non-existent cells 0 to 9.

One way to solve that issue is to declare an array of size 10 without specifying content at the declaration point.

City cityArray[10];

And then assign each cell individually as you do. This, however is not the best solution and it won't even work, because you haven't defined a default parameterless constructor.

You can instead create an array whith cities you exactly want your array to hold. See code below.

If you want to use struct-like initialization, like you do, the code would go like this:

//put city into array
City cityArray[] = {
  {"Providence", 41.8239890, -71.4128340},
  {"Cranston", 41.7798230, -71.4372800},
  {"NewYork", 40.7143530, -74.0059730},
  {"Boston", 42.3584310, -71.0597730},
  {"Killington", 43.6775680, -72.7798250},
  {"Springfield", 42.1014830, -72.5898110},
  {"Bridgeport", 41.1865480, -73.1951770},
  {"Cambridge", 42.3736160, -71.1097340},
  {"Norwalk", 41.1175970, -73.4078970},
  {"Quincy", 42.2528770, -71.0022710}
};

However, you have defined a constructor for the class City, therefore, this won't compile. You can do it like this instead:

City cityArray[] = {
  City("Providence", 41.8239890, -71.4128340),
  City("Cranston", 41.7798230, -71.4372800),
  City("NewYork", 40.7143530, -74.0059730),
  City("Boston", 42.3584310, -71.0597730),
  City("Killington", 43.6775680, -72.7798250),
  City("Springfield", 42.1014830, -72.5898110),
  City("Bridgeport", 41.1865480, -73.1951770),
  City("Cambridge", 42.3736160, -71.1097340),
  City("Norwalk", 41.1175970, -73.4078970),
  City("Quincy", 42.2528770, -71.0022710)
};

You could also reuse City objects you have just created above:

City cityArray[] = {
  Providence,
  Cranston,
  NewYork,
  Boston,
  Killington,
  Springfield,
  Bridgeport,
  Cambridge,
  Norwalk,
  Quincy
};

But in the code above, you have to be aware that the objects Providence, Cranston etc. will be copied to the array. Therefore you will have two independent copies of the same data, e.g. one in Providence variable and one in cityArray[0]. Changing one won't affect the other.

Whatever case you choose, this will create an array of fixed size (as all arrays in c++ have a fixed size). You cannot add any more cities.

If you want your array to be 'extendable' - you would like to add new cities to it in the future, then instead of an array you should use one of the STL collections. Such as vector<City> or map<City>. Map is especially useful if you intend to search the collection for a specific city, e.g. by its name.

Sign up to request clarification or add additional context in comments.

5 Comments

What if he wants to add a city to the array later on?
@olevegard Then he needs to either resize the array manually, or use a construct like std:vector
This isn't really an "array of size 0", but rather an array where the size is determined by the compiler.
@ZacHowland yes, you're right. Though the size determined by the compiler will be 0. What I've meant is that the eventual effect will be an array of size 0. I dind't want to complicate it more than necessary for the OP to easily understand the answer.
@ciamej "Though the size determined by the compiler will be 0." That is incorrect. The size determined by the compiler (for the code you have written) will be 10.
3

This is a great example of when to use std::vector or std::map. In this particular case, I think std::map would be the better choice (since you wouldn't have to iterate the entire list to find 2 cities you are looking for):

std::map<std::string, City> cities;
cities["Providence"] = City("Providence", 41.8239890, -71.4128340);
// ...

Example

Comments

2

Arrays are not dynamic in C++. You'd need to declare your array with the exact size you're going to need. You can't also populate a class with that notation, it's not a valid C++ construct since you didn't declare a default constructor. Try something like this:

//put city into array
City cityArray[9];
cityArray[0].name = "Providence";
cityArray[0].latitude = 41.8239890;
cityArray[0].longitude = -71.4128340;
cityArray[1] = ...

You could of course make it a little less verbose, and make it dynamic, using the constructor for your class and an STL container like vector.

explicit vector<City*> cityArray(9);
cityArray.push_back(new City("Providence", 41.8239890, -71.4128340));
...

The argument (size) in the vector's constructor is optional, but you'll get better performance if you explicitly tell it to reserve memory for the most likely number of cities you're going to store. The vector will grow automatically if that limit is surpassed.

6 Comments

City cityArray[] = ... is valid C++ syntax and is absolutely valid C++. It is not a dynamic array, but rather an array who's size is determined by the compiler.
@ZacHowland Mmm... well it is valid syntax, but it won't compile because of the constructor he made. So that's what I meant. How would I call that... "it's not a valid construct"?
In that case, your suggestion should be to eliminate the constructor he did define so that the implicit default constructor is available. And I would caution against using the dynamic memory version as it is not necessary at all, and opens the door to potential memory leaks.
It might as well be, but it's only a suggestion. Perhaps it would be better to suggest the creation of the default constructor so both options are available. As for the dynamic memory version, won't the City be copied?
If he declares a default constructor, he should follow the rule of 3 (which the example in my post does). For the dynamic memory issue: if the vector goes out of scope without him freeing the memory that has been allocated, he just leaked all of that memory. It would be better to either declare a copy-constructor (again, with the rule of 3) or use the default copy-constructor and push the actual instance into the vector - not a pointer to the instance.
|
0

Use this

City cityArray[10] = { 
     City ("Providence", 41.8239890, -71.4128340),
    City ("Cranston", 41.7798230, -71.4372800),
    City ("NewYork", 40.7143530, -74.0059730),
    City ("Boston", 42.3584310, -71.0597730),
    City ("Killington", 43.6775680, -72.7798250),
    City ("Springfield", 42.1014830, -72.5898110),
    City ("Bridgeport", 41.1865480, -73.1951770),
    City ("Cambridge", 42.3736160, -71.1097340),
    City ("Norwalk", 41.1175970, -73.4078970),
    City ("Quincy", 42.2528770, -71.0022710)
 };

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.