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";

文字列の問題の 1 つは、一部の名前が繰り返されていることですが、基本的なパターンは名前: 値のように見えます。そこで、名前を受け取って値を返すアルゴリズムを書きましたが、機能していないようで、名前が繰り返される問題を考慮していません。

たとえば、 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
4

1 に答える 1

0

2つの微妙なエラー。

初め、

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

ここで手動でインクリメントすると、for ループによって既にインクリメントされているためi、文字をスキップしています。副作用はないようですが、それi...

2 番目: 問題の実際の原因は、間違った文字列の長さを測定していることです。名前の値 ( 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見つかる可能性があります。name12noname1

1 つの方法は、 を使用して文字列をトークンに分割すること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 に答える