【发布时间】:2020-11-27 16:23:24
【问题描述】:
我正在使用一种必须在 C 中解析的文件格式,如下所示:
5
3
1 3
1 4
1 5
3
2 3
2 4
2 5
2
3 1
3 2
3
4 1
4 2
4 5
3
5 1
5 2
5 4
除了第一行告诉我们顶点的数量外,每一行都有一个数字表示后面有多少行有2个数字。在这 2 条数字线上,我们可以看到在图中连接的 2 个顶点 ID。我的目标是获取这些信息并将 int 转换为图表。我编写了以下函数来读取单个顶点:
graph_vertex_t* read_vertex(FILE *fp, graph_vertex_t *last_vertex)
{
graph_vertex_t *current_vertex;
graph_edge_t *tmp_edge;
graph_edge_t *last_edge;
char *token;
boolean_t error = false;
current_vertex = (graph_vertex_t *)malloc(sizeof(graph_vertex_t));
int tmp_number_edges = 1;
/*Temporary character string used to read line in file. */
char *tmp;
/*Allocating memory for string. Again I'm assuming 64 charcters is*/
/*all I need. */
tmp = malloc(sizeof(char) * 64);
while (fgets(tmp,
63,
fp) != NULL
&&
tmp_number_edges > 0)
{
tmp[strcspn(tmp, "\n")] = 0;
/* Check if the line contains a vertex number. */
if (is_number(tmp))
{
/* Set the line to the vertex number. */
tmp_number_edges = atoi(tmp);
}
else
{
/* check if line has the right format. */
token = strtok(tmp, " \t");
if (is_number(token))
{
/* Set the identifier of the vertex. */
current_vertex->identifier = atoi(token);
current_vertex->next_vertex_p = last_vertex;
}
else
{
error = true;
}
token = strtok(NULL, " \t");
if (is_number(token))
{
/* Make new edge. */
tmp_edge = (graph_edge_t *)malloc(sizeof(graph_edge_t));
tmp_edge->adjac_vertex_p = (graph_vertex_t *)malloc(sizeof(graph_vertex_t));
tmp_edge->adjac_vertex_p->identifier = atoi(token);
tmp_edge->next_edge_p = last_edge;
last_edge = tmp_edge;
printf(" %d", tmp_edge->adjac_vertex_p->identifier);
}
else
{
error = true;
}
tmp_number_edges--;
}
}
current_vertex->edge_list_p = tmp_edge;
if(error)
{
current_vertex = NULL;
}
return(current_vertex);
}
这个函数在一个for循环中被调用,该循环循环计算顶点的数量。然后打印一些信息:
printf("connecting to: ");
current_vertex = read_vertex(fp,
last_vertex);
printf(" found vertex ID: %d \n", current_vertex->identifier);
因此,我希望输出看起来像这样:
连接到:3 4 5 找到顶点 ID:1
连接到:3 4 5 找到顶点 ID:2
连接到:1 2 找到顶点 ID:3
连接到:1 2 5 找到顶点 ID:4
连接到:1 2 4 找到顶点 ID:5
但实际上是这样的:
连接到:3 4 5 找到顶点 ID:1
连接到:3 找到的顶点 ID:2
连接到:5 找到的顶点 ID:2
连接到:1 找到顶点 ID:3
连接到:1 2 5 找到顶点 ID:4
连接到:1 找到的顶点 ID:5
我们可以看到,对于 ID 1 和 4,输出是正确的,但对于其余的则不是。是什么导致了这种行为?我该如何解决这个问题?
编辑:
这里是graph_vertex_t和graph_edge_t的定义。
* Structure used to hold a graph vertex information. */
typedef struct graph_vertex
{
int identifier;
struct graph_vertex *next_vertex_p;
struct graph_edge *edge_list_p;
boolean_t visited;
} graph_vertex_t;
/* Structure used to hold a graph edge information. */
typedef struct graph_edge
{
struct graph_vertex *adjac_vertex_p;
struct graph_edge *next_edge_p;
} graph_edge_t;
【问题讨论】:
-
你的图有 5 个顶点,但你分配的远不止这些。当您阅读
3 1时,您无法立即分配顶点 1,您已经创建了该顶点。您想编写一个边创建例程,该例程分配一个顶点当且仅当图中没有具有该 ID 的顶点。 -
另外,你的解析过于复杂。 atoi、tokens... 一次调用
sscanf就足够了。 -
在每个子组中,第一个 id 总是相同的,是规则还是随机的?否则我无法理解子组的原因。我想在“1 3”之后“3 1”也是多余的
-
graph_vertex_t和graph_edge_t是你定义的吗?顶点 ID 是否总是从 1 开始的连续数字? -
@BRHSM 在这种情况下简化您的生活,通过指针或添加一个字段,说明当前条目中是否定义了顶点