如何将数组重复元素复制到另一数组并获取目标数组长度?
解决C语言中复制重复元素到目标数组并获取有效长度的问题
原代码存在的问题
copy_duplicates函数逻辑错误:找到重复元素时直接用原数组索引i给dst[i]赋值,会导致目标数组出现大量未初始化的空位,且同一个重复元素会被多次计数(比如原数组中的6出现两次,会被重复统计)。- 主函数中
int dst[?lenghtdst];写法非法:C语言里静态数组的大小必须是编译期常量,不能用运行时变量定义。 - 主函数未初始化变量
i,直接进入循环会触发未定义行为。 - 未接收
copy_duplicates的返回值,无法获取目标数组的有效元素个数。
解决方案1:先统计数量再填充数组
分两步处理:先遍历源数组统计去重后的重复元素数量,再创建足够大的目标数组并填充元素。
#include <stdlib.h> #include <stdio.h> #include <stdbool.h> #include <string.h> // 统计去重后的重复元素个数 size_t count_duplicates(const int src[], size_t len) { size_t count = 0; bool added[len]; // C99变长数组,不支持的话可以用malloc动态分配 memset(added, 0, sizeof(added)); for (size_t i = 0; i < len; i++) { if (added[i]) continue; // 跳过已统计过的重复元素 bool is_duplicate = false; for (size_t d = i + 1; d < len; d++) { if (src[i] == src[d]) { is_duplicate = true; added[d] = true; // 标记后续重复元素,避免重复统计 } } if (is_duplicate) count++; } return count; } // 复制去重后的重复元素到目标数组 size_t copy_duplicates(int dst[], const int src[], size_t len) { size_t idx = 0; bool added[len]; memset(added, 0, sizeof(added)); for (size_t i = 0; i < len; i++) { if (added[i]) continue; bool is_duplicate = false; for (size_t d = i + 1; d < len; d++) { if (src[i] == src[d]) { is_duplicate = true; added[d] = true; } } if (is_duplicate) dst[idx++] = src[i]; } return idx; } int main(void) { const int src[] = {6, 4, 6, 4}; size_t src_len = sizeof(src) / sizeof(src[0]); // 第一步:统计重复元素数量 size_t dst_len = count_duplicates(src, src_len); // 创建目标数组(C99变长数组,不支持则用malloc) int dst[dst_len]; // 第二步:复制元素并获取实际填充长度 size_t actual_len = copy_duplicates(dst, src, src_len); // 输出结果 for (size_t i = 0; i < actual_len; i++) { printf("%d ", dst[i]); } printf("\n"); return 0; }
解决方案2:动态分配目标数组内存
在函数内部分配内存,返回目标数组指针,同时通过指针参数传递有效长度,无需主函数提前知道数组大小。
#include <stdlib.h> #include <stdio.h> #include <stdbool.h> #include <string.h> // 动态分配内存并复制重复元素,返回数组指针,有效长度通过out_len输出 int* copy_duplicates(const int src[], size_t len, size_t* out_len) { *out_len = 0; bool* added = malloc(len * sizeof(bool)); if (!added) return NULL; memset(added, 0, len * sizeof(bool)); // 先统计重复元素数量 for (size_t i = 0; i < len; i++) { if (added[i]) continue; bool is_duplicate = false; for (size_t d = i + 1; d < len; d++) { if (src[i] == src[d]) { is_duplicate = true; added[d] = true; } } if (is_duplicate) (*out_len)++; } // 分配目标数组内存 int* dst = malloc(*out_len * sizeof(int)); if (!dst) { free(added); return NULL; } // 填充目标数组 size_t idx = 0; memset(added, 0, len * sizeof(bool)); // 重置标记 for (size_t i = 0; i < len; i++) { if (added[i]) continue; bool is_duplicate = false; for (size_t d = i + 1; d < len; d++) { if (src[i] == src[d]) { is_duplicate = true; added[d] = true; } } if (is_duplicate) dst[idx++] = src[i]; } free(added); return dst; } int main(void) { const int src[] = {6, 4, 6, 4}; size_t src_len = sizeof(src) / sizeof(src[0]); size_t dst_len; int* dst = copy_duplicates(src, src_len, &dst_len); if (dst) { for (size_t i = 0; i < dst_len; i++) { printf("%d ", dst[i]); } printf("\n"); free(dst); // 记得释放动态分配的内存 } return 0; }
注意事项
- 方案1的变长数组(VLA)需要编译器支持C99标准,不支持的话可以替换为
malloc动态分配。 - 方案2必须记得释放动态分配的内存,避免内存泄漏。
- 两种方案都解决了原代码中重复计数、目标数组长度未知的问题,能正确获取目标数组的有效元素个数。
内容的提问来源于stack exchange,提问作者Io12
相关产品推荐
相关产品推荐

