如何用C++读取含注释、图信息及边数据的特定格式文件?
没问题,我来帮你梳理下用C++处理这种图文件的思路和代码实现,核心逻辑和你想的完全一致,只是在IO处理和语法细节上和Python有差异~
C++ 读取特定格式图文件的实现
核心思路(和你的想法对齐)
- 逐行扫描文件,跳过所有以
c开头的注释行,直到找到以p开头的图信息行 - 从
p行中解析出节点数和边数,初始化对应的图数据结构(邻接矩阵或邻接表) - 读取指定数量的
e开头边行,把边信息存入数据结构
具体代码实现
1. 选择合适的数据结构
如果你的图节点数量不大(比如示例中的50),用邻接矩阵会很直观;如果节点数很多(比如上万),推荐用邻接表节省内存。下面两种都会给你示例:
2. 完整代码示例
#include <iostream> #include <fstream> #include <sstream> #include <vector> #include <string> using namespace std; int main() { // 打开目标文件,替换成你的文件路径 ifstream fin("graph.txt"); if (!fin.is_open()) { cerr << "无法打开文件!" << endl; return 1; } string line; int n_nodes, n_edges; bool found_p_line = false; // 第一步:跳过注释,找到p行 while (getline(fin, line)) { // 跳过空行 if (line.empty()) continue; // 首字符是c,跳过注释 if (line[0] == 'c') { continue; } // 找到p行,解析节点数和边数 else if (line[0] == 'p') { istringstream iss(line); string dummy; // 用来接收"edge"这个字符串 iss >> dummy >> dummy >> n_nodes >> n_edges; found_p_line = true; break; } // 遇到非c非p的行,提前报错(可选) else { cerr << "无效的文件格式:遇到非注释非p的行" << endl; return 1; } } if (!found_p_line) { cerr << "文件中未找到p行!" << endl; return 1; } // 第二步:初始化数据结构,这里先演示邻接矩阵 vector<vector<bool>> adj_matrix(n_nodes, vector<bool>(n_nodes, false)); // 如果用邻接表,换成下面这行: // vector<vector<int>> adj_list(n_nodes); // 第三步:读取指定数量的边 int edges_read = 0; while (edges_read < n_edges && getline(fin, line)) { if (line.empty() || line[0] != 'e') { cerr << "遇到无效的边行,跳过" << endl; continue; } istringstream iss(line); string dummy; int u, v; iss >> dummy >> u >> v; // 注意:文件中的节点是1-based,C++容器是0-based,所以要减1 u--; v--; // 更新邻接矩阵 adj_matrix[u][v] = true; adj_matrix[v][u] = true; // 如果是无向图,双向都要设;有向图只设u->v // 如果用邻接表,换成下面两行: // adj_list[u].push_back(v); // adj_list[v].push_back(u); edges_read++; } if (edges_read != n_edges) { cerr << "警告:文件中的边数量与p行声明的不符,实际读取了" << edges_read << "条边" << endl; } // 测试输出:打印邻接矩阵的前5行(可选) cout << "邻接矩阵前5行:" << endl; for (int i = 0; i < min(5, n_nodes); i++) { for (int j = 0; j < min(5, n_nodes); j++) { cout << adj_matrix[i][j] << " "; } cout << endl; } fin.close(); return 0; }
关键细节说明
- 文件IO处理:用
ifstream打开文件,getline逐行读取,istringstream用来拆分每行的内容,比直接用cin更灵活,能处理行内的空格分隔 - 节点编号转换:文件里的节点是从1开始计数的,而C++的vector索引是从0开始的,所以必须减1,否则会出现数组越界错误
- 错误处理:代码里加了文件打不开、找不到p行、边数不符等情况的判断,实际使用时可以根据需求调整
- 数据结构选择:邻接矩阵适合小图,查询边是否存在的时间是O(1);邻接表适合大图,内存占用更小,遍历邻居更高效
内容的提问来源于stack exchange,提问作者Wizard
相关产品推荐
相关产品推荐

