[英]Parsing issue in C
我有以下格式的字符串:
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";
字符串的问题之一是某些名称被重复,但是基本模式似乎是名称:值。 因此,我写了一种算法,该算法将使用一个名称并返回一个值,但是它似乎不起作用,并且没有考虑名称重复的问题。
因此,例如:如果我传入name1,我期望得到251等。
这是带有示例主代码的代码:
#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;
}
当我运行它时,我得到:
$ gcc -Wall -std=c99 -o parse parse.c && ./parse
value 1 = 251 name2: 23
value 3 = -67 name4: 0.00
value 17 = 6 name18: 0 name19: 500 name20: 200 name21:
而不是预期的
value 1 = 251
value 3 = -67
value 17 = 6
两个细微的错误。
第一,
if (end[i] != ':')
{
i++;
} else ..
通过在此处手动递增i
,您已经跳过了一个字符,因为i
已经通过for循环递增了。 它似乎没有副作用,而仅仅是因为...
第二:造成问题的实际原因是您正在测量错误的字符串的长度。 你找到的名称值(年初begining
),然后它的end
通过从该位置向前扫描下一个:
。 然后,您向后跟踪以找到前一个空格,该空格应为值的结尾。 但是...
for (i=0; i < strlen(end); i++)
从字符串(已确定)的末尾检查向前 ! 当然,对于您的测试名称,您一定会在更远的地方找到一个冒号-但它的位置与您感兴趣的字符串无关,该字符串介于begining
和end
之间。
将您的i
循环更改为
for (i=0; i < end-begining; i++)
然后将:
更改为
if (begining[i] == ':')
{
char namevalue[200];
... (etc.)
(丢弃i++
行)。
寻找单个字符的一种更快的方法是strchr
:
char* end = strchr(begining,':');
您可能想找到一种更好的定位name
策略。 如果要查找name1
,则可以找到name12
以及noname1
。
一种方法是使用strtok
将字符串拆分为令牌。 然后,任何以:
结尾的都是潜在名称,下一个标记是您要查找的值。 省略,因为它本身就是一个不错的练习。 (并且,如果您要尝试这样做: strtok
会修改原始字符串! )
最后,您可以不用所有这些循环即可:-)
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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.