0

我有一个格式为:

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 等。

这是带有示例 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;
}

当我运行它时,我得到:

$ 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
4

1 回答 1

0

两个微妙的错误。

第一的,

if (end[i] != ':')
{
   i++;
} else ..

通过在此处手动递增i,您将跳过一个字符,因为ifor 循环已经递增了该字符。它似乎没有副作用,但只是因为......

第二:问题的实际原因是您测量了错误字符串的长度。您可以找到名称值 ( begining) 的开头,然后end从该位置向前扫描以查找下一个:。然后,您向后跟踪以找到前一个空格,这应该是值的结尾。但 ...

for (i=0; i < strlen(end); i++)

从字符串的(已经确定的)结尾向前检查!当然,对于您的测试名称,您肯定会在更远的地方找到一个冒号——但它的位置与您感兴趣的字符串无关,它位于and之间。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。然后任何以 a 结尾的:都是潜在名称,下一个标记是您要查找的值。省略,因为它本身就是一个很好的练习。(如果你要试试这个: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;
}
于 2013-10-20T11:21:48.817 回答