我花了几个小时试图调试我的代码,但我没有这样做。我认为问题在于我没有完全理解动态内存分配,但我也可能犯了其他一些错误。这里的问题更多的是一个个人问题,如果有人发现这个问题没有实现,我很抱歉,#34;让它与他人相关"。
我已获得下一个分配:
从区间0-100中的A[]
个随机元素中创建一个数组n
。创建一个拆分两个数组的函数,例如:array B[]
包含元素> 50
,而C[]
包含其余元素。使用动态内存分配创建阵列A和B.函数的参数必须是所有三个数组及其各自的长度。
#include <stdio.h>
#include <stdlib.h>
void Array(int *A, int *nA, int *B, int *nB, int *C, int*nC){
int i;
int nB1 = 0;
int nC1 = 0;
int *tmpB;
int *tmpC;
B = malloc((nB1+1)*sizeof(int));
C = malloc((nC1+1)*sizeof(int));
printf("\n");
for(i = 0 ; i < nA ; i++){
if(A[i] <= 50){
C[i] = A[i];
nC1++;
// The idea here is to have a new array with basically
// no length so that each time one element passes to either
// B or A array that array gets increased at the same
// time as nC or nB
tmpC = realloc(C, sizeof(int) * nC1);
if(tmpC == NULL){
printf("ERROR: realloc failed.\n");
}
C = tmpC;
// C = realloc(C, nC1 + 1);
}
else{
B[i] = A[i];
nB1++;
tmpB = realloc(B, sizeof(int) * nB1);
if(tmpB == NULL){
printf("ERROR: realloc failed.\n");
}
B = tmpB;
// B = realloc(B, nB1 + 1);
}
}
printf("\n");
printf("Array B: ");
nB = nB1;
for(i = 0 ; i < nB ; i++){
printf("%d ", B[i]);
}
printf("\n");
printf("Number of elements in array B: %d\n", nB);
printf("\n");
printf("Array C: ");
nC = nC1;
for(i = 0 ; i < nC ; i++){
printf("%d ", C[i]);
}
printf("\n");
printf("Number of elements in array C: %d\n", nC);
}
void main(){
int *A;
int *B;
int *C;
int nA, nB, nC, i, r, j;
nB = 0;
nC = 0;
printf("Enter the length of array A: ");
scanf("%d", &nA);
printf("\n");
A = malloc(nA * sizeof(int));
if (A == NULL){
printf("ERROR: malloc failed.\n");
return 1;
}
time_t t;
srand((unsigned)time(&t));
printf("Array A: ");
for(i = 0 ; i < nA ; i++){
r = rand() % 101;
A[i] = r;
printf("%d ", r);
}
printf("\n");
Array(A, nA, B, nB, C, nC);
}
到目前为止,我的代码在以下时间打破:
来自nA
的用户输入高于6
代码工作正常,而数组A
包含所有可以放在一个数组中的元素,例如B
或C
。但是,如果元素可以拆分,则数组A
的最后一个元素在B
或C
数组中时无法在屏幕上正确显示。
编辑:更新了代码,以便更容易跟踪我的错误。
#include <stdio.h>
#include <stdlib.h>
void Array(int *A, int nA, int *B, int nB, int *C, int nC){
int i;
int nB1 = 0;
int nC1 = 0;
int *tmpB;
int *tmpC;
B = malloc(1*sizeof(int));
if(B == NULL){
printf("ERROR: malloc B failed.\n");
return 1;
}
C = malloc(1*sizeof(int));
if(C == NULL){
printf("ERROR: malloc C failed.\n");
return 1;
}
printf("\n");
for(i = 0 ; i < nA ; i++){
if(A[i] <= 50){
// C[nC1] = A[i];
// nC1++;
// if( nC1 > 1){
// tmpC = realloc(C, sizeof(int) * nC1);
// if(tmpC == NULL){
// printf("ERROR: realloc C failed.\n");
// return 1;
// }
// C = tmpC;
// }
tmpC = realloc(C, sizeof(int) * nC1);
if(tmpC == NULL){
printf("ERROR: realloc C failed.\n");
return 1;
}
C = tmpC;
C[nC1++] = A[i];
// nC1++;
}
else{
// B[nB1] = A[i];
// nB1++;
// if(nB1 > 1){
// tmpB = realloc(B, sizeof(int) * nB1);
// if(tmpB == NULL){
// printf("ERROR: realloc B failed.\n");
// return 1;
// }
// B = tmpB;
// }
tmpB = realloc(B, sizeof(int) * nB1);
if(tmpB == NULL){
printf("ERROR: realloc B failed.\n");
return 1;
}
B = tmpB;
B[nB1++] = A[i];
// nB1++;
}
}
printf("\n");
printf("Array B: ");
nB = nB1;
for(i = 0 ; i < nB ; i++){
printf("%d ", B[i]);
}
printf("\n");
printf("Number of elements in array B: %d\n", nB);
printf("\n");
printf("Array C: ");
nC = nC1;
for(i = 0 ; i < nC ; i++){
printf("%d ", C[i]);
}
printf("\n");
printf("Number of elements in array C: %d\n", nC);
}
int main(){
int *A;
int *B;
int *C;
int nA, nB, nC, i, r;
printf("Enter the length of array A: ");
scanf("%d", &nA);
printf("\n");
A = malloc(nA * sizeof(int));
if (A == NULL){
printf("ERROR: malloc A failed.\n");
return 1;
}
time_t t;
srand((unsigned)time(&t));
printf("Array A: ");
for(i = 0 ; i < nA ; i++){
r = rand() % 101;
A[i] = r;
printf("%d ", r);
}
printf("\n");
Array(A, nA, B, nB, C, nC);
return 0;
}
答案 0 :(得分:0)
您的情况中的逻辑错误B[i] = A[i];
应为B[nB1] = A[i];
。与C
数组相同的事情应该是C[nC1] = A[i]
(这两个都在循环中)。
另外,来自KillaBytes字节分析。是的,你应该在添加新值之前重新分配。可能是你的程序最终崩溃的原因:
else { nB1++; // since you started at size 0 tmpB = realloc(B, sizeof(int) * nB1); //realloc to 0 = (sizeof(int) * 0) is bad if(tmpB == NULL){ printf("ERROR: realloc failed.\n"); } B = tmpB; B[nB1 - 1] = A[i];///*****KEY POINT, This happens at the very end*** }
尽管如此,还有许多其他问题,但核心逻辑却没有。特别是对指针的理解。我会尝试列出一些你需要考虑的事项:
Array
函数没有任何内容(除了打印输出),原始B
和C
保持不变。A
,B
(在函数中),C
(在函数中)最后没有释放。这个想法是,对于每个malloc / calloc(realloc在成功时都会释放),你必须在指针上调用free以避免任何内存泄漏 :)只是一个微不足道的点,但非常好的习惯。 if(tmpC == NULL){ printf("ERROR: realloc failed.\n"); }
应该是
if(tmpC == NULL){ free(C);//unnecessary because the program is going to exit // I would argue to get used to this, to force the habit // to alway free all mallocs printf("ERROR: realloc failed.\n"); exit(-1);// -1 is a generic value, error code that is checked // if the caller cares to look (you can make it any int) }
B
和C
Array()
之外的值,有几种方法,我将以单向演示。void Array(int *A, int nA, int **B, int *nB, int **C, int *nC){ // funciton signature
如果您在此功能中使用B
,nB
,C
,nC
,请使用*B
,*nB
,{{1 },*C
。例如:
*B = malloc((*nB1+1)*sizeof(int)); *C = malloc((*nC1+1)*sizeof(int));
来自*nC
的函数调用应为:
main
答案 1 :(得分:0)
我猜我会试着抓住这个。我发现您的代码存在一些值得注意的问题,可以通过对您的实现进行一些结构性更改来解决。一些较小的:
void main() {
// Code above here left out.
A = malloc(nA * sizeof(int));
if (A == NULL){
printf("ERROR: malloc failed.\n");
return 1; // Might be a problem here.
}
当没有足够的内存分配给A
时,在main中返回一个整数。这可能会导致某些编译器出现问题 - 或者如果您一般不喜欢警告,从void main
到int main
的简单修复就会清除这一点。
第二,你的职能Array
中有
void Array(int *A, int *nA, int *B, int *nB, int *C, int *nC)
但是,您开始使用nA nB
和nC
仅使用int
而不是int *
,这是类型不匹配的问题。你可以改为
void Array(int *A, int nA, int *B, int nB, int *C, int nC)
最后也是最重要的是,通过使用未初始化的ints
为传入的数组创建内存,会遇到堆错误:
int nB1;
int nC1;
B = malloc((nB1 + 1)*sizeof(int));
C = malloc((nC1 + 1)*sizeof(int));
最好只在不使用int
和nB1
的情况下向数组中添加一个nC1
。
B = malloc(1*sizeof(int));
C = malloc(1*sizeof(int));
首先应该检查B
和C
是否为空数组,然后根据需要为它们添加内存。
if (A[i] <= 50){
C[i] = A[i];
nC1++;
// The idea here is to have a new array with basically
// no length so that each time one element passes to either
// B or A array that array gets increased at the same
// time as nC or nB
tmpC = realloc(C, sizeof(int) * nC1);
if (tmpC == NULL){
printf("ERROR: realloc failed.\n");
}
C = tmpC;
}
tmpC
是realloc&#39;但C
永远不会获得更多空间,因此在分配值C[i] = A[i]
时会崩溃。您需要扩展维护数组C
和B
。
修改强>
忽略有关重新分配的评论,您的realloc
操作没问题。
遍历数组A
中的每个元素,如果值小于或等于50,则插入数组C
,否则B
。但是,您可能有一些元素满足第一个条件,但可以满足下一个条件。然后按照B[i] = A[i]
进行分配,但如上所述,您位于A
中的元素3,但是您在B
中的元素1处插入,因此使用i
迭代两者都不是正确。按照 SGM1 的建议,使用nB1
和nC1
以及 ryyker 读取每个数组,以获取有关重新分配的评论。< / p>
我每次都能编译并运行它,但是现在你必须处理实际分配值:
for (i = 0; i < nA; i++){
if (A[i] <= 50){
C[nC1] = A[i];
nC1++;
tmpC = (int *)realloc(C, sizeof(int) * nC1);
if (tmpC == NULL){
printf("ERROR: realloc failed.\n");
}
C = tmpC;
// C = realloc(C, nC1 + 1);
}
答案 2 :(得分:-1)
有一些错误。编译器标记了很多错误/警告(即始终使用-Wall
进行编译)
在Array
原型中,nA
被定义为*nA
[指针],但您在整个身体中使用了nA
。
*nB
和*nC
是正确的,但在您需要的底部附近:
*nB = nB1;
*nC = nC1;
所有阵列都有很多复制代码。每个数组都有一个自定义循环来打印它。为简化起见,创建一个“打印数组”功能。
B
和C
的重新分配是相似的,因此,再次创建一个共同的功能。
除了Array
创建B
和C
之外的其他错误,它无法将更新的值传递回main
。因此,在原型中,我们需要int **Bp
和int **Cp
。
总之,Array
有两个输入值和四个返回值。
这是更正后的代码[请原谅无偿风格的清理]:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// prtarray -- print an array
void
prtarray(int *arr,int count,const char *sym)
{
printf("\n");
printf("Array %s:",sym);
for (int i = 0; i < count; i++)
printf(" %d ", arr[i]);
printf("\n");
printf("Number of elements in array %s: %d\n",sym,count);
}
// growarray -- grow array
int *
growarray(int *arr,int *pcount,int val)
{
int off;
off = *pcount;
arr = realloc(arr,sizeof(int) * (off + 1));
arr[off] = val;
*pcount = off + 1;
return arr;
}
// BUGFIX: we need "int nA" and _not_ "int *nA"
#if 0
void
Array(int *A, int *nA, int *B, int *nB, int *C, int *nC)
#else
void
Array(int *A, int nA, int **Bp, int *nB, int **Cp, int *nC)
#endif
{
#if 1
int *B = NULL;
int *C = NULL;
#endif
int i;
printf("\n");
for (i = 0; i < nA; i++) {
if (A[i] <= 50)
C = growarray(C,nC,A[i]);
else
B = growarray(B,nB,A[i]);
}
*Bp = B;
*Cp = C;
}
int
main()
{
int *A;
int *B;
int *C;
int nA;
int nB;
int nC;
nB = 0;
nC = 0;
printf("Enter the length of array A: ");
scanf("%d", &nA);
printf("\n");
A = malloc(nA * sizeof(int));
if (A == NULL) {
printf("ERROR: malloc failed.\n");
return 1;
}
time_t t;
srand((unsigned) time(&t));
for (int i = 0; i < nA; i++)
A[i] = rand() % 101;
prtarray(A,nA,"A");
#if 0
Array(A, nA, B, nB, C, nC);
#else
Array(A, nA, &B, &nB, &C, &nC);
#endif
prtarray(B,nB,"B");
prtarray(C,nC,"C");
return 0;
}
但是,动态数组“呐喊”使用struct
来控制事物。代码变得更简单:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// array control
struct array {
int *arr_data; // data
int arr_count; // array count
const char *arr_sym; // array name
};
// arrinit -- initialize array
void
arrinit(struct array *arr,const char *sym)
{
arr->arr_data = NULL;
arr->arr_count = 0;
arr->arr_sym = sym;
}
// arrprint -- print an array
void
arrprint(struct array *arr)
{
printf("\n");
printf("Array %s:",arr->arr_sym);
for (int i = 0; i < arr->arr_count; i++)
printf(" %d ", arr->arr_data[i]);
printf("\n");
printf("Number of elements in array %s: %d\n",arr->arr_sym,arr->arr_count);
}
// arrgrow -- grow array
void
arrgrow(struct array *arr,int val)
{
int off;
off = arr->arr_count;
arr->arr_data = realloc(arr->arr_data,sizeof(int) * (off + 1));
arr->arr_data[off] = val;
arr->arr_count = off + 1;
}
// BUGFIX: we need "int nA" and _not_ "int *nA"
void
Array(struct array *A, struct array *B, struct array *C)
{
int i;
int val;
printf("\n");
for (i = 0; i < A->arr_count; i++) {
val = A->arr_data[i];
if (val <= 50)
arrgrow(C,val);
else
arrgrow(B,val);
}
}
int
main()
{
struct array A;
struct array B;
struct array C;
int nA;
arrinit(&A,"A");
arrinit(&B,"B");
arrinit(&C,"C");
printf("Enter the length of array A: ");
scanf("%d", &nA);
printf("\n");
time_t t;
srand((unsigned) time(&t));
for (int i = 0; i < nA; i++)
arrgrow(&A,rand() % 101);
arrprint(&A);
Array(&A, &B, &C);
arrprint(&B);
arrprint(&C);
return 0;
}
<强>更新强>
这是realloc
在上面使用的干净包装。
// qrealloc -- reallocate with null check
void *
qrealloc(void *ptr,size_t len)
{
#if 1
// what is normally sufficient
ptr = realloc(ptr,len);
if (ptr == NULL) {
fprintf(stderr,"qrealloc: realloc failure -- len=%lu\n",len);
exit(1);
}
#else
// what valgrind needs
void *tmp = realloc(ptr,len);
if (tmp == NULL) {
free(ptr);
fprintf(stderr,"qrealloc: realloc failure -- ptr=%p len=%lu\n",ptr,len);
exit(1);
}
ptr = tmp;
#endif
return ptr;
}