I'm doing my homework but there is some bugs I cannot fix Could you please help me? The question is using Dynamic memory allocation in C Find the some location of smallest negative element
The Function amnn is the "thing" I cannot fix
Thank u so much
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int nhapmang (int *p,int n)
{
int i;
for (i=0;i<n;i++)
{
printf ("Nhap vao a[%d] = ",i);
scanf ("%d",&*(p+i));
}
}
int inmang (int *p,int n)
{
for (int i=0;i<n;i++)
printf (" %d",*(p+i));
}
int amnn(int *p, int n)
{
int tg,tg1;
for (int i=0;i<n;i++)
{
if (*(p+i)<0)
{
tg=*(p+i);
break;
}
}
for (int i=0;i<n;i++)
{
if (*(p+i)<0 && (tg>*(p+i)))
{
tg1=i;
}
}
printf ("\nvi tri so am nho nhat trong mang la: a[%d]",tg1);
}
int main()
{
int *p, n,a,amnn1;
printf ("nhap vao n: ");
scanf ("%d",&n);
p=(int*)malloc(n*sizeof(int));
nhapmang (p,n);
printf ("\nin ma tran:");
inmang(p,n);
amnn(p,n);
return 0;
}
Input: n=5, a[0]=-9, a[1]=5, a[2]=-2, a[3]=-99, a[4]=-99 The result is a[3], a[4]
Unfortunately, I didn't understand the logic of your amnn
.
It appears to only handle the case where there is one minimum value, so it would not handle your sample input.
I had to completely refactor your code. It is annotated:
#include <stdio.h>
#include <stdlib.h>
// amnn -- find all minimum negative numbers
void
amnn(int *arr,int n)
{
// number of indexes that contain the minimum value
int mincount = 0;
// list of indexes that contain the minimum value
#if ALLOC
int *idxlist = malloc(sizeof(*idxlist) * n);
#else
int idxlist[n];
#endif
// current minimum value
// start with a positive value to handle initial case
int minval = 1;
// loop through all array elements
for (int curidx = 0; curidx < n; ++curidx) {
int curval = arr[curidx];
// we only want negative values
if (curval >= 0)
continue;
// ignore values that are greater than the current minimum
if (curval > minval)
continue;
// we have a new minimum value
if (curval < minval) {
// reset count of matching indexes
mincount = 0;
// set new minimum value
minval = curval;
}
// current value is part of the set of minimum values
if (curval == minval)
idxlist[mincount++] = curidx;
}
// print results
do {
if (minval >= 0) {
printf("no negative values found\n");
break;
}
printf("minimum value is: %d\n",minval);
printf("it is contained in indexes:\n");
for (int listidx = 0; listidx < mincount; ++listidx)
printf(" %d\n",idxlist[listidx]);
} while (0);
#if ALLOC
free(idxlist);
#endif
}
UPDATE:
why must reset
mincount = 0
? – Đinh Trọng Đạt
Perhaps, the better question to ask is:
What happens if we do not reset mincount = 0
?
With the following sequence we would still get the correct answer (but only by luck):
-7 -6
However, if we have a list where the absolute/true minimum comes after a local/false minimum, without the reset, this will fail:
-6 -7
It will record/remember -6
. When it sees -7
, it will not remove -6
from the list.
Here is the code modified to test this assertion:
#include <stdio.h>
#include <stdlib.h>
int noreset; // 1=do _not_ reset count (testing)
// amnn -- find all minimum negative numbers
void
amnn(int *arr,int n)
{
// number of indexes that contain the minimum value
int mincount = 0;
// list of indexes that contain the minimum value
#if ALLOC
int *idxlist = malloc(sizeof(*idxlist) * n);
#else
int idxlist[n];
#endif
// current minimum value
// start with a positive value to handle initial case
int minval = 1;
// loop through all array elements
for (int curidx = 0; curidx < n; ++curidx) {
int curval = arr[curidx];
// we only want negative values
if (curval >= 0)
continue;
// ignore values that are greater than the current minimum
if (curval > minval)
continue;
// we have a new minimum value
if (curval < minval) {
// reset count of matching indexes
if (! noreset)
mincount = 0;
// set new minimum value
minval = curval;
}
// current value is part of the set of minimum values
if (curval == minval)
idxlist[mincount++] = curidx;
}
// print results
do {
if (minval >= 0) {
printf("no negative values found\n");
break;
}
printf("minimum value is: %d\n",minval);
printf("it is contained in indexes:\n");
for (int listidx = 0; listidx < mincount; ++listidx) {
int arridx = idxlist[listidx];
int curval = arr[arridx];
printf(" arr[%d]=%d%s\n",
arridx,curval,(curval != minval) ? " FAIL" : "");
}
} while (0);
#if ALLOC
free(idxlist);
#endif
}
#define DOTEST(_data...) \
do { \
int arr[] = { _data }; \
dotest(sizeof(arr) / sizeof(arr[0]),arr); \
} while (0)
void
dotest(int n,int arr[n])
{
printf("\n");
for (int col = 1; col <= 80; ++col)
printf("-");
printf("\n");
printf("dotest: n=%d\n",n);
for (int arridx = 0; arridx < n; ++arridx)
printf("dotest: arr[%d]=%d\n",arridx,arr[arridx]);
printf("\nNORMAL:\n");
noreset = 0;
amnn(arr,n);
printf("\nNORESET:\n");
noreset = 1;
amnn(arr,n);
}
int
main(void)
{
DOTEST(-9, 5, -2, -99, -99);
DOTEST(-7, -6);
DOTEST(-6, -7);
return 0;
}
Here is the program output:
--------------------------------------------------------------------------------
dotest: n=5
dotest: arr[0]=-9
dotest: arr[1]=5
dotest: arr[2]=-2
dotest: arr[3]=-99
dotest: arr[4]=-99
NORMAL:
minimum value is: -99
it is contained in indexes:
arr[3]=-99
arr[4]=-99
NORESET:
minimum value is: -99
it is contained in indexes:
arr[0]=-9 FAIL
arr[3]=-99
arr[4]=-99
--------------------------------------------------------------------------------
dotest: n=2
dotest: arr[0]=-7
dotest: arr[1]=-6
NORMAL:
minimum value is: -7
it is contained in indexes:
arr[0]=-7
NORESET:
minimum value is: -7
it is contained in indexes:
arr[0]=-7
--------------------------------------------------------------------------------
dotest: n=2
dotest: arr[0]=-6
dotest: arr[1]=-7
NORMAL:
minimum value is: -7
it is contained in indexes:
arr[1]=-7
NORESET:
minimum value is: -7
it is contained in indexes:
arr[0]=-6 FAIL
arr[1]=-7
As above, it can help to write code that checks the results for validity.
To help debug programs, we can also add extra printf
statements that can show intermediate values and progress. To keep the code small and easy to read, I prefer to use a macro:
#if DEBUG
#define dbgprt(_fmt...) \
printf(_fmt)
#else
#define dbgprt(_fmt...) \
do { } while (0)
#endif
Then, when we want to see the debug output, we compile with -DDEBUG
. Otherwise, the program runs normally (at full speed).