C语言中的语法分析问题
我有一个字符串,格式如下:C语言中的语法分析问题,c,parsing,pattern-matching,C,Parsing,Pattern Matching,我有一个字符串,格式如下: char *sampleLine = "name1: 251 name2: 23 name3: -67 name4: 0.00 name5: 310 name6: 410 name7: 54001 name8: 332 name9: SOME_TEXT name10: 3 name1: 181 235 237 name11: 11 name12: 240 241 242 243 244 245 246 247 248 249 250 name13: 0 name14:
char *sampleLine = "name1: 251 name2: 23 name3: -67 name4: 0.00 name5: 310 name6: 410 name7: 54001 name8: 332 name9: SOME_TEXT name10: 3 name1: 181 235 237 name11: 11 name12: 240 241 242 243 244 245 246 247 248 249 250 name13: 0 name14: 2 name15: 1 name16: 0 name17: 6 name18: 0 name19: 500 name20: 200 name21: 64 name22: 1 name23: 6 name24: 0 name25: 0";
字符串的一个问题是有些名称是重复的,但基本模式似乎是name:value。因此,我编写了一个算法,它将接受一个名称并返回一个值,但它似乎不起作用,并且没有考虑到名称重复的问题
例如:如果我通过name1,我会得到251,以此类推
以下是带有示例main的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
char* extractValue(char* name, char* buffer)
{
char* begining = strstr(buffer,name);
begining += strlen(name) + 2;
if (begining != NULL)
{
char* end = strstr(begining,":");
if (end != NULL)
{
end += 1;
for (int i=0; i < strlen(end); i++)
{
if (end[i] != ':')
{
i++;
} else {
char namevalue[200];
bzero(namevalue,200);
strncpy(namevalue,begining,i);
for (int x=strlen(namevalue); x>0; x--)
{
if (namevalue[x] == ' ')
{
char* value = (char*)malloc(200);
bzero(value,200);
strncpy(value,namevalue,strlen(namevalue) - (strlen(namevalue) - x));
return value;
}
}
break;
}
}
}
}
return NULL;
}
int main (int argc, char** argv)
{
char *sampleLine = "name1: 251 name2: 23 name3: -67 name4: 0.00 name5: 310 name6: 410 name7: 54001 name8: 332 name9: SOME_TEXT name10: 3 name1: 181 235 237 name11: 11 name12: 240 241 242 243 244 245 246 247 248 249 250 name13: 0 name14: 2 name15: 1 name16: 0 name17: 6 name18: 0 name19: 500 name20: 200 name21: 64 name22: 1 name23: 6 name24: 0 name25: 0";
char* value1 = extractValue("name1", sampleLine);
char* value3 = extractValue("name3", sampleLine);
char* value17 = extractValue("name17", sampleLine);
printf("value 1 = %s\n",value1);
printf("value 3 = %s\n",value3);
printf("value 17 = %s\n",value17);
return 0;
}
而非预期
value 1 = 251
value 3 = -67
value 17 = 6
两个微妙的错误
首先,
if (end[i] != ':')
{
i++;
} else ..
通过在此处手动递增i
,您将跳过一个字符,因为for循环已经递增了i
。它似乎没有副作用,但只是因为
第二:问题的实际原因是您测量的字符串长度错误。通过从该位置向前扫描下一个:
,可以找到名称值的开头(begining
),然后找到其end
。然后,向后追踪以查找上一个空格,该空格应为值的结尾。但是
for (i=0; i < strlen(end); i++)
并将:
检查更改为
if (begining[i] == ':')
{
char namevalue[200];
... (etc.)
(丢弃i++
行)
零票 查找单个字符的稍微快一点的方法是
strchr
:
char* end = strchr(begining,':');
您可能希望找到更好的策略来定位名称
。如果您正在查找name1
,它可以找到name12
以及noname1
一种方法是使用strtok
将字符串拆分为令牌。然后,任何以:
结尾的内容都是一个可能的名称,下一个标记就是您要查找的值。省略,因为它本身就是一个很好的练习。(如果你想试试这个:)
最后,您可以不使用所有这些循环:-)
C还是C++,哪一个?这看起来像C。在C++中似乎更容易实现,但是问题似乎是C,所以我不会回答。这对于NAME2:23的工作非常有效,但是对于NAME12:240,241,242,243,244,245,246,247,248,249,250,这不起作用。如何提取这两种类型的值?在这种情况下,您可以使用自己的想法:从
开始
,向前扫描下一个:
;如果找到,再次向后扫描以查找空间。在我更新end
的地方更改此选项,start
仍然很好。顺便说一句,如果您有nameX:
但没有数据,那么它将返回一个空字符串。我的代码返回下一个名称。
if (begining[i] == ':')
{
char namevalue[200];
... (etc.)
char* end = strchr(begining,':');
char* extractValue(char* name, char* buffer)
{
char *start, *end, *ret_val;
int length;
char* begining = strstr(buffer,name);
if (!begining)
return NULL;
start = begining + strlen(name);
if (start[0] != ':')
return NULL;
start++;
// skip initial spaces, if any
while (*start == ' ')
start++;
// ptr points to the start of data. Find end.
end = start;
while (*end && *end != ' ')
end++;
// we have the correct string in start..end
length = end-start;
// it's a zero-terminated string so add 1 for the zero
ret_val = (char *)malloc(length+1);
strncpy (ret_val, start, length);
// put the zero where it belongs
ret_val[length] = 0;
return ret_val;
}