C 基于初始格式解析字符串

C 基于初始格式解析字符串,c,string,parsing,C,String,Parsing,我试图解析一组行,并根据初始格式(读取配置文件)提取字符串的某些部分 更多说明:该格式最多可以包含4个要格式化的部分。在这种情况下,%S将跳过该部分,%a-%c将提取该部分并将作为字符串处理,%d作为int 我现在想做的是想出一些聪明的方法来解析它。到目前为止,我提出了以下原型。然而,我的指针算法仍然需要一些工作来跳过/提取部分 最终,每个部分都将存储在一个结构数组中 编辑:在这种情况下,使用sscanf可能不起作用,因为格式是在配置文件中指定的。此外,格式可能会缩放,字符串(和类型)可能会更改

我试图解析一组行,并根据初始格式(读取配置文件)提取字符串的某些部分

更多说明:该格式最多可以包含4个要格式化的部分。在这种情况下,
%S
将跳过该部分,
%a-%c
将提取该部分并将作为字符串处理,
%d
作为int

我现在想做的是想出一些聪明的方法来解析它。到目前为止,我提出了以下原型。然而,我的指针算法仍然需要一些工作来跳过/提取部分

最终,每个部分都将存储在一个结构数组中

编辑:在这种情况下,使用
sscanf
可能不起作用,因为格式是在配置文件中指定的。此外,格式可能会缩放,字符串(和类型)可能会更改

#include <stdio.h>
#include <string.h>

#define DIM(x) (sizeof(x)/sizeof(*(x)))

void process (const char *fmt, const char *line) {
   char c;
   const char *src = fmt;
   while ((c = *src++) != '\0')
   {   
      if (c == 'S');      // skip part
      else if (c == 'a'); // extract %a
      else if (c == 'b'); // extract %b
      else if (c == 'c'); // extract %c
      else if (c == 'd'); // extract %d (int)
      else { 
         printf("Unknown format\n");
         exit(1);
      }   
   }
}

static const char *input[] = {
   "bar 200.1 / / (zaz) - \"bon 10\"",
   "foo 100.1 / / (baz) - \"apt 20\"",
};

int main (void) {
   const char *fmt = "%S %a / / (%b) - \"%c %d\"";
   size_t i;
   for(i = 0; i < DIM (input); i++) 
   {
      process (fmt, input[i]);
   }   
   return (0);
}
#包括
#包括
#定义尺寸(x)(尺寸(x)/尺寸(*(x)))
无效流程(常量字符*fmt,常量字符*行){
字符c;
常量字符*src=fmt;
而((c=*src++)!='\0')
{   
if(c=='S');//跳过部分
else if(c=='a');//提取%a
else if(c=='b');//提取%b
else if(c=='c');//提取%c
else if(c=='d');//提取%d(int)
否则{
printf(“未知格式\n”);
出口(1);
}   
}
}
静态常量字符*输入[]={
“bar 200.1/(zaz)-“bon 10”,
“foo 100.1/(baz)-“apt 20”,
};
内部主(空){
常量char*fmt=“%S%a//(%b)\%c%d\”;
尺寸i;
对于(i=0;i
如果没有每个占位符的严格定义,根据格式进行解析可能会很困难。 您计划如何处理以下情况:

fmt = "(%c)";

input = "(a)bc)";
?


显然,用户希望得到“a)bc”,但由于“')”是您的最终解析标记,因此您只得到了“a”

scanf表达式有时足以解析实际输入,并且可以在运行时或编译时构建它们。所以,在重新发明轮子之前,我会尝试沿着这条路走:

#include <stdio.h>
#include <string.h>

#define DIM(x) (sizeof(x)/sizeof(*(x)))

static const char *input[] = {
   "bar 200.1 / / (zaz) - \"bon 10\"",
   "foo 100.1 / / (baz) - \"apt 20\"",
};
const char *format = "%*[^ ] %[^ ] / / (%[^)]) - \" %[^ ] %d \"";

int main()
{
 typedef char buffer[100];
 buffer A,B,C;
 int D, i, p;

 for (i = 0; i < DIM(input); i++) {
  if ((p = sscanf(input[i], format, A, B, C, &D)) == 4)
   printf("%s %s %s %d\n", A, B, C, D);
  else
   printf("parsed only %d\n", p);
 }
}

看来你想创建一个新的printf,对吗?给我们一个输入和输出的例子。你想做什么?比如printf?因为这不起作用……我没有尝试重新创建另一个printf,我只想根据指定的格式提取零件。我想他是在尝试实现一个我忘记提到的自定义,该格式将由用户在配置文件中指定。所以,我不确定使用sscanf是否会有帮助。如果是这样,我认为正则表达式是更简单、更快速的解决方案。搜索并替换then.Extraction
a
现在还可以,稍后,在另一个函数上,我可以验证提取的内容是否与应该的内容匹配。chac:因为用户在conf文件上指定了格式,我想知道sscanf是否能理解问题上的格式?凯拉:我认为从文件中获取规范没有问题,请使用fgets()。正如我所建议的,规范(是regexp的子集)也可以通过strcat在运行时编写。
200.1 zaz bon 10
100.1 baz apt 20