#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)
答案 0 :(得分:3)
您可以通过创建一个快速split
函数来加速它,这将破坏您的line
(更不用说潜伏的分段错误和内存泄漏;此代码没有错误检查或{{1资源):
free
结果:
#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]);
}
答案 1 :(得分:1)
我没有对你的代码进行时序测试,但我敢打赌镍问题是使用malloc()。那很慢。
Bart意味着char []数组可以包含多个字符串,背靠背。如果您将数组扫描为单个字符串一次,将所有','字符更改为'\ 0',您的最后一行将如下所示:
{ '2', '5', 0, 0, '4', '5', 0, ? rest of buffer }
^ ^ ^ !
下面的^ carets标记了记录指向三个字符串的指针的位置。如您所见,它们相当于单独数组中单独的“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()的替代品,不再需要它。
在此工作之后,查看数据验证。此(或原始)中的任何内容都不会检测到无效数字。