I have to write a function with the signature
int *greater (int n[], int length, int value)
that returns a pointer to an array containing the elements in n[] that are greater than a value. The array returned must be exactly the length to hold the values greater than value and have no unused elements.
I have the following code:
#include <stdio.h>
int k=0, v[100];
int * greater(int n[], int length, int value)
{
for (int i=0; i<length-1; i++)
if (n[i]>value)
{
v[k]=n[i];
k++;
}
int *p=v;
return p;
}
int main ()
{
int a[]={1,2,3,4,5};
int *p=greater (a,5,3);
int *end; end=v+k;
while (p<=end)
{
printf ("%i ", *p);
p++;
}
}
The problem is that p will only hold the value of 4, therefore it will print 4 0, instead of 4 5. Any ideas what I am doing wrong?
To resolve your issue, do not use a global array( v[100];
). Instead,
greater()
malloc()
. realloc()
In the lights of the comment from Mr. @alk , you can get the number of elements in the array using the global variable k
.
Note: once you're done using the memory, don't forget to free()
the pointer from main()
.
BTW, the recommended signature of main()
is int main(void)
EDIT:
Also, for the logical part, as mentioned in the comments by Mr. @BLUEPIXY and @karma_geek , please note
for (int i=0; i<length; i++)
while
loop to while (p<end)
I would suggest 2 changes in addition to the ones already mentioned:
Iterate the for loop
till <length
, as <legnth-1
would not cover the entire array.
int * greater(int n[], int length, int value)
{
for (int i=0; i<length; i++)
if (n[i]>value)
{
v[k]=n[i];
k++; // increment
}
int *p=v;
return p;
}
Also, change the formula for end. This is because in the function, where the increment occurs, k=0
would change as: k=1
for 4 > 3
, then k=2
for 5 > 3
. Now,
end = v + k ;
would result in end = v + 2
when instead we wanted 1 lesser value.
int *end; end=v+k-1;
As the specs do not require to return the size of the target array, allocating a new array inside the fucntion make the pointer returned quiet useless as the caller does not know which elements (if any) are valid.
So the only sane approach would be to not allocate memory for the target, to not even use a second array. This also is not required by the specs, so you might like to take following approach
Example:
#include <qsort.h>
int cmp(const void * pv1, const void * pv2)
{
int i1 = *((int *) pv1);
int i2 = *((int *) pv2);
return (i1 - i2);
}
int * greater(int n[], int length, int value)
{
qsort(n, sizeof *n, length, cmp);
while (0 < length)
{
--length;
if (n[length] > value)
{
break;
}
}
return n + length + 1;
}
The only req/
array returned must be exactly the length to hold the values greater than valu
is met.
Modify your search function to return the number of elements found in a pointer parameter. Allocate the results array within the function, minimize the number of possible allocations in the function, shrink the results array before returning.
For example:
#include <stdio.h>
#include <stdlib.h>
int *
greater(
const int const n[],
const size_t n_elem,
const int threshold,
size_t *n_greater
)
{
size_t i = 0;
size_t n_found = 0;
size_t n_allocated = 0;
int *ret = NULL;
for (i = 0; i < n_elem; i += 1) {
if (n[i] > threshold) {
n_found += 1;
if (n_found > n_allocated) {
size_t new_size = (n_allocated < (n_elem / 2))
? 2 * n_found
: n_elem
;
int *tmp = realloc(ret, new_size * sizeof(*tmp));
if (!tmp) {
fputs("Failed to allocate memory", stderr);
exit(EXIT_FAILURE);
}
n_allocated = new_size;
ret = tmp;
}
ret[n_found - 1] = n[i];
}
}
if (n_allocated > n_found) {
int *tmp = realloc(ret, n_found * sizeof(*tmp));
if (!tmp) {
fputs("Failed to shrink result array", stderr);
exit(EXIT_FAILURE);
}
ret = tmp;
}
*n_greater = n_found;
return ret;
}
int main (void)
{
int a[] = {1,2,3,4,5,1,1,2,3,7,6,5,5,0,-1,7};
size_t n_greater_than_three = 0;
size_t i =0;
int *p = greater(a, sizeof(a)/sizeof(a[0]), 3, &n_greater_than_three);
for (i = 0; i < n_greater_than_three; i += 1) {
printf("%d\n", p[i]);
}
free(p);
return EXIT_SUCCESS;
}
Output:
C:\...\Temp> greater.exe 4 5 7 6 5 5 7
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.