【问题标题】:problems with data entry and malloc in CC中的数据输入和malloc问题
【发布时间】:2011-09-15 04:37:53
【问题描述】:

我是 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 而退出 * 对不起,我遗漏了我认为的一个重要部分......在我的代码中,我在 scanf("%d",&arr[i]) 之后调用了一个 calc()返回值,然后返回下一个值,例如2 不是 0 我将读取,创建一个新数组,发送 arr,在控制台上打印结果,如果下一个值为 0,那么它将退出。 * 你们能告诉我哪里错了吗?

【问题讨论】:

  • 解释你提交的代码是如何失败的。输入例子中的序列不退出吗?
  • 使用break 语句代替exit。这保证在while 循环之后执行任何其他代码。

标签: c arrays malloc exit


【解决方案1】:

你快到了!

您正在arr 中创建新数组,但这是一个单指针,因此只能引用一个内存块。当您调用 malloc 时,新内存存储在 arr 中,但旧内存会丢失。您正在“泄漏内存”,因为机器保留了旧内存,但您没有存储其地址的变量,因此您无法再次找到它。

如果您只需要存储最后一个列表,您应该在分配新空间之前释放旧内存(在 arr 中)。如果需要存储所有数组,则需要在 arr 中创建一个指针数组。

编辑:
在分配新内存之前,您需要调用 free 以“释放”先前分配的内存。在第一组数据中,您没有任何现有的“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

【讨论】:

  • 我认为没关系,因为当我得到一个数组时,我可以调用一个我没有在那里添加的方法,然后在控制台上打印该值。如果 neXt 值不为 0,那么我将再次调用该方法。所以我认为我不需要一次记住所有数组......在这种情况下......我需要释放(arr)???
【解决方案2】:

您的代码中可见的问题是:
1.检查while中未初始化的整数n。要解决此问题,请将n 初始化为非零或使用do{ ... } while() 而不是while()
2. 您需要验证通过scanf 读取的n 的值。 mallocsize_t 类型为参数,即unsigned int。但是n是一个整数可以接受负值,因此如果输入一个负值,它将作为unsigned int传递给malloc,这可能会导致不希望的结果(另外for循环将执行不正确的次数次)。您也可以考虑将n的类型从integer更改为unsigned int类型或将退出条件更改为if( n &lt; 1 )
3.你的程序有内存泄漏。通过malloc 分配的内存不会通过free 释放。
4. 不要以为malloc 会永远成功。请通过NULL 检查malloc 是否成功,即

if (NULL == arr)
{
   //error handling
}

5。 exit 非零值一般表示异常终止。您可以使用breakreturnbreak 可能是一个更好的主意,因为随着函数中的退出点增加,通常很难测试函数(尽管在您的情况下这可能不是真的,但仅供参考)
6. 或者,您可以检查scanf 的返回值以确保输入了有效的输入。

帮帮忙!

【讨论】:

  • 感谢这对我理解编程有很大帮​​助! :)
【解决方案3】:

您没有初始化n,因此您可能会也可能不会进入while 循环。从 -1 开始 n 是合理的做法:

int i, n = -1;

并且你应该转换malloc的返回值,这样可以隐藏问题。

您还泄漏了内存,因为您没有在从malloc 返回时调用free,并且每次为arr 分配新值时,您都会忘记读取的内容。不过,Brian Roach 和 Martin Becket 已经提到了这些事情。

【讨论】:

    【解决方案4】:

    大概您希望以后能够访问这些数组。

    事实上,当您 malloc 下一个数组时,您会丢失指向前一个数组的指针(当然,如果它是一个更大的应用程序,则会导致内存泄漏)。

    您需要分配一个 int *(一组 int 指针),然后将每个 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");
        }
    }
    

    使用数组/原始内存进行动态分配意味着您需要跟踪内容。更好的方法实际上是为您的数据使用链表。在这种情况下,您可以有一个节点链表,每个节点都包含一个整数链表。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-17
      • 2018-07-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多