我有一个数据挖掘类(class)的项目,我必须在其中编写文件的水库采样算法。该程序将数字 k、输入文件的名称和要创建的输出文件的名称作为输入。输出文件必须包含来自输入的 k 个随机行。我尝试了一些东西,但输出是错误的。
这是我使用的代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
int countLines(FILE* file)
{
char ch,lines=0;
while ((ch=fgetc(file)) != EOF)
if (ch=='\n')
lines++;
return(lines);
}
void itemSelection(FILE* fp1, FILE* fp2, int k)
{
int i,j,n,test=0;
char line[256];
char** buffer;
srand((unsigned int) time(NULL));
buffer = (char**)malloc(sizeof(char*));
for(i=0;i<k;i++)
buffer[i] = (char*)malloc(256*sizeof(char));
n = countLines(fp1);
if(k>n)
{
rewind(fp1);
while(fgets(line, 256, fp1)!=NULL)
{
printf("%s test\n",line);
fprintf(fp2,"%s",line);
}
}
else
{
rewind(fp1);
for(i=0;i<k;i++)
{
fgets(line, 256, fp1);
buffer[i]=line;
printf("first k lines:\t%s\n",buffer[i]);
}
for(i=k;i<n;i++)
{
fgets(line,256,fp1);
printf("line is:\t%s.\n", line);
j = rand() % (i+1);
if(j<k)
{
buffer[j]=line;
printf("later parts are:\t%s. J is:%d.\n",buffer[j],j);
}
}
}
for(i=0;i<k;i++)
printf("buffer test:\t%s.\n", buffer[i]);
}
void printFunc(FILE* fp2,int k)
{
char line[256];
int i;
rewind(fp2);
for(i=0;i<k;i++)
{
fgets(line, 256, fp2);
printf("print test is:\t%s.\n",line);
}
}
void main(int args, char** argv)
{
FILE* fp1;
FILE* fp2;
int k;
if(args<4)
{
printf("Expected more arguments!\n");
exit(-1);
}
fp1 = fopen(argv[2],"r");
if(fp1 == NULL)
{
printf("Could not open input file!\n");
perror("Error: ");
exit(-1);
}
fp2 = fopen(argv[3],"w");
if(fp2 == NULL)
{
printf("Could not open output file!\n");
perror("Error: ");
exit(-1);
}
k = atoi(argv[1]);
itemSelection(fp1, fp2, k);
printFunc(fp2,k);
fclose(fp1);
fclose(fp2);
}
这个程序试图做的是从文件中读取前 k 行并将其存储在一个 (k,256) 大小的二维字符串数组中。然后为下一行生成一个随机数 j,如果该数字小于 k,则将 buffer[j] 替换为从文件中获取的最新行。
然而,我得到的输出由 k 行 组成,这是输入的最后一个字符。
像这样(例如 k=5):
}
}
}
}
}
当我打印缓冲区以查看其内容时,它显示正确。但是当我写入文件时,它会写入错误的输出。
任何帮助将不胜感激!提前致谢!
最佳答案
当你选择行时,你必须复制行的内容,而不是指针(它始终是行
,其内容将不断被覆盖):
buffer[i]=line;
应该是
strcpy(buffer[i], line);
buffer[j]
也是如此。
你也有一个分配错误:
buffer = (char**)malloc(sizeof(char*));
应该是:
buffer = malloc(k * sizeof(char*));
为 k
字符串腾出空间(并注意关于 casting the result of malloc in C 的流行建议)。你还应该考虑你想用 buffer
做什么:你是否返回它,以便客户端代码可以使用它(并且必须 free
它)或者它是本地的到 itemSelection
,它应该在返回之前释放
。目前你两者都不做。
最后,在您的 countLines
函数中,变量应该是 int
,而不是 char
:fgetc
返回一个 int,因此您可以区分所有有效(无符号)char
值和特殊值 EOF
。
关于c - 水库采样算法不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26608305/