2016-10-06 2 views
0

Я изо всех сил пытаюсь понять, как прочитать этот файл на карте. Я начал с чтения файла в вектор. Затем попытался взять строковое значение в векторе и вставить его в карту. Я полностью потерян.Как бы я прочитал этот файл на карте C++

Первое значение - это ключ, а упорядоченные пары - значения. Я должен быть около добавить «бесконечное число значений»

1 2,1 8,2 
2 1,1 3,1 
3 2,1 4,1 
4 3,1 5,1 
5 4,1 6,1 
6 5,1 7,1 
7 6,1 8,1 
8 7,1 1,2 

Текущий код чтения:

int main(int argc, char const *argv[]){ 

    map<int, string> map; 
    vector<string> v; 
    vector<int> v2; 
    string line; 
    string fileName(argv[1]); 
    ifstream inputFile; 
    inputFile.open(fileName); 

    while(getline(inputFile, line)){ 
     v.push_back(line); 
    } 

    return 0; 
} 
+0

'std :: map >>' может быть, что вы после, но, возможно, нет. Пожалуйста, расширьте то, как вы собираетесь использовать эти данные. Там могут быть лучшие варианты. – user4581301

+0

ключи являются «узлами», а значения «другим узлом, длиной края для узла» и мне нужно использовать алгоритм dijkstras для нахождения кратчайшего пути – Zach

+0

ключи - это первые числа 1-8? –

ответ

1

Вы указали, что на каждой строке начальное значение является последовательным ключом, а остальные значения на каждой строке состоят из разделенных пробелами разделителей, каждый из которых является двумя значениями, разделенными запятой, причем первое значение является некоторым другим идентификатором, и поэтому первое значение всех кортежей в одной строке будет уникальным.

Как таковой, я хотел бы предложить следующую структуру данных:

typedef std::vector<std::map<int, int>> map_t; 

индекс вектор должен быть начальным ключом. Ваши векторные индексы основаны на 0, и в вашем файле данных они основаны на 1, но это достаточно просто, чтобы обрабатывать «на лету». Либо измените свой файл данных, либо просто выполните ключ 0 без данных.

Каждое значение в векторе представляет собой карту. Ключ карты - это идентификатор «другого узла», а значение - расстояние до другого узла - в соответствии с вашим описанием того, что означают эти данные.

Эта структура данных будет моделировать эти данные. Теперь, насколько этот вопрос чтения и разбора эти данные:

Ваш первоначальный подход является правильным: использовать std::getline() читать каждую строку в то время в строку:

map_t my_map; 

std::string line; 

while (std::getline(inputFile, line)) { 

    // Here be dragons 

} 

Там нет ничего, чтобы быть получен из помещая каждый line в вектор строк. Мы можем просто анализировать каждую строку, когда мы ее читаем. Внутри цикла мы обработаем каждую прочитанную строку и поместим ее данные непосредственно в my_map. Это план. Простой, легкий и простой.

Внутри цикла, мы начинаем, помещая каждую строку в std::istringstream для того, чтобы разобрать его, а затем извлечь начальный узел ID:

int node_id; 

std::istringstream line_stream(line); 

line_stream >> node_id; 

достаточно просто. Если вам нужно обрабатывать плохой ввод, вы должны быть в состоянии выяснить, как проверить ошибки преобразования самостоятельно здесь и в остальном коде.

Теперь мы тогда просто нужно срывать каждый «other_node, расстояние» пары кортеж:

std::string node_distance; 
std::map<int, int> node_distance_map; 

while (line_stream >> node_distance) 
{ 
    // Here be more dragons. 
} 

И вот что. Внутри цикла, где больше драконов, node_distance будет каждой отдельной строкой «n, n» с двумя значениями. Это достаточно просто для вас, чтобы выяснить самостоятельно: как извлечь эти два ints из этой строки самостоятельно; затем обновите node_distance_map. Затем, после этого while_loop, вы берете построенный node_distance_map и извлечение node_id раньше, и просушите все это в my_map. Миссия выполнена. Это было не очень сложно, не так ли?

+0

Я не могу понять, как объединить node_distance_map и node_id в my_map. Я думаю, что у меня есть все остальное. – Zach

+0

'map_t' - это вектор, а' node_id' будет его индексом. Итак, сначала проверьте, что индекс 'node_id' фактически существует в векторе, а если нет,' resize() 'вектор так, чтобы он это делал. Тогда это просто 'my_map [node_id] = node_distance_map;'. Ничто не отличается от назначения какой-либо другой ценности любому другому виду вектора. –

0

Проверить это решение, это не лучшее решение, но оно достигает цели:

map<int, vector<pair<int, int>>> result; 

ifstream infile("C:\\Users\\Mohamed\\Desktop\\test.txt"); 

string line; 
while (getline(infile, line)) { 

    istringstream iss(line); 
    vector<string> tokens{istream_iterator<string>{iss}, 
          istream_iterator<string>{}}; 

    if(tokens.size() == 0) continue; // Workaround 

    int pair1FirstValue, pair1SecondValue, pair2FirstValue, pair2SecondValue; 

    string pair1 = tokens.at(1); 
    string pair2 = tokens.at(2); 

    sscanf(pair1.c_str(), "%d,%d", &pair1FirstValue, &pair1SecondValue); 
    sscanf(pair2.c_str(), "%d,%d", &pair2FirstValue, &pair2SecondValue); 

    vector<pair<int,int>> valueVector { make_pair(pair1FirstValue, pair1SecondValue), make_pair(pair2FirstValue, pair2SecondValue) }; 

    result.insert(make_pair(stoi(tokens.at(0)), valueVector)); 
} 

cout << "Printing the map: " << endl; 

for(auto it = result.begin(); it != result.end(); it++) { 

    cout << it->first << " " 
     << it->second.at(0).first << " " << it->second.at(0).second << " " 
     << it->second.at(1).first << " " << it->second.at(1).second << endl; 
} 

Для того, чтобы построить код, вам необходимо включить следующие заголовочные файлы:

#include <iostream>
#include <sstream>
#include <fstream>

Попытка понять код, и исправить обходной путь, удачи.

0

Это простой пример чтения. Это никоим образом не оптимально, но его нужно легко читать, понимать, отлаживать и запускать OP. Если чтение файла является тяжелым фактором времени обработки, рассмотрите возможность использования чего-то вроде конечного автомата.

#include <map> 
#include <vector> 
#include <string> 
#include <fstream> 
#include <sstream> 
#include <iostream> 

int main(int argc, char const *argv[]) 
{ 

    std::vector<std::map<int, int>>adjacencies; 
    std::string line; 

    if (argc >=2) // no argv[1] if argc < 2 
    { 
     std::ifstream inputFile(argv[1]); 

     while(getline(inputFile, line)) // get a line until no more lines 
     { 
      std::map<int,int> temp; // holder for adjacent nodes as we find them 
      std::stringstream ss(line); // stream to ease parsing of nodes from line 
      std::string node; 
      while (ss >> node) // get adjacent node on this line until end of line 
      { 
       std::stringstream ss2(node); //stream to ease taking nodes apart 
       int key; 
       char comma; 
       int weight; 
       if (ss2 >> key >> comma >> weight) // take apart node 
       { 
        temp[key] = weight; // put adjacent node in list 
       } 
       else 
       { 
        std::cerr << "File is bogus. Bailing\n"; 
        return -1; 
       } 
      } 

      adjacencies.push_back(temp); // put node and all adjacencies in list 
     } 

     try 
     { 
      auto weight_of_15_8 = adjacencies[15-1].at(8); 
      //-1 because origin 0 indexing 
     } 
     catch(std::out_of_range &) 
     { 
      std::cerr << "node 15 is not adjacent to 8\n"; 
     } 

     return 0; 
    } 
    else 
    { 
     std::cerr << "Usage <prog name here> <filename here>\n"; 
     return -2; 
    } 
} 

Исключение особенно тупо медленно, но если ключ не в map, то map будет создавать и по умолчанию инициализации значения, если вы используете []. Вам не нужен список с нулевыми узлами смежности, поэтому лучше всего закрепите эту ошибку раньше.

Смежные вопросы