英文:
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 <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;
}
//* 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 >= 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 < (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
-
你最初使用
malloc()
分配了1个字节,而不是sizeof(int) == sizeof *primes
,在我的系统上是4
。 -
更喜欢使用变量的
sizeof
而不是类型。这意味着你不必重复类型,这使得代码在未来(类型)更改时更加健壮。 -
不要对来自
malloc()
的void *
进行强制类型转换。 -
由于你想要更改
primes
(使用realloc()
),所以需要将&primes
传递给makePrimes()
。 -
对于
realloc()
的返回值,使用临时变量(tmp
)来存储,否则在失败时会发生内存泄漏。 -
检查
malloc()
和realloc()
的返回值。 -
将找到的值赋给
primes
。 -
(未修复)坚持使用指针而不是数组表示,会使工作变得更加困难。
-
(未修复)考虑使用无符号类型。这可以消除错误类别。例如,如果
primeTarget
是负数,期望的输出是什么?如果传入负的素数会怎样? -
isPrime()
可以优化为只检查testFactor <= input / testFactor
。 -
(未修复)考虑重新设计接口,使得
makePrimes()
填充第一个值,而不是依赖调用者放入*primes
和*primesLength
的正确魔术值。 -
(未修复)由于你指定了要多少个素数,可以预先分配
primes
数组,而不是逐个增加数组成员。 -
我创建了一个
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
英文:
- You initially
malloc()
1 byte instead ofsizeof(int) == sizeof *primes
which is4
on my system. - 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. - Don't cast the
void *
frommalloc()
. - As you want to change
primes
(withrealloc()
) you need to pass in&primes
tomakePrimes()
. - Use a temporary variable (
tmp
) for the return value ofrealloc()
otherwise you leak memory on failure. - Check return value from
malloc()
andrealloc()
. - Assign the value you found to
primes
. - (Not fixed) You are making it harder for yourself by insisting on using pointer instead of array notation.
- (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? isPrime()
can be optimized to only look attestFactor <= input / testFactor
.- (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
. - (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. - 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 <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;
}
example run:
2, 3, 5
答案2
得分: -1
在注释中(位于//
后面)说明了为什么添加或更改了以下内容<br>
更新:使makePrimes'
的返回值类似于realloc()
--- orig0.c
+++ orig1.c
@@ -1,16 +1,23 @@
#include <stdio.h>
#include <stdlib.h>
+#include <err.h>
-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 <stdio.h>
#include <stdlib.h>
+#include <err.h>
-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, "malloc");
*primes = 2;
int primesLength = 1;
- makePrimes(primes, &primesLength, 3);
- printf("%d", *(primes + 2));
+ primes = makePrimes(primes, &primesLength, 10);
+ if (primes) { // print all of them
+ for (int i = 0; i < primesLength; i++)
+ printf("%d ", primes[i]);
+ printf("\n");
+ }
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 >= 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("realloc");
+ 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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论