在C中的文件中交换行

时间:2017-03-21 15:09:52

标签: c file swap

嗨我在尝试在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。

对于编写文件的混乱方式感到抱歉

2 个答案:

答案 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声明的更新,其中len1len2分别为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