You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言动态数组重复元素删除问题求助

解决动态数组去重失败的问题

我来帮你排查下代码里的问题,你的去重逻辑和文件读取部分都有几个关键点需要修正,咱们一步步来:

1. 文件读取的feof陷阱

你用while(!feof(f))作为循环条件是个常见的坑——feof只有在尝试读取并失败后才会被置为真,这意味着当文件最后一个整数读完后,循环还会多执行一次:这次fscanf会失败,但你还是会realloc数组、给v[n]赋一个不确定的垃圾值,同时n会多计数1,导致数组末尾出现无效数据,后续排序和去重都会受影响。

正确的做法是把fscanf的返回值作为循环条件,因为fscanf成功读取一个整数时会返回1,遇到文件结束或读取失败时返回其他值:

while(fscanf(f,"%d", &v[n]) == 1) {
    v = realloc(v, (n+1)*sizeof(int));
    n++;
}

(另外,malloc和realloc在C里不需要强制转换为int*,不过这不是功能问题,只是代码风格的小细节)

2. 去重逻辑的核心错误

你当前的去重代码逻辑完全不对:

  • 循环从j=n开始,v[j]是数组越界访问(数组下标范围是0到n-1),会触发未定义行为;
  • 每次发现重复就直接realloc缩小数组,但没有把重复元素后面的有效数据往前移动,也没有更新n的值,最后输出还是用原来的n,会访问到已经被释放的内存或垃圾值;
  • 频繁调用realloc效率极低,也不是正确的去重姿势。

因为数组已经用快速排序排好序了,我们可以用双指针法高效去重:

  • 用变量k记录不重复元素的最后位置,初始为0;
  • 从i=1开始遍历数组,如果当前元素v[i]和v[k]不相等,就把v[i]放到v[++k]的位置;
  • 遍历结束后,k+1就是不重复元素的总个数,再重新分配数组内存并更新n。

修正后的完整代码

#include <stdio.h>
#include <stdlib.h>

// 假设你的OrdenarQuicksort函数已经正确实现
void OrdenarQuicksort(int *v, int inicio, int fim);

int main(){ 
    FILE *f; 
    int *v; 
    int n=0, i, k; 

    f = fopen("InteirosComRepetidos.txt","r");
    if(f == NULL) { // 别忘了检查文件是否成功打开
        printf("无法打开文件!\n");
        return 1;
    }

    v = malloc(sizeof(int));
    if(v == NULL) { // 检查内存分配是否成功
        printf("内存分配失败!\n");
        fclose(f);
        return 1;
    }

    // 正确读取文件内容
    while(fscanf(f,"%d", &v[n]) == 1) {
        v = realloc(v, (n+1)*sizeof(int));
        if(v == NULL) { // 检查realloc是否成功
            printf("内存重新分配失败!\n");
            free(v);
            fclose(f);
            return 1;
        }
        n++;
    }
    fclose(f); // 读完文件及时关闭

    OrdenarQuicksort(v, 0, n-1); // 注意这里的参数,fim应该是n-1而不是n,避免越界
    printf("排序后:\n");
    for(i=0; i<n; i++){ 
        printf("%d\n",v[i]); 
    } 

    // 去重逻辑:双指针法
    if(n == 0) { // 处理空数组的情况
        printf("无元素可去重\n");
    } else {
        k = 0;
        for(i=1; i<n; i++){
            if(v[i] != v[k]){
                v[++k] = v[i];
            }
        }
        // 重新分配内存到不重复元素的个数
        v = realloc(v, (k+1)*sizeof(int));
        if(v == NULL) {
            printf("内存重新分配失败!\n");
            free(v);
            return 1;
        }
        n = k+1; // 更新元素个数
    }

    printf("去重后:\n");
    for(i=0; i<n; i++){ 
        printf("%d\n",v[i]); 
    } 

    free(v); // 释放动态分配的内存
    system("pause"); 
    return 0;
}

额外注意点

  • 每次调用malloc和realloc都要检查返回值是否为NULL,避免内存分配失败导致的程序崩溃;
  • 调用OrdenarQuicksort时,fim参数应该是n-1,因为数组下标从0开始,否则会访问越界;
  • 用完文件和动态内存后要及时关闭/释放,避免资源泄漏。

内容的提问来源于stack exchange,提问作者Rúben Cardoso

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:06:19