我是C的新手,我的代码遇到了一个小问题:
int i, n;
int *arr;
while(n != 0) {
scanf("%d", &n);
if(n == 0)
exit(1);
else {
arr = (int*) malloc(sizeof(int) * n);
for(i = 0; i < n; i++)
scanf("%d", &arr[i]);
} //end if
} //end while
我要做的是制作一个n大小的数组,当我输入'0'时我想停止阅读,例如我输入:
3
2
2
5
2
6
7
0
我想要一个大小为3的数组,其值为2,2,5,数组为2,值为6和7,并且因为0而退出 *对不起,我遗漏了一个重要的部分我认为...在我的代码中调用calc(),我发送arr,在scanf之后(“%d”,&amp; arr [i])然后我将返回值,然后返回下一个值,例如2不是0我将读取,创建一个新数组,在控制台上发送arr,打印结果,如果下一个值为0,它将再次退出。 * 你能告诉我我哪里错了吗?
答案 0 :(得分:3)
你快到了!
您正在arr
中创建新数组,但这是一个单指针,因此只能引用一个内存块。当您调用malloc时,新内存存储在arr
中,但旧内存将丢失。你正在“泄漏内存”,因为机器保留了旧内存,但你没有存储它的地址的变量,所以你无法再找到它。
如果你只需要存储最后一个列表,你应该在malloc新空间之前释放旧内存(在arr中)。如果需要存储所有数组,则需要在arr。
中使用指针数组编辑:
在分配新内存之前,您需要自由调用以释放先前分配的内存。在第一组数据中,您没有任何现有的'malloc',但释放NULL指针总是安全的,因此只需在开始时将指针设置为NULL即可。
提示:在定义变量时,将所有变量设置为某个安全的初始值始终是个好主意。
int *arr=NULL; // Mark this as pointing to no memory
....
free(arr); // first time it does nothing, afterwards it deletes the previous reserved memory
arr = (int*) malloc(sizeof(int) * n); // as before this reserves some memory
答案 1 :(得分:2)
您的代码中可见的问题是:
1.在n
中检查未初始化的整数while
。要解决此问题,请将n
初始化为非零,或使用do{ ... } while()
代替while()
。
2.您需要验证通过n
读取的scanf
的值。 malloc
将size_t
类型作为参数unsigned int
。但是n
是一个整数可以接受负值,因此如果输入负值,它将作为unsigned int
传递给malloc
,这可能会导致意外结果(同时{{1} }循环执行次数不正确)。您也可以考虑将for
的类型从n
更改为integer
类型,或将退出条件更改为unsigned int
。
3.程序中存在内存泄漏。通过if( n < 1 )
分配的内存不会通过malloc
释放
4.不要以为free
将永远成功。请通过malloc
支票检查malloc
是否成功,即
NULL
5。具有非零值的if (NULL == arr)
{
//error handling
}
通常表示异常终止。您可以使用exit
或break
。 return
可能是一个更好的主意,因为通常很难测试函数作为函数中的退出点增加(尽管在您的情况下可能不是这样,但它是FYI)
6.(可选)您可以检查break
的返回值,以确保输入了有效输入。
帮助这有帮助!
答案 2 :(得分:0)
据推测,您希望以后能够访问这些数组。
实际上,当你malloc
下一个数组时,你正在丢失指向前一个数组的指针(当然,如果它是一个更大的应用程序,会导致内存泄漏)。
您需要分配一个int *
(一组int
指针)的chuck,然后将每个int
指针存储在那里。
诀窍是......如果你不知道你需要多少个数组,你需要你的代码是动态的(例如;分配一些空间,如果你用完就分配更多)
另一种选择是,您可以限制用户可以输入的系列数量,并告诉他们在到达时已完成。
如果你想进入后一条路线,这里有一些帮助:
int i;
int n = 1;
int **myArrayOfArrays = malloc(sizeof(int*) * 5); /* max of 5 arrays */
int *arr;
int arrayCount = 0;
while(n != 0) {
scanf("%d", &n);
if(n == 0)
break;
else {
if (arrayCount == 4) {
printf("Woah there partner! That's enough!\n");
break;
}
else
{
arr = malloc(sizeof(int) * n);
for(i = 0; i < n; i++)
scanf("%d", &arr[i]);
myArrayOfArrays[arrayCount] = arr;
arrayCount++;
}
} //end if
} //end while
但是......现在你不知道每个阵列有多长。这是一个问题。您需要跟踪它,或使用动态结构,如链接列表。在下面的示例中,我们将长度添加为每个数组的第一个元素:
int main()
{
int i;
int n = 1;
int **myArrayOfArrays = malloc(sizeof(int*) * 5);
int *arr;
int arrayCount = 0;
while(n != 0) {
scanf("%d", &n);
if(n == 0)
break;
else {
if (arrayCount == 4) {
printf("Woah there partner! That's enough!\n");
break;
}
else
{
arr = malloc(sizeof(int) * (n + 1)); /* one more than we need */
arr[0] = n; /* store the array length in the first element */
for(i = 1; i <= n; i++)
scanf("%d", &arr[i]);
myArrayOfArrays[arrayCount] = arr;
arrayCount++;
}
} //end if
} //end while
int j;
for (i = 0; i < arrayCount; i++)
{
int length = myArrayOfArrays[i][0]; /* retrieve the length */
for (j = 1; j <= length; j++)
printf("%d ", myArrayOfArrays[i][j]);
printf("\n");
}
}
使用数组/原始内存进行动态分配意味着您需要跟踪内容。更好的方法是使用数据链表。在这种情况下,您可以拥有一个链接的节点列表,每个节点都包含一个整数链接列表。
答案 3 :(得分:0)
您没有初始化n
,因此您可能会或可能不会进入while
循环。从-1开始n
将是一件合理的事情:
int i, n = -1;
你应该转换malloc
的返回值,这可以隐藏问题。
你也在泄漏记忆,因为你没有打电话给free
,因为你从malloc
回来了,并且每次分配新值时,你都会忘记你读到的内容arr
。 Brian Roach和Martin Becket已经提到了这些事情。