首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >解析函数解析文件,但仅部分解析

解析函数解析文件,但仅部分解析
EN

Stack Overflow用户
提问于 2020-08-07 10:29:57
回答 1查看 55关注 0票数 0

我正在处理一种必须用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

除了第一行,它告诉我们顶点的数量,每一行有一个数字,表示有两个数字的行数。在这两个数字线上,我们可以看到两个顶点ID,它们是在一个图中连接的。我的目标是获取这些信息并将int转换成一个图。我编写了以下函数来读取单个顶点:

代码语言:javascript
复制
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循环中调用的,这个循环是对顶点数的循环。然后打印一些信息:

代码语言:javascript
复制
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

连接到:12找到顶点ID: 3连接到:1 2 5找到顶点ID: 4

连接到:12 4找到的顶点ID: 5

但实际上看起来是这样的:

连接到:3 4 5找到顶点ID: 1

连接到:3个已找到的顶点ID: 2个连接到:5个已找到的顶点ID: 2个已找到的顶点ID: 3个已找到的顶点ID: 3个已找到的顶点ID:4个

连接到:1个找到的顶点ID: 5

我们可以看到,对于ID 1和4,输出是正确的,但对于其余的输出,则不是。是什么导致了这种行为?我怎么才能解决这个问题?

编辑:

以下是graph_vertex_tgraph_edge_t的定义。

代码语言:javascript
复制
* 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;
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-08-07 12:38:12

从你的话

i首先需要理解sscanf

帮助你阅读这里的一些建议,从你的结构中的任何记忆中选出。

不检查数字的第一项建议是否在分隔线上:

代码语言:javascript
复制
#include <stdio.h>

int main()
{
  int nVertices, verticesRank;
  
  if ((scanf("%d", &nVertices) != 1) ||
      (nVertices < 0)) {
    fputs("wrong number of vertices\n", stderr);
    return -1;
  }

  for (verticesRank = 0; verticesRank < nVertices; verticesRank += 1) {
    int nGroups, groupRank, vertex;
    
    if ((scanf("%d", &nGroups) != 1) ||
        (nGroups < 0)) {
      fprintf(stderr, "wrong number of groups in vertices #%d\n", verticesRank);
      return -1;
    }
    
    for (groupRank = 0; groupRank < nGroups; groupRank += 1) {
      int a, b;
      
      if ((scanf("%d%d", &a, &b) != 2) ||
          (a < 1) || (b < 1)) {
        fprintf(stderr, "wrong vertex IDs group #%d vertices #%d\n",
               groupRank, verticesRank);
        return -1;
      }
      
      if (groupRank == 0) {
        vertex = a;
        printf("vertex %d connecting", a);
      }
      else if (a != vertex) {
        fprintf(stderr, "wrong vertex ID group #%d vertices #%d, %d rather than %d\n",
                groupRank, verticesRank, a, vertex);
        return -1;
      }
      printf(" %d", b);
    }
    putchar('\n');
  }
  
  return 0;
}

汇编和执行:

代码语言:javascript
复制
pi@raspberrypi:/tmp $ gcc -Wall c.c
pi@raspberrypi:/tmp $ cat > v
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
pi@raspberrypi:/tmp $ ./a.out <v
vertex 1 connecting 3 4 5
vertex 2 connecting 3 4 5
vertex 3 connecting 1 2
vertex 4 connecting 1 2 5
vertex 5 connecting 1 2 4
pi@raspberrypi:/tmp $ 

第二个版本检查每行值的正确数目:

代码语言:javascript
复制
#include <stdio.h>

int main()
{
  char line[64];
  int nVertices, verticesRank;
  int dummy;
  
  if ((fgets(line, sizeof(line), stdin) == NULL) ||
      (sscanf(line, "%d%d", &nVertices, &dummy) != 1) ||
      (nVertices < 0)) {
    fputs("wrong number of vertices\n", stderr);
    return -1;
  }

  for (verticesRank = 0; verticesRank < nVertices; verticesRank += 1) {
    int nGroups, groupRank, vertex;
    
    if ((fgets(line, sizeof(line), stdin) == NULL) ||
        (sscanf(line, "%d%d", &nGroups, &dummy) != 1) ||
        (nGroups < 0)) {
      fprintf(stderr, "wrong number of groups in vertices #%d\n", verticesRank);
      return -1;
    }
    
    for (groupRank = 0; groupRank < nGroups; groupRank += 1) {
      int a, b;
      
      if ((fgets(line, sizeof(line), stdin) == NULL) ||
          (sscanf(line, "%d%d%d", &a, &b, &dummy) != 2) ||
          (a < 1) || (b < 1)) {
        fprintf(stderr, "wrong vertex IDs group #%d vertices #%d\n",
               groupRank, verticesRank);
        return -1;
      }
      
      if (groupRank == 0) {
        vertex = a;
        printf("vertex %d connecting", a);
      }
      else if (a != vertex) {
        fprintf(stderr, "wrong vertex ID group #%d vertices #%d, %d rather than %d\n",
                groupRank, verticesRank, a, vertex);
        return -1;
      }
      printf(" %d", b);
    }
    putchar('\n');
  }
  
  return 0;
}

汇编和执行:

代码语言:javascript
复制
pi@raspberrypi:/tmp $ gcc -Wall cc.c
pi@raspberrypi:/tmp $ ./a.out <v
vertex 1 connecting 3 4 5
vertex 2 connecting 3 4 5
vertex 3 connecting 1 2
vertex 4 connecting 1 2 5
vertex 5 connecting 1 2 4
pi@raspberrypi:/tmp $ 

注意,我不检查是否有数字以外的其他内容,因此第一行被认为是正确的,例如,如果您需要检查:

代码语言:javascript
复制
#include <stdio.h>

int main()
{
  char line[64];
  int nVertices, verticesRank;
  char dummy;
  
  if ((fgets(line, sizeof(line), stdin) == NULL) ||
      (sscanf(line, "%d%c", &nVertices, &dummy) != 2) ||
      (nVertices < 0) ||
      (dummy != '\n')) {
    fputs("wrong number of vertices\n", stderr);
    return -1;
  }

  for (verticesRank = 0; verticesRank < nVertices; verticesRank += 1) {
    int nGroups, groupRank, vertex;
    
    if ((fgets(line, sizeof(line), stdin) == NULL) ||
        (sscanf(line, "%d%c", &nGroups, &dummy) != 2) ||
        (nGroups < 0) ||
        (dummy != '\n')) {
      fprintf(stderr, "wrong number of groups in vertices #%d\n", verticesRank);
      return -1;
    }
    
    for (groupRank = 0; groupRank < nGroups; groupRank += 1) {
      int a, b;
      
      if ((fgets(line, sizeof(line), stdin) == NULL) ||
          (sscanf(line, "%d%d%c", &a, &b, &dummy) != 3) ||
          (a < 1) || (b < 1) ||
          (dummy != '\n')) {
        fprintf(stderr, "wrong vertex IDs group #%d vertices #%d\n",
               groupRank, verticesRank);
        return -1;
      }
      
      if (groupRank == 0) {
        vertex = a;
        printf("vertex %d connecting", a);
      }
      else if (a != vertex) {
        fprintf(stderr, "wrong vertex ID group #%d vertices #%d, %d rather than %d\n",
                groupRank, verticesRank, a, vertex);
        return -1;
      }
      printf(" %d", b);
    }
    putchar('\n');
  }
  
  return 0;
}

汇编和执行:

代码语言:javascript
复制
pi@raspberrypi:/tmp $ gcc -Wall cc.c
pi@raspberrypi:/tmp $ ./a.out <v
vertex 1 connecting 3 4 5
vertex 2 connecting 3 4 5
vertex 3 connecting 1 2
vertex 4 connecting 1 2 5
vertex 5 connecting 1 2 4
pi@raspberrypi:/tmp $ 

注意,在这种情况下,即使在最后一个期望的数字被认为是一个错误之后,也有一个额外的空格(在换行符之外),最后一行也必须用换行符来完成。

这并不是说在理论结束之后有什么东西,你可以用几种方式去做。

在您的示例中,顶点ID是每个配对中的第一个数字,是连续数字1、2.在我之前的建议中,我不检查,即使检查vertex == verticesRank+1也很容易。如果这是一条规则,那么在只有第二个数字就足够的情况下,为什么要给出这对值呢?

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63299960

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档