我正在尝试解析一些 CSV 日志文件,只提取第 n 个字段(为了速度而忽略其他字段)。当我使用 fread 大于输入大小时的缓冲区大小时,我的函数按预期工作。
问题是当我读取部分输入并尝试在下次调用该函数时从我中断的地方继续。我认为问题在于我如何处理空终止符和设置我的全局变量,但我似乎无法弄清楚。
非常感谢任何有助于理解我做错了什么的人!
代码
#include <stdio.h>
#include <time.h>
int gcomc = 0;
int gpos = 0;
void test(char *str, int len)
{
const char *ptr = str;
char ch;
int i;
char so[10];
int comc = gcomc;
int pos = gpos;
for(i = 0; i < len; i++)
{
ch = ptr[i];
switch(ch)
{
case ';':
comc++;
break;
case '\0':
gcomc = comc;
gpos = pos;
break;
default:
if (comc == 3) {
ch = ptr[i];
so[pos++] = ch;
}
if (comc == 7) {
printf(" %s ", so);
comc = 0;
pos = 0;
gcomc = 0;
gpos = 0;
}
}
}
return;
}
int main(int argc, char* argv[])
{
FILE *fin=fopen("test.txt", "rb");
char buffer[100 + 1];
size_t bsz;
while((bsz = fread(buffer, sizeof *buffer, 100, fin)) > 0)
{
buffer[bsz] = '\0';
test(buffer, bsz);
}
return 1;
}
输入
A;B;C;D;E;F;G;H
I;J;K;L;M;N;O;P
Q;R;S;T;U;V;W;X
Y;Z;1;2;3;4;5;6
缓冲区大小为 100 (101) 的输出
D L T 2
缓冲区大小为 10 (11) 的输出
D P
Q X
Segmentation fault (core dumped)
编辑: 感谢您的评论和代码,我已经修改了我的(相当愚蠢的)代码 - 欢迎任何进一步的批评(建设性的或破坏性的,我从中吸取教训):
#include <stdio.h>
#include <time.h>
void test(char *str, int len);
int gcomc, gpos = 0;
void test(char *str, int len)
{
const char *ptr = str;
char ch;
int i;
static char so[10];
for(i = 0; i < len; i++)
{
ch = ptr[i];
switch(ch)
{
case ';':
gcomc++;
break;
default:
if (gcomc == 3) {
ch = ptr[i];
so[gpos++] = ch;
}
if (gcomc == 7) {
so[gpos] = '\0'; /* ensure so is null terminated */
printf(" %s ", so);
gcomc = 0;
gpos = 0;
}
}
}
return;
}
extern int main()
{
FILE *fin=fopen("test.txt", "rb");
char buffer[10 + 1];
size_t bsz;
while((bsz = fread(buffer, sizeof *buffer, sizeof buffer, fin)) > 0)
{
test(buffer, bsz);
}
return 1;
}
最佳答案
您的代码中至少存在两个问题才能分块读取文件。
首先,so
array 是自动的:它没有理由在一次调用中保留其值。您应该将其声明为全局(在测试函数之外)或静态。
接下来,只有在找到 null 时才将本地状态复制到全局状态。但是 null 位于 len 位置,并且您在之前退出循环(for(i = 0; i < len; i++)
请注意 <
),因此在下一次调用时您将再次从 0、0 开始。您应该选择一种方法来指示缓冲区的末尾,要么传递一个长度,要么写入一个空标记,但混合两者很容易出错。当你使用 fread
,我的建议是坚持一个长度:
主要用途:
while((bsz = fread(buffer, sizeof *buffer, sizeof buffer, fin)) > 0)
{
test(buffer, bsz);
}
(这样,你只写一次缓冲区的大小)
并在测试中:
void test(char *str, int len)
{
const char *ptr = str;
char ch;
int i;
static char so[10];
int comc = gcomc;
int pos = gpos;
for(i = 0; i < len; i++)
{
ch = ptr[i];
switch(ch)
{
case ';':
comc++;
break;
default:
if (comc == 3) {
ch = ptr[i];
so[pos++] = ch;
}
if (comc == 7) {
so[pos] = '\0'; /* ensure so is null terminated */
printf(" %s ", so);
comc = 0;
pos = 0;
gcomc = 0;
gpos = 0;
}
}
}
gcomc = comc; /* store the state to globals */
gpos = pos;
return;
}
但是正如您在评论中所说,混合本地和全局变量很容易出错。看起来您在设计程序结构和确定实际需要全局的内容之前就开始编码了。你没有,是吗? ;-)
关于c - 函数 'saving progress' 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39658965/