C中数据输入和malloc的问题

时间:2011-09-15 04:37:54

标签: c arrays malloc exit

我是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,它将再次退出。 * 你能告诉我我哪里错了吗?

4 个答案:

答案 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的值。 mallocsize_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 } 通常表示异常终止。您可以使用exitbreakreturn可能是一个更好的主意,因为通常很难测试函数作为函数中的退出点增加(尽管在您的情况下可能不是这样,但它是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已经提到了这些事情。