c++ - vector 的最后一项不显示/vector 索引问题

标签 c++ boost vector cout boost-graph

我有一个我根本找不到的奇怪错误。

我正在使用 Boost 图库构建一个 adjacency_list 图,并将顶点列表填充到一个 vector 中。当我遍历 vector 时,它会正确打印出所有顶点,但是,当我运行算法(例如 Dijkstra 的最短路径)时,最后 顶点显示为空白。

例如:

Shortest path from C to R 
C -> H = 55 
H ->  = 97
  -> R = 56

Distance: 208

更糟糕的是,如果我编写一个简单的搜索来选择一个特定的顶点, vector 中的最后顶点再次成为一个问题,因为它表明它不存在。

std::string start_vertex;
bool valid = false;
std::cout << "Vertices:" << std::endl;
for (auto &i : _vertices) {
    std::cout << i << " ";
}
std::cout << std::endl;
while (!valid) {
    std::cout << "Enter starting vertex: ";
    std::cin >> start_vertex;
    for (auto &i : _vertices) {
        if (i == start_vertex) {
            valid = true;
            break;
        }
    }
}

上面,在搜索问题顶点时,继续循环,而所有其他顶点都正常工作。正如前面提到的,所有顶点都在迭代时打印出来。

最后,当上面的 foreach 循环运行时,第一个 顶点是空白的。我想所有这些都是相关的,但我无法弄清楚我在这里做了什么。我很乐意提供更多代码,但了解我应该首先寻找的内容会很有帮助。

谢谢。


#include <fstream>
#include <iostream>
#include <string>
#include <boost/tokenizer.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/iteration_macros.hpp>
#include <boost/graph/properties.hpp>
#include <boost/graph/kruskal_min_spanning_tree.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/config.hpp>
#include <boost/algorithm/string.hpp>
#include <utility>
#include <vector>
#include <map>

int main(int , const char * argv[]) {
    std::ifstream input(argv[1]);
    typedef int Weight;
    typedef boost::property<boost::vertex_name_t, std::string> VertexNameProperty;
    typedef boost::property<boost::edge_weight_t, Weight> EdgeWeightProperty;
    typedef boost::adjacency_list<boost::listS, boost::vecS, boost::directedS,
                                                                VertexNameProperty, EdgeWeightProperty> Graph;
    typedef boost::graph_traits<Graph>::vertex_descriptor Vertex;
    typedef boost::property_map<Graph, boost::vertex_index_t>::type IndexMap;
    typedef boost::property_map<Graph, boost::vertex_name_t>::type NameMap;
    typedef boost::iterator_property_map<Vertex*, IndexMap, Vertex, Vertex&>
    PredecessorMap;
    typedef boost::iterator_property_map<Weight*, IndexMap, Weight, Weight&>
    DistanceMap;
    std::string line, vertex;
    std::getline(input, line);
    std::getline(input, line);
    boost::char_separator<char> sep(",");
    typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
    tokenizer tok(line, sep);
    std::vector<std::string> _vertices;
    for (auto &i : tok) {
        _vertices.push_back(i);
    }
    Graph g(sizeof(_vertices));
    std::map<std::string, Vertex> vertex_map;
    for (auto &i : _vertices) {
        vertex_map[i] = boost::add_vertex(std::string(i), g);
    }
    char c;
    struct GraphParameters {
        char vertex_one, vertex_two;
        Weight edge_weight;
    };
    std::getline(input, line);
    while (getline(input, line)) {
        GraphParameters p;
        std::istringstream iss(line);
        iss >> c >> p.vertex_one >> c >> p.vertex_two >> c >> p.edge_weight >> c;
        std::string v1, v2;
        std::stringstream ss1 ,ss2;
        ss1 << p.vertex_one;
        ss1 >> v1;
        ss2 << p.vertex_two;
        ss2 >> v2;
        boost::add_edge(vertex_map[v1], vertex_map[v2], p.edge_weight, g);
    }
std::string start_vertex, end_vertex;
bool valid = false;
std::cout << "Vertices:" << std::endl;
for (auto &i : _vertices) {
    std::cout << i << " ";
}
std::cout << std::endl;
while (!valid) {
    std::cout << "Enter starting vertex: ";
    std::cin >> start_vertex;
    for (auto &i : _vertices) {
        if (i == start_vertex) {
            valid = true;
            break;
        }
  }
}
while (valid) {
    std::cout << "Enter ending vertex: ";
    std::cin >> end_vertex;
    for (auto &i : _vertices) {
        if (i == end_vertex) {
            valid = false;
            break;
        }
    }
}
    std::vector<Vertex> predecessors(boost::num_vertices(g));
    std::vector<Weight> distances(boost::num_vertices(g));
    IndexMap indexMap = boost::get(boost::vertex_index, g);
    PredecessorMap predecessorMap(&predecessors[0], indexMap);
    DistanceMap distanceMap(&distances[0], indexMap);
    boost::dijkstra_shortest_paths(g, vertex_map[start_vertex],
                                                                 boost::distance_map(distanceMap)
                                                                 .predecessor_map(predecessorMap));
    NameMap nameMap = boost::get(boost::vertex_name, g);
    std::cout << std::endl;
    typedef std::vector<Graph::edge_descriptor> PathType;
    PathType path;
    Vertex v = vertex_map[end_vertex];
    for(Vertex u = predecessorMap[v]; u != v; v = u, u = predecessorMap[v]) {
        std::pair<Graph::edge_descriptor, bool> edgePair = boost::edge(u, v, g);
        Graph::edge_descriptor edge = edgePair.first;
        path.push_back(edge);
    }
    std::cout << "Shortest path from " << start_vertex << " to " << end_vertex
                        << std::endl;
    for(PathType::reverse_iterator pathIterator = path.rbegin(); pathIterator
            != path.rend(); ++pathIterator) {
        std::cout << nameMap[boost::source(*pathIterator, g)] << " -> "
                            << nameMap[boost::target(*pathIterator, g)]
                            << " = " << boost::get(boost::edge_weight, g, *pathIterator)
                            << std::endl;
    }
    std::cout << std::endl;
    std::cout << "Distance: " << distanceMap[vertex_map[end_vertex]] << std::endl;
    std::cout << std::end;
  return EXIT_SUCCESS;
}

示例输入文件:

Vertices:
S,H,R,C,G
Edges
(S,C,39)
(R,S,86)
(G,S,74)
(C,H,55)
(R,C,126)
(G,C,68)
(R,H,111)
(G,R,56)
(H,G,97)
(S,H,27)

最佳答案

Graph g(sizeof(_vertices));

这是一个错误。你想写。

Graph g(_vertices.size());

然而,这仍然是错误的。稍后您已经在循环中添加顶点 (add_vertex),因此您不需要预先填充图形。

Graph g;

工作演示

下面的程序有一些样式修复(允许我阅读代码,以及更多地依赖解析)我用所有可能的有效输入对它进行了详尽的测试:

for i in {S,H,R,C,G}\ {S,H,R,C,G}; do valgrind ./test <<< $i; done

(与 http://paste.ubuntu.com/14002530/ 相同)

它清楚地显示所有运行,没有可检测到的内存错误。

Live On Coliru

#include <boost/algorithm/string.hpp>
#include <boost/config.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/iteration_macros.hpp>
#include <boost/graph/kruskal_min_spanning_tree.hpp>
#include <boost/graph/properties.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/tokenizer.hpp>
#include <iostream>
#include <fstream>
#include <map>
#include <string>
#include <utility>
#include <vector>

namespace {
    typedef int Weight;
    typedef boost::property<boost::vertex_name_t, std::string> VertexNameProperty;
    typedef boost::property<boost::edge_weight_t, Weight> EdgeWeightProperty;
    typedef boost::adjacency_list<boost::listS, boost::vecS, boost::directedS, VertexNameProperty, EdgeWeightProperty> Graph;
    typedef boost::graph_traits<Graph>::vertex_descriptor Vertex;
    typedef boost::property_map<Graph, boost::vertex_index_t>::type IndexMap;
    typedef boost::property_map<Graph, boost::vertex_name_t>::type NameMap;
    typedef boost::iterator_property_map<Vertex*, IndexMap, Vertex, Vertex&> PredecessorMap;
    typedef boost::iterator_property_map<Weight*, IndexMap, Weight, Weight&> DistanceMap;
}

template <typename V, typename VM>
Graph readGraph(std::string const& fname, V& _vertices, VM& vertex_map) {
    std::ifstream input(fname);
    std::string line, vertex;
    std::getline(input, line);
    assert(line == "Vertices:");

    std::getline(input, line);
    boost::char_separator<char> sep(",");
    typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
    tokenizer tok(line, sep);

    for (auto &i : tok) {
        _vertices.insert(_vertices.end(), i);
    }

    Graph g;
    for (auto &i : _vertices) {
        vertex_map[i] = boost::add_vertex(std::string(i), g);
    }

    char c;
    struct GraphParameters {
        char source, target;
        Weight weight;
    };

    std::getline(input, line);
    assert(line == "Edges");

    while (getline(input, line)) {
        GraphParameters p;
        std::istringstream iss(line);
        if (iss >> c && c == '('
                && iss >> p.source >> c && c == ','
                && iss >> p.target >> c && c == ','
                && iss >> p.weight >> c && c == ')') 
        {
            boost::add_edge(
                    vertex_map[std::string(1,p.source)],
                    vertex_map[std::string(1,p.target)],
                    p.weight,
                    g);
        } else {
            throw std::runtime_error("Parse error in '" + line + "'\n");
        }
    }

    return g;
}

int main() {
    std::vector<std::string>      _vertices;
    std::map<std::string, Vertex> vertex_map;
    auto g = readGraph("input.txt", _vertices, vertex_map);

    std::string start_vertex, end_vertex;
    bool valid = false;
    std::cout << "Vertices:" << std::endl;
    for (auto &i : _vertices) {
        std::cout << i << " ";
    }
    std::cout << std::endl;
    while (!valid) {
        std::cout << "Enter starting vertex: ";
        std::cin >> start_vertex;
        for (auto &i : _vertices) {
            if (i == start_vertex) {
                valid = true;
                break;
            }
        }
    }
    while (valid) {
        std::cout << "Enter ending vertex: ";
        std::cin >> end_vertex;
        for (auto &i : _vertices) {
            if (i == end_vertex) {
                valid = false;
                break;
            }
        }
    }
    std::vector<Vertex> predecessors(boost::num_vertices(g));
    std::vector<Weight> distances(boost::num_vertices(g));

    IndexMap indexMap = boost::get(boost::vertex_index, g);
    PredecessorMap predecessorMap(&predecessors[0], indexMap);
    DistanceMap distanceMap(&distances[0], indexMap);

    boost::dijkstra_shortest_paths(g, vertex_map[start_vertex],
                                   boost::distance_map(distanceMap).predecessor_map(predecessorMap));

    NameMap nameMap = boost::get(boost::vertex_name, g);

    std::cout << std::endl;
    typedef std::vector<Graph::edge_descriptor> PathType;

    PathType path;
    Vertex v = vertex_map[end_vertex];
    for (Vertex u = predecessorMap[v]; u != v; v = u, u = predecessorMap[v]) {
        std::pair<Graph::edge_descriptor, bool> edgePair = boost::edge(u, v, g);
        Graph::edge_descriptor edge = edgePair.first;
        path.push_back(edge);
    }
    std::cout << "Shortest path from " << start_vertex << " to " << end_vertex << std::endl;
    for (PathType::reverse_iterator pathIterator = path.rbegin(); pathIterator != path.rend(); ++pathIterator) {
        std::cout << nameMap[boost::source(*pathIterator, g)] << " -> " << nameMap[boost::target(*pathIterator, g)]
                  << " = " << boost::get(boost::edge_weight, g, *pathIterator) << std::endl;
    }
    std::cout << std::endl;
    std::cout << "Distance: " << distanceMap[vertex_map[end_vertex]] << std::endl;
    std::cout << std::endl;
    return EXIT_SUCCESS;
}

关于c++ - vector 的最后一项不显示/vector 索引问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34260257/

相关文章:

c++ - 在 VC++ 中使用多线程和 boost

根据索引向量替换矩阵列中的值?

c++ - 关于 vector 初始化的一些问题

c++ - 在 CMake 中包含目录

c++ - 编译器会优化静态函数的未使用参数吗?

c++ - 在数组中间添加新索引

c++ - glog 详细日志记录和 Boost 程序选项

c++ - Boost ASIO 可能会影响同一台机器上其他程序的性能

c# - 在 Unity C# 中将对象缓慢移动到新位置

C++按值而不是按引用发送数组到函数