增加数组大小失败

huangapple go评论65阅读模式
英文:

Increment Array Size Failure

问题

我试图编写一个函数来将素数添加到数组中,但我的 realloc 不断失败。有人可以看看我的代码并告诉我为什么失败吗?

#include <stdio.h>
#include <stdlib.h>

void makePrimes(int *primes, int *primesLength, int primeTarget);
int isPrime(int input);

int main(void)
{
    int *primes = (int *)(malloc(1));
    *primes = 2;
    int primesLength = 1;
    makePrimes(primes, &primesLength, 3);
    printf("%d", *(primes + 2));
    free(primes);
    return 0;
}

//* 找到素数目标数 prime 的素数(例如,2 是第零个素数)
//! PRIME TARGET 从零开始计数,但 PRIMES LENGTH 从 1 开始计数
void makePrimes(int *primes, int *primesLength, int primeTarget)
{
    // 什么都不做
    if (*primesLength >= primeTarget + 1)
        return;

    int lastValue = *(primes + (*primesLength - 1));
    while (primeTarget + 1 != *primesLength)
    {
        lastValue++;
        if (isPrime(lastValue))
        {
            (*primesLength)++;
            primes = realloc(primes, *primesLength * sizeof(int));
            *(primes + (*primesLength - 1));
        }
    }
}

//* 检查给定的整数是否为素数
int isPrime(int input)
{
    if (input == 0 || input == 1)
    {
        return 0;
    }
    int testFactor = 2;
    for (int iii = 0; iii < (input - 2); iii++)
    {
        if ((input % testFactor) == 0)
            return 0;
        testFactor++;
    }
    return 1;
}

我期望它会向数组 'primes' 添加一个可用元素。使用调试器,我发现 'primes' 被设置为 NULL,因此未执行后面的行。谢谢。

英文:

I was trying to write a function to add primes to a array but my realloc kept failing. Can someone please look at my code and tell me why it is failing?

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

void makePrimes(int *primes, int *primesLength, int primeTarget);
int isPrime(int input);

int main(void)
{
    int *primes = (int *)(malloc(1));
    *primes = 2;
    int primesLength = 1;
    makePrimes(primes, &amp;primesLength, 3);
    printf(&quot;%d&quot;, *(primes + 2));
    free(primes);
    return 0;
}

//* Finds the prime number that is the prime target number prime
//* (i.e 2 is the zeroth prime)
//! PRIME TARGET COUNTS FROM ZERO BUT  PRIMES LENGTH COUNTS FROM 1
void makePrimes(int *primes, int *primesLength, int primeTarget)
{
    // do nothing
    if (*primesLength &gt;= primeTarget + 1)
        return;

    int lastValue = *(primes + (*primesLength - 1));
    while (primeTarget + 1 != *primesLength)
    {
        lastValue++;
        if (isPrime(lastValue))
        {
            (*primesLength)++;
            primes = realloc(primes, *primesLength * sizeof(int));
            *(primes + (*primesLength - 1));
        }
    }
}

//* Checks if a given integer is prime
int isPrime(int input)
{
    if (input == 0 || input == 1)
    {
        return 0;
    }
    int testFactor = 2;
    for (int iii = 0; iii &lt; (input - 2); iii++)
    {
        if ((input % testFactor) == 0)
            return 0;
        testFactor++;
    }
    return 1;
}

I was expecting it to add one more available element to the array 'primes'. Using a debugger I found that primes was being set to NULL and not running the following line. Thanks.

答案1

得分: 3

  1. 你最初使用 malloc() 分配了1个字节,而不是 sizeof(int) == sizeof *primes,在我的系统上是 4

  2. 更喜欢使用变量的 sizeof 而不是类型。这意味着你不必重复类型,这使得代码在未来(类型)更改时更加健壮。

  3. 不要对来自 malloc()void * 进行强制类型转换。

  4. 由于你想要更改 primes(使用 realloc()),所以需要将 &primes 传递给 makePrimes()

  5. 对于 realloc() 的返回值,使用临时变量(tmp)来存储,否则在失败时会发生内存泄漏。

  6. 检查 malloc()realloc() 的返回值。

  7. 将找到的值赋给 primes

  8. (未修复)坚持使用指针而不是数组表示,会使工作变得更加困难。

  9. (未修复)考虑使用无符号类型。这可以消除错误类别。例如,如果 primeTarget 是负数,期望的输出是什么?如果传入负的素数会怎样?

  10. isPrime() 可以优化为只检查 testFactor <= input / testFactor

  11. (未修复)考虑重新设计接口,使得 makePrimes() 填充第一个值,而不是依赖调用者放入 *primes*primesLength 的正确魔术值。

  12. (未修复)由于你指定了要多少个素数,可以预先分配 primes 数组,而不是逐个增加数组成员。

  13. 我创建了一个 printPrimes() 函数,用于[调试;如果你只想要最后一个,为什么要将其余的存储在数组中?

#include <stdio.h>
#include <stdlib.h>

int isPrime(int input) {
    if (input == 0 || input == 1)
        return 0;
    for (int testFactor = 2; testFactor <= input / testFactor; testFactor++) {
        if (!(input % testFactor))
            return 0;
    }
    return 1;
}

void makePrimes(int **primes, int *primesLength, int primeTarget) {
    if (*primesLength < 1)
        return;
    int lastValue = *(*primes + (*primesLength - 1));
    while (*primesLength < primeTarget) {
        lastValue++;
        if (isPrime(lastValue)) {
            int *tmp = realloc(*primes, sizeof *tmp * (*primesLength + 1));
            if (!tmp) {
                printf("realloc failed\n");
                return;
            }
            *primes = tmp;
            *((*primes) + *primesLength) = lastValue;
            (*primesLength)++;
        }
    }
}

void printPrimes(int n, int primes[n]) {
    if (n <= 0)
        return;
    printf("%d", *primes);
    for (int i = 1; i < n; i++)
        printf(", %d", *(primes + i));
    printf("\n");
}

int main(void) {
    int *primes = malloc(sizeof *primes);
    if (!primes) {
        printf("malloc failed\n");
        return 1;
    }
    *primes = 2;
    int primesLength = 1;
    makePrimes(&primes, &primesLength, 3);
    printPrimes(primesLength, primes);
    free(primes);
    return 0;
}

示例运行:

2, 3, 5
英文:
  1. You initially malloc() 1 byte instead of sizeof(int) == sizeof *primes which is 4 on my system.
  2. Prefer sizeof variable instead of type. This means you don't have to repeat the type which makes the code less brittle in the face of future (type) changes.
  3. Don't cast the void * from malloc().
  4. As you want to change primes (with realloc()) you need to pass in &amp;primes to makePrimes().
  5. Use a temporary variable (tmp) for the return value of realloc() otherwise you leak memory on failure.
  6. Check return value from malloc() and realloc().
  7. Assign the value you found to primes.
  8. (Not fixed) You are making it harder for yourself by insisting on using pointer instead of array notation.
  9. (Not fixed) Consider using unsigned types. This eliminates error classes. For instance what if primeTarget is negative what is the expected output? What if a negative prime number is passed in?
  10. isPrime() can be optimized to only look at testFactor &lt;= input / testFactor.
  11. (Not fixed) Consider reworking the interface so makePrimes() fills in the first value, too, instead of relying on caller to put in the right magic values for *primes and *primesLenght.
  12. (Not fixed) As you specify how many primes you want, you could just pre-allocate the primes array instead of growing the array member at a time.
  13. I made a printPrimes() function which is better for[debugging; you use your original code is just want the last one. If you just want the last prime why bother storing the rest in an array?
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
int isPrime(int input) {
if (input == 0 || input == 1)
return 0;
for (int testFactor = 2; testFactor &lt;= input / testFactor; testFactor++) {
if (!(input % testFactor))
return 0;
}
return 1;
}
void makePrimes(int **primes, int *primesLength, int primeTarget) {
if(*primesLength &lt; 1)
return;
int lastValue = *(*primes + (*primesLength - 1));
while (*primesLength &lt; primeTarget) {
lastValue++;
if (isPrime(lastValue)) {
int *tmp = realloc(*primes, sizeof *tmp * (*primesLength + 1));
if(!tmp) {
printf(&quot;realloc failed\n&quot;);
return;
}
*primes = tmp;
*((*primes) + *primesLength) = lastValue;
(*primesLength)++;
}
}
}
void printPrimes(int n, int primes[n]) {
if(n &lt;= 0) return;
printf(&quot;%d&quot;, *primes);
for(int i = 1; i &lt; n; i++)
printf(&quot;, %d&quot;, *(primes+i));
printf(&quot;\n&quot;);
}
int main(void) {
int *primes = malloc(sizeof *primes);
if(!primes) {
printf(&quot;malloc failed\n&quot;);
return 1;
}
*primes = 2;
int primesLength = 1;
makePrimes(&amp;primes, &amp;primesLength, 3);
printPrimes(primesLength, primes);
free(primes);
return 0;
}

example run:

2, 3, 5

答案2

得分: -1

在注释中(位于//后面)说明了为什么添加或更改了以下内容<br>
更新:使makePrimes'的返回值类似于realloc()

--- orig0.c
+++ orig1.c
@@ -1,16 +1,23 @@
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
+#include &lt;err.h&gt;

-void makePrimes(int *primes, int *primesLength, int primeTarget);
+int* makePrimes(int *primes, int *primesLength, int primeTarget);
int isPrime(int input);

int main(void)
{
-    int *primes = (int *)(malloc(1));
+    int *primes = (int *)(malloc(sizeof(int))); // 分配适当的大小
+    if (!primes) // 检查malloc分配的结果
+        err(-1, "malloc");
    *primes = 2;
    int primesLength = 1;
-    makePrimes(primes, &primesLength, 3);
-    printf("%d", *(primes + 2));
+    primes = makePrimes(primes, &primesLength, 10);
+    if (primes) { // 打印它们所有
+        for (int i = 0; i < primesLength; i++)
+            printf("%d ", primes[i]);
+        printf("\n");
+    }
    free(primes);
    return 0;
}
@@ -18,11 +25,11 @@
//* 查找是素数目标数的素数(即2是零号素数)
//! PRIME TARGET COUNTS FROM ZERO BUT PRIMES LENGTH COUNTS FROM 1
-void makePrimes(int *primes, int *primesLength, int primeTarget)
+int* makePrimes(int *primes, int *primesLength, int primeTarget) // 返回指针,类似于realloc()
{
    // 什么也不做
    if (*primesLength >= primeTarget + 1)
-        return;
+        return primes;

    int lastValue = *(primes + (*primesLength - 1));
    while (primeTarget + 1 != *primesLength)
@@ -30,11 +37,17 @@
        lastValue++;
        if (isPrime(lastValue))
        {
+            int *reallocated = realloc(primes, (*primesLength + 1) * sizeof(int));
+            if (!reallocated) { // 检查realloc的结果
+                warn("realloc");
+                break;
+            }
+            primes = reallocated;
+            *(primes + *primesLength) = lastValue; // 忘记赋值
            (*primesLength)++;
-            primes = realloc(primes, *primesLength * sizeof(int));
-            *(primes + (*primesLength - 1));
        }
    }
+    return primes;
}

//* 检查给定整数是否为素数
英文:

in comments (text after //) there's why it was added or changed<br>
upd: makePrimes' retvalue like realloc()

--- orig0.c
+++ orig1.c
@@ -1,16 +1,23 @@
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
+#include &lt;err.h&gt;
-void makePrimes(int *primes, int *primesLength, int primeTarget);
+int* makePrimes(int *primes, int *primesLength, int primeTarget);
int isPrime(int input);
int main(void)
{
-    int *primes = (int *)(malloc(1));
+    int *primes = (int *)(malloc(sizeof(int))); // allocate proper size
+    if (!primes) // test a result of malloc allocation
+        err(-1, &quot;malloc&quot;);
*primes = 2;
int primesLength = 1;
-    makePrimes(primes, &amp;primesLength, 3);
-    printf(&quot;%d&quot;, *(primes + 2));
+    primes = makePrimes(primes, &amp;primesLength, 10);
+    if (primes) { // print all of them
+        for (int i = 0; i &lt; primesLength; i++)
+            printf(&quot;%d &quot;, primes[i]);
+        printf(&quot;\n&quot;);
+    }
free(primes);
return 0;
}
@@ -18,11 +25,11 @@
//* Finds the prime number that is the prime target number prime
//* (i.e 2 is the zeroth prime)
//! PRIME TARGET COUNTS FROM ZERO BUT  PRIMES LENGTH COUNTS FROM 1
-void makePrimes(int *primes, int *primesLength, int primeTarget)
+int* makePrimes(int *primes, int *primesLength, int primeTarget) // return pointer like realloc()
{
// do nothing
if (*primesLength &gt;= primeTarget + 1)
-        return;
+        return primes;
int lastValue = *(primes + (*primesLength - 1));
while (primeTarget + 1 != *primesLength)
@@ -30,11 +37,17 @@
lastValue++;
if (isPrime(lastValue))
{
+            int *reallocated = realloc(primes, (*primesLength + 1) * sizeof(int));
+            if (!reallocated) { // test a result of realloc()
+                warn(&quot;realloc&quot;);
+                break;
+            }
+            primes = reallocated;
+            *(primes + *primesLength) = lastValue; // forgotten assignment
(*primesLength)++;
-            primes = realloc(primes, *primesLength * sizeof(int));
-            *(primes + (*primesLength - 1));
}
}
+    return primes;
}
//* Checks if a given integer is prime

huangapple
  • 本文由 发表于 2023年6月26日 11:50:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/76553416.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定