【发布时间】:2021-01-13 06:58:43
【问题描述】:
快速总结 - 我正在测试我的函数,为此,我决定编写自己的 add_as_first() 和 add_as_last() 函数,它们通过创建一个新的字符串数组并将字符添加到旧字符串数组中一个副本,不使用默认的 c 语言字符串函数。出于某种原因,二分之一的字符串数组的行为不像我希望的那样。我添加了用于调试的 strlen() 函数,我可以看到在 print_file 函数中,我的字符串数组非常健康,并且随着函数的循环而变大。但是由于某种原因,当函数结束时,字符串“res”之一的长度恢复为 0,而第二个字符串“body”得到了适当的变异并具有应该具有的值。它们之间的区别在于,“res”是通过在 print_file 循环函数中使用 add_as_last() 函数来填充的,而“body”是通过在 print_file() 函数内部使用 add_as_first() 函数来填充的。 )。知道为什么它会这样吗?这看起来像是范围界定问题,但考虑到“body”和“res”的使用方式大致相同,它应该可以正常工作。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define x_size 4
#define y_size 4
char* add_as_first(char *given_arr, char given_char, int check) {
int strLen = 0;
while (given_arr[strLen] != '\0') {
strLen++;
}
char *new_arr;
new_arr = (char*)malloc((strLen + 1 + 1) * sizeof(char));
new_arr[0] = given_char;
int i = 0;
for (; i < strLen; i++) {
new_arr[i + 1] = given_arr[i];
}
new_arr[i + 1] = '\0';
if ((i + 1 + 1) != (strLen + 1 + 1)) {
printf("WE GOT A MEMORY LEAK OUT THERE\n");
}
if (check != 0) {
free(given_arr);
}
return new_arr;
}
char* add_as_last(char *given_arr, char given_char, int check) {
int strLen = 0;
while (given_arr[strLen] != '\0') {
strLen++;
}
char* newString = (char*)malloc((strLen + 1 + 1) * sizeof(char));
int i = 0;
for(; i < strLen; i++) {
newString[i] = given_arr[i];
}
newString[i] = given_char;
newString[i + 1] = '\0';
if ((i + 1 + 1) != (strLen + 1 + 1)) {
printf("WE GOT A MEMORY LEAK OUT THERE\n");
}
return newString;
}
void forming_list(int file_arr[][y_size], int i, int j, char body[]) {
char thing = '0';
thing = j + '0';
body = add_as_first(body, thing, 1);
body = add_as_first(body, ',', 1);
thing = i + '0';
body = add_as_first(body, thing, 1);
body = add_as_first(body, ' ', 1);
if ((file_arr[i][j] == 1) || (file_arr[i][j] == 5)) {
if (j < x_size - 1) {
forming_list(file_arr, i, j + 1, body);
} else {
forming_list(file_arr, i + 1, 0, body);
}
} else if ((file_arr[i][j] == 2) || (file_arr[i][j] == 6)) {
if (j != 0) {
forming_list(file_arr, i, j - 1, body);
} else {
forming_list(file_arr, i - 1, x_size - 1, body);
}
} else if ((file_arr[i][j] == 3) || (file_arr[i][j] == 7)) {
if (i == 0) {
forming_list(file_arr, y_size - 1, j, body);
} else {
forming_list(file_arr, i - 1, j, body);
}
} else if ((file_arr[i][j] == 4) || (file_arr[i][j] == 8)) {
if (i == y_size - 1) {
forming_list(file_arr, 0, j, body);
} else {
forming_list(file_arr, i + 1, j, body);
}
}
}
void print_file(int file_arr[][y_size], char *res, char *body) {
int i = 0;
int j = 0;
for(i; i < y_size; i++) {
for (j; j < x_size; j++) {
if ((file_arr[i][j] >= 5) && (file_arr[i][j] <= 9)) {
res = add_as_last(res, '#', 1);
}
else if ((file_arr[i][j] >= 1) && (file_arr[i][j] <= 4)) {
res = add_as_last(res, '#', 1);
forming_list(file_arr, i, j, body);
} else {
res = add_as_last(res, 'x', 1);
}
}
res = add_as_last(res, '\n', 1);
printf("Length of string = %zu \n",strlen(res));
j = 0;
}
}
int main()
{
int disp[x_size][y_size] = {
{0, 1, 8, 0},
{0, 0, 8, 0},
{0, 9, 6, 0},
{0, 0, 0, 0}
};
char *res;
char *body;
res = (char*)malloc((1) * sizeof(char));
body = (char*)malloc((1) * sizeof(char));
res[0] = '\0';
body[0] = '\0';
printf("Length of string = %zu \n",strlen(res));
print_file(disp, res, body);
printf("Length of string = %zu \n",strlen(res));
printf("%s\n", res);
printf("%s\n", body);
return 0;
}
输出是:
Length of string = 0 //创建res线后
字符串长度 = 5 //第一个外层for循环之后
字符串长度 = 10 //第二个外层for循环之后
字符串长度 = 15 //第三个外层for循环之后
Length of string = 20 //在第四个外部for循环之后,就在退出函数之前
Length of string = 0 //打印“res”字符串之前的函数外
//Printing empty "res" string
2,1 2,2 1,2 0,2 0,1 //打印正确填充的“body”字符串
为什么“body”和“res”的值在我的程序完成工作后却如此不同,尽管如此相似?
【问题讨论】:
-
记住函数参数是按值传递的。也就是说,参数的值被复制到函数参数变量中。修改这个副本当然不会修改原件。想想电话
print_file(disp, res, body)。并做一些关于在C中模拟通过引用传递的研究。 -
我知道按引用传递/按值传递的差异,并且我知道我可以只返回“res”并且它可以正常工作,但我试图理解差异,为什么“body " 正在按预期工作,而 "res" 在内存中丢失了?
-
您的代码中很可能存在某种未定义的行为。尝试缩减您的程序(很多!),将minimal reproducible example 的minimal 部分发挥到极致。确保它有效。然后一次添加一小部分,构建(启用详细的额外警告)和测试。当问题发生时,您可以缩小范围并仅调试小的非工作位。
-
另外请阅读the help pages,采取SO tour,阅读How to Ask,以及this question checklist。您的问题是一堵难以阅读的文字墙。
-
我知道我应该避免问可重复的问题,但我的问题是我不知道如何制定它。如果我更熟悉 C 中的这些恶作剧和术语,我想我就不会费心提出烦人的问题了。
标签: c string pointers scope mutation