自定义随机字符串生成器中memcpy复制目标字符串出现垃圾字符问题求助
问题分析与修复方案
你的代码出现的两个问题,根源集中在字符串存储的数组声明错误、字符串复制未处理终止符以及变量作用域误用这几个点上,咱们一步步拆解解决:
核心问题拆解
1. 错误的二维数组声明
你用了char data[num_data][string_length];,但string_length在声明时是未初始化的变量,而且它的值是后续循环里动态变化的——C语言的变长数组(VLA)要求声明时大小必须是确定的,这直接导致data的每个元素长度完全不可控,要么是随机垃圾值,要么无法适配后续不同长度的字符串,这是残留内容和垃圾字符出现的核心原因。
2. 字符串复制未处理终止符
memcpy(data[i], str, sizeof(str))只复制了str里的字符,没把字符串的终止符'\0'复制进去,而且data[i]的长度和str不匹配时,打印会越界读取内存里的垃圾内容。
3. 重复检查时的变量作用域错误
当检测到重复字符串时,你在for循环内部重新声明了char str[string_length];,这个str是内层局部变量,和外面的str完全不是同一个——也就是说,你重新生成的字符串根本没替换掉原来的重复字符串,后续还是会把重复内容存进去。
4. 未初始化随机数种子
rand()在调用前没有用srand()初始化种子,每次运行程序生成的随机序列都是一样的,这虽然不是当前的直接问题,但也是随机生成器的必要优化点。
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> // Random string generator void rand_str(char *dest, size_t length) { char charset[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; int charset_length = 62; while (length-- > 0) { size_t index = rand() % charset_length; *dest++ = charset[index]; } *dest = '\0'; // 确保终止符被写入 } int main () { int num_data = 5; int max_string_length = 10; // 用指针数组存储每个动态分配的字符串,适配不同长度 char *data[num_data]; int i = 0; // 初始化随机数种子,让每次运行的随机序列不同 srand((unsigned int)time(NULL)); while (i < num_data) { // 生成3到max_string_length+2之间的长度(原逻辑:3 + 0~9 → 3~12) int string_length = 3 + (rand() % max_string_length); // 动态分配内存,多留1字节存终止符 char *str = malloc(string_length + 1); if (!str) { perror("malloc failed"); exit(EXIT_FAILURE); } rand_str(str, string_length); // 循环检查并生成,直到得到不重复的字符串 int is_duplicate = 0; do { is_duplicate = 0; for (int j = 0; j < i; j++) { if (!strcmp(data[j], str)) { is_duplicate = 1; free(str); // 释放重复的字符串内存 string_length = 3 + (rand() % max_string_length); str = malloc(string_length + 1); if (!str) { perror("malloc failed"); exit(EXIT_FAILURE); } rand_str(str, string_length); break; } } } while (is_duplicate); // 把生成的字符串存入data数组 data[i] = str; printf("生成的字符串:%s\n", str); printf("存储的字符串:%s\n\n", data[i]); i++; } // 释放动态分配的内存,避免内存泄漏 for (int j = 0; j < num_data; j++) { free(data[j]); } return 0; }
关键修复点说明
- 改用指针数组+动态内存分配:每个字符串根据实际长度动态分配内存,完美适配不同长度的字符串,彻底解决残留内容问题。
- 确保字符串终止符正确写入:
rand_str里明确写入'\0',动态分配时多留一个字节,保证终止符有存储空间。 - 修复重复检查逻辑:用do-while循环重复生成,直到得到不重复的字符串,同时修正了变量作用域问题,确保更新的是同一个字符串变量。
- 初始化随机数种子:让每次运行生成的随机序列都不一样,符合随机生成器的预期。
- 添加内存释放逻辑:避免内存泄漏,养成良好的C语言编程习惯。
内容的提问来源于stack exchange,提问作者Rusty
相关产品推荐
相关产品推荐

