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() 上。那是慢。

Bart 的意思是一个 char[] 数组可以包含多个字符串,背靠背。如果您将数组作为单个字符串扫描一次,将所有 ',' 字符更改为 '\0',您的最后一行将如下所示:

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

下面的 ^ 插入符号标记了您将记录指向三个字符串的指针的位置。如您所见,它们等效于单独数组中的单独字符串“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);
}

显然你不需要一个 1K 的缓冲区来处理三个值,所以会有一个循环来提取这些值。前两个 strtol() 调用之后的 if 语句是您对 getfield() 的替代,它不再需要。

完成此操作后,查看数据验证。此(或原始)中的任何内容都不会检测到无效数字。

于 2012-11-02T12:34:56.523 回答