如果字符被 # 注释为 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()
(用于错误检查)来查找 #.
的索引
我已经使用 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()
(用于错误检查)来查找 #.