繁体   English   中英

用C解析问题

[英]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++)

从字符串(已确定)的末尾检查向前 当然,对于您的测试名称,您一定会在更远的地方找到一个冒号-但它的位置与您感兴趣的字符串无关,该字符串介于beginingend之间。

将您的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM