Search code examples
c++stringmatrixdynamic-arrays

C++ Matrix to dynamic 2D arrray (with strings)


Let's say we have a .txt file with data like this:

6
Paris New_York 1
London Berlin 1
Moskow Kiev 1
Paris London 1
New_York Moscow 1

Where 6 is number of Citys and than it means Paris and New_York are connected with value 1, it will always be 1.

Now i would like to turn this into 2D dynamic array. I did it with numbers like this, but i don't know how should i do this with strings. For numbers:

ifstream myfile("info.txt");
if (myfile.is_open()) {
    getline(myfile, line);
    istringstream(line) >> Number; 
}

int **matrix= new int*[Number];
for (int i = 0; i < Number; i++) {
    matrix[i] = new int[Number];
}

while (getline(myfile, line)) {
    cout << line << '\n';
    std::stringstream linestream(line);
    int row;
    int column;
    int value;
    if (linestream >> row >> column >> value)
    {
        a[row-1][column-1] = value;
        a[column-1][row-1] = value;// mirror
    }

So how can i do this for strings? Thank you for your helpful answers


Solution

  • You need an unordered_map<string, int>, beside the matrix, to map string to indexes. Here is my solution:

    #include <iostream>
    #include <sstream>
    #include <string>
    #include <fstream>
    #include <unordered_map>
    using namespace std;
    
    int main() {
      string line;
      int Number;
    
      ifstream myfile("info.txt");
      if (myfile.is_open()) {
        getline(myfile, line);
        istringstream(line) >> Number;
      }
    
      int **matrix= new int*[Number];
      for (int i = 0; i < Number; i++) {
        matrix[i] = new int[Number](); // note () at the end for initialization to 0
      }
    
      unordered_map<string, int> citiesMap; // to map cities (string) to indexes (int)
      int cityIndex = 0;
    
      while (getline(myfile, line)){
        std::stringstream linestream(line);
        string row;
        string column;
        int value;
    
        if (linestream >> row >> column >> value) {
          if(citiesMap.find(row) == citiesMap.cend())
            citiesMap[row] = cityIndex++; // add city to the map if it doesn't exist
    
          if(citiesMap.find(column) == citiesMap.cend())
            citiesMap[column] = cityIndex++; // add city to the map if it doesn't exist
    
          matrix[citiesMap[row]][citiesMap[column]] = value;
          matrix[citiesMap[column]][citiesMap[row]] = value;// mirror
        }
      }
    
      for(auto x: citiesMap) {
        cout << x.first << ": " << x.second << endl;
      }
      cout << endl;
    
      for(int i = 0; i < Number; i++) {
        for(int j = 0; j < Number; j++) {
          cout << matrix[i][j] << " ";
        }
        cout << endl;
      }
      // matrix should be freed here
    }
    

    You may optionally keep unique cities in a vector (or array) to access cities from their indexes. Don't forget to free the memory. Also, you may use std::array for the matrix and don't bother with memory issues.