"覆盖"文件中的重复值(C)

时间:2014-06-18 23:07:23

标签: c file overwrite

您好我有一点问题,但我找不到解决方案了。我有一个文件(data.txt),其中包含下一个信息:

5,5,6,2,5,2
1,4,2,3,7,2
4,2,5,2,3,4
5,5,6,2,5,2
4,5,2,6,2,4
2,1,5,6,3,2

我想将所有重复的行设置为0,例如:5,5,6,2,5,2出现两次,因此最终文件必须如下所示:

0,0,0,0,0,0
1,4,2,3,7,2
4,2,5,2,3,4
0,0,0,0,0,0
4,5,2,6,2,4
2,1,5,6,3,2

我尝试过使用辅助文件,但无法获得解决方案,我会在任何帮助下做到这一点。

我可以将这两行中的任何一行设置为0但不能同时设置为两行,如果同一行显示的次数超过两次,则相同。

1 个答案:

答案 0 :(得分:1)

您可以通过以下方式实现这一目标:

  • 首先在"r+"模式下打开输入/输出文件
  • 系统地将文件中的字符逐行添加到字符数组数组中
  • 相互比较行,将逗号以外的字符配对为零字符
  • 寻回文件
  • 将行重新写回文件,用新行分隔

要正确检测配对,您可以遵循以下逻辑:

  • 选择一行,随之创建变量并将其设置为1
  • 将该行与其他人比较
  • 如果匹配,请将变量设置为0并继续将您的线与其余部分进行比较
  • ...直到最后,将每个匹配的非逗号字符替换为零字符
  • 使用它们全部检查后,根据最初设置为1的变量的状态修改或不修改最初选择的行

这是一个有效的代码,除非你没有足够的内存,否则应该没有缺陷:

#include <stdio.h>
#include <malloc.h>
#include <string.h>

void settozero( char * line ) {
    for ( int i = 0; line[i] != '\0'; i++ )
        if ( line[i] != ',' )
            line[i] = '0';
}

int main( ) {

    char ** lines = NULL;
    FILE * input;

    if ( ( input = fopen( "input", "r+" ) ) == NULL ) {
        printf( "error at line %d", __LINE__ );
        return -1;
    }

    int currentchar;
    int newline = 1;
    int linecount = 0;
    int lineindex;
    int linesize;
    while ( ( currentchar = fgetc( input ) ) != EOF ) {
        if ( newline ) {
            linecount++;
            lineindex = 0;
            linesize = 128;
            lines = realloc( lines, linecount * sizeof * lines );
            lines[linecount - 1] = malloc( linesize );
            newline = 0;
        }
        if ( lineindex == linesize ) {
            linesize *= 3;
            lines[linecount - 1] = realloc( lines[linecount - 1], linesize );
        }
        if ( currentchar == '\n' ) {
            newline = 1;
            currentchar = '\0';
        }
        lines[linecount - 1][lineindex++] = currentchar;
    }

    if ( !newline ) {
        if ( lineindex == linesize )
            lines[linecount - 1] = realloc( lines[linecount - 1], linesize + 1 );
        lines[linecount - 1][lineindex] = '\0';
    }

    int * linestoskip = calloc( linecount, sizeof * linestoskip );

    for ( int i = 0; i < linecount; i++ ) {
        if ( linestoskip[i] )
            continue;

        int unique = 1;
        for ( int j = i + 1; j < linecount; j++ ) {
            if ( linestoskip[j] )
                continue;

            if ( strcmp( lines[i], lines[j] ) == 0 ) {
                unique = 0;
                settozero( lines[j] );
                linestoskip[j] = 1;
            }
        }
        if ( !unique )
            settozero( lines[i] );
    }

    free( linestoskip );
    fseek( input, 0L, SEEK_SET );

    for ( int i = 0; i < linecount; i++ ) {
        for ( int j = 0; lines[i][j] != '\0'; j++ ) {
            fputc( lines[i][j], input );
        }
        if ( i != linecount - 1 || newline )
            fputc( '\n', input );
        free( lines[i] );
    }

    free( lines );

    putchar( 10 );
    return 0;
}