memcpy() 在目标字符串中复制一些垃圾字符
memcpy() copies some garbage characters in the destination string
我正在尝试使用以下代码创建一个随机字符串生成器。
#include <stdio.h>
#include <stdlib.h>
#include <string.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 = '[=10=]';
}
int main ()
{
int num_data = 5;
int string_length;
int max_string_length = 10;
char data[num_data][string_length];
int i = 0;
while (i < num_data)
{
string_length = 3 + (rand() % max_string_length);
char str[string_length];
rand_str(str, string_length);
short increment_avoider_flag = 0;
for (int j = 0; j < i; j++)
{
if (!strcmp(data[j], str))
{
string_length = 3 + (rand() % max_string_length);
char str[string_length];
rand_str(str, string_length);
increment_avoider_flag = -1;
break;
}
}
if (!increment_avoider_flag)
{
memcpy(data[i], str, sizeof(str));
printf("%s\n", str);
printf("%s\n\n\n", data[i]);
i++;
}
}
}
上述代码的输出是
pn2QMwQbLq
pn2QMwQbLq~??
WqJ99NSq
WqJ99NSqLq~??
LDvi5z
LDvi5zSqLq~??
gxBewrk5rHr
gxBewrk5rHr??
DcDg
DcDgwrk5rHr??
这里的输出有两个问题。
- 如果创建的第一个字符串的长度 x 大于后面的字符串长度,memcpy 也会复制前一个字符串的剩余部分。例如第一个字符串是
pn2QMwQbLq
,第二个字符串是 WqJ99NSq
,但复制的字符串是 WqJ99NSqLq~??
,其中有第一个字符串的附加 Lq
。
- 复制的字符串中有一些乱码。例如第一个原始字符串
pn2QMwQbLq
但复制的字符串 pn2QMwQbLq~??
有额外的 ~??
.
我不确定这里发生了什么,但似乎我在错误地声明或复制字符数组。请帮我解决这个问题。
由于字符串长度每次都在变化,所以需要动态定义,下面是对代码的2处修改。
int main ()
{
int num_data = 5;
int string_length;
int max_string_length = 10;
//char data[num_data][string_length];
char **data = (char **)malloc(num_data * sizeof(char *)); //change1
int i = 0;
while (i < num_data)
{
string_length = 3 + (rand() % max_string_length);
data[i] = (char*)malloc(string_length * sizeof(char)); //change2
char str[string_length];
rand_str(str, string_length);
short increment_avoider_flag = 0;
如果你想生成没有任何内存泄漏的随机字符串。
以下代码实现了时间复杂度为 O(n)
的 map
结构,其中 n 是字符串的长度。
这不是 map
的良好实现,但是在 C 中创建 map
将是一项繁重的任务。
优点:
- 没有堆内存分配
- 最终的随机字符串中没有重复字符
缺点:
- 不是
map
的良好实现,因为时间复杂度应该是 O(log(n))
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
const char *charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
void random_str(char *str, size_t len);
void random_str(char *str, size_t len)
{
if (len == 0)
{
fprintf(stderr, "could not generate 0 length string\n");
exit(1);
}
for (size_t i = 0; i < len; i++)
{
str[i] = charset[(rand() % 62)];
}
str[len] = 0;
}
#define NUM_DATA 5
#define MAX_LEN 10
int main(void)
{
char rdata[NUM_DATA][MAX_LEN + 1] = {0};
srand(time(NULL));
for (size_t i = 0; i < NUM_DATA;)
{
int flag = 1;
random_str(rdata[i], MAX_LEN);
for (size_t j = 0; j < i; j++)
if (strcmp(rdata[i], rdata[j]) == 0)
flag = 0;
if (flag == 1)
{
printf("%s\n", rdata[i]);
i++;
}
}
return 0;
}
您的代码中存在多个导致未定义行为的问题:
定义 char data[num_data][string_length];
具有未定义的行为,因为 string_length
未初始化。您应该使用 char data[num_data][max_string_length + 1];
以允许空终止符。
3 + (rand() % max_string_length)
生成 3
到 max_string_length + 2
范围内的 pseudo-random 整数,这似乎不正确。您应该使用 3 + (rand() % (max_string_length - 2)
来获取 3
到 max_string_length
的范围。
char str[string_length];
定义数组 str
一个字节对于 string_length
个字符的字符串来说太短了。
如果发生碰撞,则无需生成新的随机字符串,尤其是在新的本地数组中。只需设置指标并跳出循环。
您可以通过在 for
循环外定义 j
并使用 i == j
检查没有重复项来消除对指标的需求。
您应该为随机数生成器设置种子以避免在每个 运行 生成相同的字符串。使用 srand(time(NULL));
意外输出是由未定义的行为引起的。
这是修改后的版本:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
// Random string generator
void rand_str(char *dest, size_t length) {
static const char charset[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
int charset_length = sizeof(charset) - 1;
while (length-- > 0) {
size_t index = rand() % charset_length;
*dest++ = charset[index];
}
*dest = '[=10=]';
}
int main() {
int num_data = 5;
int max_string_length = 10;
char data[num_data][max_string_length + 1];
int i = 0, j;
srand(time(NULL));
while (i < num_data) {
int string_length = 3 + (rand() % (max_string_length - 2));
char str[string_length + 1];
rand_str(str, string_length);
for (j = 0; j < i; j++) {
if (!strcmp(data[j], str))
break;
}
if (j == i) {
strcpy(data[i], str);
printf("%s\n", str);
i++;
}
}
printf("\n");
for (i = 0; i < num_data; i++) {
printf("%s\n", data[i]);
}
return 0;
}
我正在尝试使用以下代码创建一个随机字符串生成器。
#include <stdio.h>
#include <stdlib.h>
#include <string.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 = '[=10=]';
}
int main ()
{
int num_data = 5;
int string_length;
int max_string_length = 10;
char data[num_data][string_length];
int i = 0;
while (i < num_data)
{
string_length = 3 + (rand() % max_string_length);
char str[string_length];
rand_str(str, string_length);
short increment_avoider_flag = 0;
for (int j = 0; j < i; j++)
{
if (!strcmp(data[j], str))
{
string_length = 3 + (rand() % max_string_length);
char str[string_length];
rand_str(str, string_length);
increment_avoider_flag = -1;
break;
}
}
if (!increment_avoider_flag)
{
memcpy(data[i], str, sizeof(str));
printf("%s\n", str);
printf("%s\n\n\n", data[i]);
i++;
}
}
}
上述代码的输出是
pn2QMwQbLq
pn2QMwQbLq~??
WqJ99NSq
WqJ99NSqLq~??
LDvi5z
LDvi5zSqLq~??
gxBewrk5rHr
gxBewrk5rHr??
DcDg
DcDgwrk5rHr??
这里的输出有两个问题。
- 如果创建的第一个字符串的长度 x 大于后面的字符串长度,memcpy 也会复制前一个字符串的剩余部分。例如第一个字符串是
pn2QMwQbLq
,第二个字符串是WqJ99NSq
,但复制的字符串是WqJ99NSqLq~??
,其中有第一个字符串的附加Lq
。 - 复制的字符串中有一些乱码。例如第一个原始字符串
pn2QMwQbLq
但复制的字符串pn2QMwQbLq~??
有额外的~??
.
我不确定这里发生了什么,但似乎我在错误地声明或复制字符数组。请帮我解决这个问题。
由于字符串长度每次都在变化,所以需要动态定义,下面是对代码的2处修改。
int main ()
{
int num_data = 5;
int string_length;
int max_string_length = 10;
//char data[num_data][string_length];
char **data = (char **)malloc(num_data * sizeof(char *)); //change1
int i = 0;
while (i < num_data)
{
string_length = 3 + (rand() % max_string_length);
data[i] = (char*)malloc(string_length * sizeof(char)); //change2
char str[string_length];
rand_str(str, string_length);
short increment_avoider_flag = 0;
如果你想生成没有任何内存泄漏的随机字符串。
以下代码实现了时间复杂度为 O(n)
的 map
结构,其中 n 是字符串的长度。
这不是 map
的良好实现,但是在 C 中创建 map
将是一项繁重的任务。
优点:
- 没有堆内存分配
- 最终的随机字符串中没有重复字符
缺点:
- 不是
map
的良好实现,因为时间复杂度应该是O(log(n))
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
const char *charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
void random_str(char *str, size_t len);
void random_str(char *str, size_t len)
{
if (len == 0)
{
fprintf(stderr, "could not generate 0 length string\n");
exit(1);
}
for (size_t i = 0; i < len; i++)
{
str[i] = charset[(rand() % 62)];
}
str[len] = 0;
}
#define NUM_DATA 5
#define MAX_LEN 10
int main(void)
{
char rdata[NUM_DATA][MAX_LEN + 1] = {0};
srand(time(NULL));
for (size_t i = 0; i < NUM_DATA;)
{
int flag = 1;
random_str(rdata[i], MAX_LEN);
for (size_t j = 0; j < i; j++)
if (strcmp(rdata[i], rdata[j]) == 0)
flag = 0;
if (flag == 1)
{
printf("%s\n", rdata[i]);
i++;
}
}
return 0;
}
您的代码中存在多个导致未定义行为的问题:
定义
char data[num_data][string_length];
具有未定义的行为,因为string_length
未初始化。您应该使用char data[num_data][max_string_length + 1];
以允许空终止符。3 + (rand() % max_string_length)
生成3
到max_string_length + 2
范围内的 pseudo-random 整数,这似乎不正确。您应该使用3 + (rand() % (max_string_length - 2)
来获取3
到max_string_length
的范围。char str[string_length];
定义数组str
一个字节对于string_length
个字符的字符串来说太短了。如果发生碰撞,则无需生成新的随机字符串,尤其是在新的本地数组中。只需设置指标并跳出循环。
您可以通过在
for
循环外定义j
并使用i == j
检查没有重复项来消除对指标的需求。您应该为随机数生成器设置种子以避免在每个 运行 生成相同的字符串。使用
srand(time(NULL));
意外输出是由未定义的行为引起的。
这是修改后的版本:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
// Random string generator
void rand_str(char *dest, size_t length) {
static const char charset[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
int charset_length = sizeof(charset) - 1;
while (length-- > 0) {
size_t index = rand() % charset_length;
*dest++ = charset[index];
}
*dest = '[=10=]';
}
int main() {
int num_data = 5;
int max_string_length = 10;
char data[num_data][max_string_length + 1];
int i = 0, j;
srand(time(NULL));
while (i < num_data) {
int string_length = 3 + (rand() % (max_string_length - 2));
char str[string_length + 1];
rand_str(str, string_length);
for (j = 0; j < i; j++) {
if (!strcmp(data[j], str))
break;
}
if (j == i) {
strcpy(data[i], str);
printf("%s\n", str);
i++;
}
}
printf("\n");
for (i = 0; i < num_data; i++) {
printf("%s\n", data[i]);
}
return 0;
}