嗨我在尝试在C中使用许多记录的文件中实现冒泡排序时遇到了问题。
我必须只修改我的文件而不使用任何临时文件。每当我尝试在我的文件中交换两行时,我设法写第二行而不是第一行成功,但是当我尝试写第一行而不是第二行时,它似乎在第二行之后覆盖行。我知道这是因为线条的长度不一样,但是有没有办法可以用空的字符填充线条或成功做到这一点?
这里是代码:(由于某种原因,似乎无法上传变量声明......) 相关部分属于if条件
for(j=0; j<linesNum-1; j++)
{
for(k=0; k<linesNum-j-1; k++)
{
getline(&line1, &len, fp);
pos = ftell(fp);
getline(&line2, &len, fp);
int i;
char *tmp1 = (char*)malloc(sizeof(char)*strlen(line1));
char *tmp2 = (char*)malloc(sizeof(char)*strlen(line2));
strcpy(tmp1, line1);
strcpy(tmp2, line2);
token1 = strtok(tmp1, del);
for(i=0; i<field; i++)
{
token1 = strtok(NULL, del);
}
token2 = strtok(tmp2, del);
for(i=0; i<field; i++)
{
token2 = strtok(NULL, del);
}
if(strcmp(token1, token2) > 0)
{
fseek(fp, -(strlen(line1)+strlen(line2)), SEEK_CUR);
fputs(line2, fp);
//fsetpos(fp, &pos);
fputs(line1, fp);
}
fsetpos(fp, &pos);
free(tmp1);
free(tmp2);
}
}
}
来自此文件:
GNY1MJS2X,Mulan,Tony Bancroft,88,Harvey Fierstein,USA,7.5,Adventure
A1F9ENILS,Tropic Thunder,Ben Stiller,121,Steve Coogan,USA,7,Action
3YRMEJM1Y,The Departed,Martin Scorsese,151,Matt Damon,USA,8.5,Crime
NQMNMMOMR,The Girl with the Dragon Tattoo,David Fincher,158,Goran Visnjic,USA,7.8,Crime
FT2ULUNQ5,Die Hard with a Vengeance,John McTiernan,128,Aldis Hodge,USA,7.6,Action
我似乎得到了这个:
A1F9ENILS,Tropic Thunder,Ben Stiller,121,Steve Coogan,USA,7,Action
GNY1MJS2X,Mulan,Tony Bancroft,88,Harvey Fierstein,USA,7.5,Adventure
YRMEJM1Y,The Departed,Martin Scorsese,151,Matt Damon,USA,8.5,Crime
NQMNMMOMR,The Girl with the Dragon Tattoo,David Fincher,158,Goran Visnjic,USA,7.8,Crime
FT2ULUNQ5,Die Hard with a Vengeance,John McTiernan,128,Aldis Hodge,USA,7.6,Action
在第一行和第二行之间有一个空行......它也会破坏下一行。
另外,我按逗号分隔的一个字段排序,说第一个字段是电影ID。
对于编写文件的混乱方式感到抱歉
答案 0 :(得分:0)
首先,考虑一下你的算法。
您始终将 N 行与 N-1 行进行比较。读取第1行后,始终将当前行(从第2行开始)与前一行进行比较。跟踪文件中 N-1 行的偏移量,因为当您进行交换时,您将 N 行写入 N-1 < / em>位置。您不需要跟踪当前位置,因为在您按交换顺序查找和写入行之后,您将处于下一行的开头。
所以,你的算法就像:
do
pos = 0
read prev
while read curr
if curr < prev
seek to pos
write curr
write prev
copy prev to curr (for the next comparison)
nswapped++
pos = ftell
rewind
until nswapped == 0
我没有尝试调试你的程序,因为无论出现什么问题都是你所引入的复杂性的一部分。如果您将工作量降至最低,任何错误都将变得更加明显。
答案 1 :(得分:0)
您看到输出损坏的原因是您将位置设置回line1结束的位置,即使换行也是如此。如果line1和line2的长度不同,则会出现问题。
为了最大限度地减少重构,您可以在交换时向后搜索line1的长度,如果不进行交换,则可以向后搜索line2的长度。
以下是if
声明的更新,其中len1
和len2
分别为line1和line2的长度。
if(strcmp(token1, token2) > 0)
{
fseek(fp, -(len1 + len2), SEEK_CUR);
fputs(line2, fp);
fputs(line1, fp);
fseek(fp, -len1, SEEK_CUR);
}
else
{
fseek(fp, -len2, SEEK_CUR);
}
如果您想要返回文件,我还认为您需要在外部循环中rewind
。