-3

I know a char can be used as the index in the array. But using string as the index becomes difficult.

For example, I want to record the distance between two cities.

MAP["NewYork"]["Washington"] = 2000;

The only way I know is to

strcpy(city[0], "NewYork"); strcpy(city[1], "Washington");

and use 0 and 1 as the index in MAP

MAP[0][1] = 2000

But things get complicated if I need to calculate the total amount from Places A to B then to C.

I am looking for suggestions as to how my approach to implementing these things can be improved.

ryyker
  • 22,849
  • 3
  • 43
  • 87
jetsai
  • 105
  • 6
  • 3
    You want to use strings for readability? then better use enumerators. `enum city { NewYork, Washington};` then `MAP[NewYork][Washington] = 200;`. Here NewYork corresponds to 0 and Washington to 1. – rsonx Dec 21 '18 at 12:31
  • I have to read city names from the text file. So I couldn't know how many of them in advance – jetsai Dec 21 '18 at 12:38
  • 1
    What you want is a dictionary implementation for C. C standard library does not have this. Try googling for *C hashmap implementation* or something. – hyde Dec 21 '18 at 12:49
  • Or, if this is an exercise and you aren't allowed to use normal C application development resources, you need to roll one yourself. It doesn't have to be a fancy hash map, but in the end you probably want to be able to do something like `MAP[getCityIndex("New York")][getCityIndex("Washington")]`. The trick is to create the function `getCityIndex` and design the data structure backing it. Simplest is just unsorted array of city names, and linear search through it. Next comes sorted array and binary search. Finally most efficient will be a hash table based dictionary. – hyde Dec 21 '18 at 12:57
  • Please define "efficiency"!! – Sourav Ghosh Dec 21 '18 at 13:02
  • Ironically, given that all the comments (and some answers) making statements about C not providing native dictionary support are true,one of the best tutorials of how to implement one in C is found in the classic book: _[C Programming Language](https://www.amazon.com/dp/0131103628/?tag=stackoverflow17-20)_. _[More here](https://stackoverflow.com/a/4384446/645128)_. – ryyker Dec 21 '18 at 15:47
  • 1
    "So I couldn't know how many of them in advance" --> OK, lets set the string-to-index problem aside for a while. Now how are you make the array `MAP` without knowing how many in advance? Wait till all data is read? dynamic allocation? The point is, once that problem is settled, then the best "string-to-index" is readily had. In other words, consider the whole problem. – chux - Reinstate Monica Dec 22 '18 at 02:40

3 Answers3

4

There are no dictionaries in the C language. You need to write it yourself. You may have an array of structures where one member is a string another hold something else. Then you need to implement the function to find the proper structure using the string

0___________
  • 60,014
  • 4
  • 34
  • 74
1

You could also hash your strings.

A hash function can turn a string into a number, then you could modulo(%) it to the maximum map size.

Downside is that there can be collisions(two strings pointing to the same number) which you may have to treat by comparing the original strings themselves, but then you would need to store which string is associated with each number to compare them later.

There are some string hashes discussed in this question.

If you want to read more about hash tables: The wikipedia page might be a good start

0

..."But using string as the index becomes difficult."
..."I want to record the distance between two cities"...

You cannot use a string as an array index, but you can associate a specific array index with a particular string using a combination of an enum (array index) and const char array. The following address the two stated issues above by illustrating how a struct, enum and const char arrays may be used in calulating distances between city locations.

//from Google:
//Longest city name: Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch

#define MAX_NAME 60 //59+1
#define earthRadiusKm 6371.0
#define PI 3.14159265359

enum {
    LAT,
    LON
};

enum {
    NEW_YORK,
    WASHINGTON,
    MIAMI,
    MAX_CITIES
};

typedef struct {
    char sCity[MAX_NAME];
    double lat;
    double lon;
}CITY_LOC;

// Note:
// Normally the following two items would be accessed from a lookup
// table, or database, but for purposes of illustration, will
// include a very abbreviated collection of values for city strings
// and latitude/longitude values here:    
const char cities[MAX_CITIES][MAX_NAME] = {"New York", "Washington", "Miami"};
double lat_lon[MAX_CITIES][2] = {{40.730610, -73.935242},
                                 {38.889931, -77.009003},
                                 {25.761681,  -80.191788}};

double distanceEarth(double lat1d, double lon1d, double lat2d, double lon2d);
double deg2rad(double deg);
double rad2deg(double rad);

int GetCityIndexFromString(char *city);

/// enter two city names
/// use double quotes if city name include spaces. eg. "New York"
int main(int argc, char *argv[])
{
    int i, j;
    double MAP[MAX_CITIES][MAX_CITIES] = {0};
    CITY_LOC cLoc[MAX_CITIES] = {0};

    if(argc != 3)
    {
        printf("Usage: %s <city1> <city2>\nExiting", argv[0]);
        getchar();
        return 0;
    }

    //populate struct
    for(i=0;i<MAX_CITIES;i++)
    {
        strcpy(cLoc[i].sCity, cities[i]);
        cLoc[i].lat = lat_lon[i][LAT];
        cLoc[i].lon = lat_lon[i][LON];
    }

    //calculate distances between all cities
    for(i=NEW_YORK;i<MAX_CITIES;i++)
    {
        for(j=NEW_YORK;j<MAX_CITIES;j++)
        {
            MAP[i][j] = distanceEarth(cLoc[i].lat, cLoc[i].lon, cLoc[j].lat, cLoc[j].lon);
        }
    }

    //distance in kilometers between requested cities
    int city1 = GetCityIndexFromString(argv[1]);
    int city2 = GetCityIndexFromString(argv[2]);        
    double distance = MAP[city1][city2];

    return 0;
}

int GetCityIndexFromString(char *city)
{
    int i;
    for(i=0;i<MAX_CITIES;i++)
    {
        if(stricmp(city,cities[i]) == 0)
        {
            return i;
        }
    }
    return -1;
}


double distanceEarth(double lat1d, double lon1d, double lat2d, double lon2d) {
  double lat1r, lon1r, lat2r, lon2r, u, v;
  lat1r = deg2rad(lat1d);
  lon1r = deg2rad(lon1d);
  lat2r = deg2rad(lat2d);
  lon2r = deg2rad(lon2d);
  u = sin((lat2r - lat1r)/2);
  v = sin((lon2r - lon1r)/2);
  return 2.0 * earthRadiusKm * asin(sqrt(u * u + cos(lat1r) * cos(lat2r) * v * v));
}

// This function converts decimal degrees to radians
double deg2rad(double deg) {
  return (deg * PI / 180);
}

//  This function converts radians to decimal degrees
double rad2deg(double rad) {
  return (rad * 180 / PI);
}

Where credit for distanceEarth() goes to:
double distanceEarth(double lat1d, double lon1d, double lat2d, double lon2d)

ryyker
  • 22,849
  • 3
  • 43
  • 87