如果字符被 # 注释为 fscanf,则在配置解析器中跳过行

Skip line in config parser if character is # commented with fscanf

我已经使用 fscanf 编写了一个简单的配置解析器,现在想添加一个注释字符 (#)。

我的配置文件包含三列,其中 fscanf 读取并存储在相应的数组中。这很好用,但我有点不确定如何编写它以便“如果读取的字符是 # 然后移动到下一行。

我试过使用 fgetc 但它似乎只读取了第一个字符,而且它似乎破坏了我的 while 循环中的逻辑。

我已经尝试在我的 fscanf 中使用 "%*[^\n]\n" 的修改作为:

while(fscanf(fp,"%d\t%f\t%f%*[^#]\n", &a[i], &b[i], &c[i]) != EOF)

但这会导致段错误。

配置:

#hello and welcome to my config file
1666    -0.314913523    0.999804843        #blah blah
1667    -0.337279687    0.999865966
1703    -0.323162231    0.999774194
1704    -0.311984064    0.99964375
1705    -0.311984064    0.99964375
1706    -0.313381260    0.999671436
1707    -0.313170802    0.999558174

代码:

#include <iostream>
using namespace std;

#define NUM_ITEMS 50

int main()
{
    FILE *fp;
    fp = fopen("config.conf","r");

    if(fp==NULL){
        printf("No file.\n");
        return -1;
    }

    int a[NUM_ITEMS];
    float b[NUM_ITEMS];
    float c[NUM_ITEMS];

    int i = 0;

    while(fscanf(fp,"%d\t%f\t%f", &a[i], &b[i], &c[i]) != EOF)
    {
        printf("-> %d   %f  %f\n", a[i], b[i], c[i]);
        i++;
    }

    fclose(fp);
}

您可以使用 fgets 将每一行作为字符串读取,然后检查 '#'出现。

#include <stdio.h>

#define NUM_ITEMS 50
#define MAX_CHAR 500

ssize_t find_index(char *str)
{
  size_t i=0U;

  for (; *str!='[=10=]'; i++)
  {
    if (*str++=='#')
    {
      return i;
    }
  }

  return -1;
}

int main(void)
{
  int a[NUM_ITEMS];
  float b[NUM_ITEMS];
  float c[NUM_ITEMS];
  char buff[MAX_CHAR];
  FILE *fp;
  size_t i=0U;
  ssize_t index=0U;

  fp = fopen("config.conf","r");

  if(!fp)
  {
    printf("No file.\n");
    return -1;
  }

  while (fgets(buff,MAX_CHAR,fp))
  {
    index=find_index(buff);
    if (index!=-1)
    {
      buff[index]='[=10=]'; /* Bare in mind this will skip the newline character which fgets appends */
    }

    if(sscanf(buff,"%d%f%f", &a[i], &b[i], &c[i])==3) /* Checking scanf read 3 numbers */
    {
      printf("-> %d %f %f\n", a[i], b[i], c[i]);
      i++;
    }
  }

  return 0;
}

所以find_index()returns找到元素#的位置。然后替换为NULL终结符.

正如 Jonathan 在评论中指出的那样,您还可以使用 strcspn() 函数和 strlen() (用于错误检查)来查找 #.

的索引