0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* getfield(char* line, int num) {
    char* tok = line;
    char* result;
    if (line)
    {
        do
        {
            if (!--num)
            {
                tok = strchr(line, ',');
                if (tok == NULL)
                {
                    tok = &line[strlen(line)];
                }
                size_t fieldlen = tok - line;
                if (fieldlen)
                {
                    result = (char*)malloc(fieldlen+1);
                    result[fieldlen] = '\0';
                    strncpy(result, line, fieldlen);
                    return result;
                }
                else
                {
                    break;
                }
            }
            tok = strchr(line, ',');
            line = tok + 1;
        } while (tok);
    }
    result = (char*)malloc(2);
    strcpy(result, "0");
    return result;
}

int main()
{
    FILE* stream = fopen("data.csv", "r");
    char line[1024];
    char *pstr;int num1,num2,num3;
    char* value1,value2,value3;

    while (fgets(line, 1024, stream))
    {
        char* tmp = strdup(line);

        value1=getfield(tmp, 1);
        value2=getfield(tmp, 2);
        value3=getfield(tmp, 3);

        num1 =strtol(value1,&pstr,10);
        num2 =strtol(value2,&pstr,10);
        num3 =strtol(value3,&pstr,10)
        free(value1); 
        free(value2); 
        free(value3);
        printf("Fields 1,2,3 would be 1=%d 2=%d 3=%d\n", num1,num2,num3);
        // NOTE strtok clobbers tmp
        free(tmp);
    }
}

上記はファイルを読み取るための私のCコードです....

 :::: data.csv ::::
    10,34,30
    10,33,
    23,45,23
    25,,45

上記は私のファイルです..

ここで私の問題は、「num」フィールドで関数を呼び出すことができることです。そのため、すべての行を読み取るために、関数を3回呼び出すと思います.. !! そのため、大きなデータファイルのパフォーマンスが低すぎます..関数を一度に呼び出すことができ、配列が返されることを誰かが助けてくれます..簡単に保存して印刷できます(たとえば、最初の行の配列[0] =10,配列[1]=34,配列[2]=30)

4

2 に答える 2

3

splitあなたはあなたを破壊する高速関数を作成することによってそれをスピードアップすることができますline (多くの潜在的なセグメンテーション違反とメモリ リークは言うまでもありません; このコードにはエラー チェックやfreeリソースの ing はありません):

#include <stdio.h>
#include <stdlib.h>

char **split(char *line, char sep, int fields) {
  char **r = (char **)malloc(fields * sizeof(char*));

  int lptr = 0, fptr = 0;
  r[fptr++] = line;

  while (line[lptr]) {
    if (line[lptr] == sep) {
      line[lptr] = '\0';
      r[fptr] = &(line[lptr+1]);
      fptr++;
    }

    lptr++;
  }

  return r;
}

int main(int argc, char **argv) {
  char line[] = "some,info,in a line";

  char **fields = split(line, ',', 3);

  printf("0:%s 1:%s 2:%s\n", fields[0], fields[1], fields[2]);
}

結果:

0:some 1:info 2:in a line
于 2012-11-02T11:21:21.610 に答える
1

私はあなたのコードでタイミング テストを実行していませんが、問題が malloc() を使用していることに賭けます。それがSLOWです。

Bart が意味することは、char[] 配列には複数の文字列を連続して含めることができるということです。配列を 1 つの文字列として 1 回スキャンし、すべての「,」文字を「\0」に変更すると、最後の行は次のようになります。

{ '2', '5', 0, 0, '4', '5', 0, ? rest of buffer }
   ^           ^   ^        !

以下の ^ キャレットは、3 つの文字列へのポインターを記録する位置を示します。ご覧のとおり、これらは個別の配列で "25"、""、"45" の個別の文字列と同等です。!以下は、元の文字列を終了する 0 をマークします。それ以上のことは何の意味もありません。

これはすべて、元の文字列をその場で変更できることに依存しており、おそらくそれ以降の処理には役に立たなくなります (無効なフィールドが検出された場合に問題のある行を出力するなど)。ただし、ローカルで使用するために元のバッファーを既にコピーしているため、問題にはなりません。ちなみに、そのコピー バッファの malloc も削除します。

コードは次のようになります。

while (fgets(line, 1024, stream))
{
    char tmp[sizeof line]; /* this will save a malloc()/free() pair */
    char *tok, *fence, *pstr;
    char ch, *cp1=line, *cp2=tmp;

    while (0 != (ch = *cp1++))
        *cp2++ = (ch == ',') ? 0 : ch;

    fence = cp2; /* remember end of string */
    *fence = 0;  /* and terminate final string */
    tok = tmp;   /* point to first token */

    num1 =strtol(tok, &pstr, 10);
    if (tok < fence) tok += strlen(tok) + 1;

    num2 =strtol(tok,&pstr,10);
    if (tok < fence) tok += strlen(tok) + 1;

    num3 =strtol(tok,&pstr,10);

    printf("Fields 1,2,3 would be 1=%d 2=%d 3=%d\n", num1,num2,num3);
}

明らかに、3 つの値を処理するために 1K のバッファーは必要ないため、値を引き出すためのループが発生します。最初の 2 つの strtol() 呼び出しの後の if ステートメントは、getfield() の代わりになりますが、これはもう必要ありません。

これが機能したら、データ検証を見てください。これ (またはオリジナル) の何も無効な番号を検出しません。

于 2012-11-02T12:34:56.523 に答える