I am studying the pointers and this question became interesting. I want it to be like this: we have two arrays of integers. Determine the value and number of the largest element of the first array that is not part of the second but I don't know how to make the second part of the code that will check if the largest number is not included in the second array
#include <stdio.h>
int main()
{
long array[100], * maximum, size, c, location = 1;
printf("Enter the number of elements in array\n");
scanf_s("%ld", &size);
printf("Enter %ld integers\n", size);
for (c = 0; c < size; c++)
scanf_s("%ld", &array[c]);
maximum = array;
*maximum = *array;
for (c = 1; c < size; c++)
{
if (*(array + c) > *maximum)
{
*maximum = *(array + c);
location = c + 1;
}
}
printf("Maximum element is present at location number %ld and it's value is %ld.\n", location, *maximum);
return 0;
}
For starters your incomplete code already is wrong. It changes the source array
maximum = array;
//...
*maximum = *(array + c);
More precisely it changes the first element of the array. It shall not do that.
As for your question then the code will look more clear and readable if to implement the algorithm as separate functions.
Here is a demonstration program.
#include <stdio.h>
int find( const int a[], size_t n, int value )
{
const int *p = a;
while (p != a + n && *p != value) ++p;
return p != a + n;
}
int * max_exclusive_element( const int a1[], size_t n1, const int a2[], size_t n2 )
{
const int *max = a1;
while (max < a1 + n1 && find( a2, n2, *max ) ) ++max;
if (max < a1 + n1)
{
for ( const int *p = max; ++p < a1 + n1; )
{
if ( *max < *p && !find( a2, n2, *p ) )
{
max = p;
}
}
}
return ( int * )( max == a1 + n1 ? NULL : max );
}
int main( void )
{
int a1[] = { 1, 3, 5, 6, 7, 8, 9 };
const size_t N1 = sizeof( a1 ) / sizeof( *a1 );
int a2[] = { 1, 3, 5, 7, 9 };
const size_t N2 = sizeof( a2 ) / sizeof( *a2 );
int *max = max_exclusive_element( a1, N1, a2, N2 );
if (max != NULL)
{
printf( "Maximum element is present at location number %td and it's value is %d.\n",
max - a1, *max );
}
}
The program output is
Maximum element is present at location number 5 and it's value is 8.
The function find determines whether a given value is present in an array. And the second function max_exclusive_element finds the maximum element according to the requirement.
As you can see all loops use pointers.
If you need to use arrays with elements of the type long int then it will be not hard to change the presented code.
I think you are doing this in the wrong order. If you find the maximum first and that is in the second array, you need to find the maximum again. You should first check each number in the first array against the second. If it is in the second, change the value to LONG_MIN. Then the maximum will be the right answer. Basically something like this:
#include <limits.h>
int i = 0;
for (; i < n; ++i) {
int j = 0;
for (; j < n; ++j) {
/* in both arrays? */
if (arr2[i] == arr1[j]) {
arr1[j] = LONG_MIN;
break;
}
}
}
At this point any numbers in arr1 that are in arr2 will be set to LONG_MIN. Now just calculate max like you already did.
Edit: changed INT_MIN to LONG_MIN. I didn't notice you were doing long int arrays.
Related
I need to filter some specific elements from an array. I write the code which work perfectly:
#include <stdio.h>
#define NELEMS(x) (sizeof(x) / sizeof((x)[0]))
int main (int argc, char *argv[]) {
// our initial array
int x[] = {1,2,-3,4,5};
// initialize filtered_array with pointer
int *filtered;
int upper_bound = 4, lower_bound = 1, i, j=0, total = -1,result;
size_t n = NELEMS(x);
printf("size of the main array: %d\n",n);
// check which element satisfy the condition and count them
for (i=0;i<n;++i)
{
total = ((x[i] >= lower_bound) && (x[i] <= upper_bound)) ? total+1 : total;
};
// allocate array size for filtered array
filtered = (int*) calloc(total,sizeof(int));
for (i=0;i<n;++i)
{
// filter element from main array and store them in filtered array
result = ((x[i] >= lower_bound) && (x[i] <= upper_bound)) ? 1 : 0;
if(result) {
filtered[j] = x[i];
++j;
};
};
for (i = 0; i<total+1; ++i){
printf("%d ",filtered[i]);
};
return 0;
}
But can I avoid to create a new array like I used filtered and dynamically do this for the main array by some overwrite trick?
For starters your program is incorrect.
Firstly you need to include the header <stdlib.h>
#include <stdlib.h>
Secondly, initially total is set to -1
total = -1
So if the original array contains only one element that satisfies the condition then total will be equal to 0 due to this statement
total = ((x[i] >= lower_bound) && (x[i] <= upper_bound)) ? total+1 : total;
As a result this statement
filtered = (int*) calloc(total,sizeof(int));
is trying to allocate a memory with the size equal to 0. If the memory will be allocated (it is implementation defined) then you may not write anything in this memory. Otherwise the program will have undefined behavior.
In any case you are counting elements that satisfy the condition incorrectly and hence allocating a block of memory of an incorrect size.
Also there is no sense to insert a null statement after compound statements as you are doing
for (i=0;i<n;++i)
{
//...
};
^^^
Remove such redundant semicolons.
And you are using an incorrect conversion specifier in this call of printf.
printf("size of the main array: %d\n",n);
^^^
You have to write
printf("size of the main array: %zu\n",n);
^^^
As for your question
But can I avoid to create a new array like I used filtered and
dynamically do this for the main array by some overwrite trick?
then what you need is to change the array in place and to track the number of actual elements that satisfy the condition.
For example
int x[] = {1,2,-3,4,5};
// initialize filtered_array with pointer
size_t n = NELEMS(x);
int upper_bound = 4, lower_bound = 1;
printf( "size of the main array: %zu\n", n );
size_t m = 0;
for ( size_t i = 0; i < n; ++i )
{
if ( x[i] >= lower_bound) && x[i] <= upper_bound )
{
if ( m != i )
{
x[m] = x[i];
}
++m;
}
}
for ( size_t i = 0; i < m; ++i )
{
printf( "%d ", x[i] );
}
putchar( '\n' );
If you need to reallocate the original array according to the number of elements that satisfy the condition then the code can look for example the following way
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
//...
size_t n = 5;
int *x = malloc( n * sizeof( int ) );
memcpy( x, ( int[] ){ 1, 2, -3, 4, 5 }, n * sizeof( int ) );
int upper_bound = 4, lower_bound = 1;
printf( "size of the main array: %zu\n", n );
size_t m = 0;
for ( size_t i = 0; i < n; ++i )
{
if ( x[i] >= lower_bound) && x[i] <= upper_bound )
{
if ( m != i )
{
x[m] = x[i];
}
++m;
}
}
if ( m != n )
{
int *tmp = realloc( x, m * sizeof( int ) );
if ( tmp != NULL )
{
x = tmp;
for ( size_t i = 0; i < m; ++i )
{
printf( "%d ", x[i] );
}
putchar( '\n' );
}
}
free( x );
What you are looking for is called modification (in this case filtering) in place.
That's even pretty simple:
int* filter(int* begin, int* end)
{
int* pos = begin; // start at the beginning of the array
for(; begin != end; ++begin)
{
if(*begin != 0) // your appropriate condition!
// this one filters out all zero values...
{
*pos++ = *begin; // copy current element to retain into
// first position not yet used
// (pos always points to one element past
// the last one retained!)
}
}
return pos; // as above, points to one past the last element retained
}
The return value is important to know how many elements remained.
If you prefer, you can instead write an index-based variant avoiding pointer arithmetics...
The basic idea about the filtering algorithm is that you just copy the elements towards the front, overwriting those values that either are filtered away or have already been copied.
Edit: Additional explanations:
begin and end pointers are to be passed as pointer to first element of the array and pointer to one past the array (typical C++ semantics when iterating over C++ STL containers, though these come with their own iterator types instead of pointers...).
So you'd call the function like:
int array[N];
int* newEnd = filter(array, array + sizeof(array)/sizeof(*array));
This is typical C++ semantics when iterating over STL containers (though these come with their specific iterator types instead of poitners).
If you don't like:
size_t filter(size_t length, int array[length]) // note: length as array subscript
// is ignored anyway...
{
int* pos = array;
int* begin = array;
int* end = array + length;
// now following the identical loop as above
return pos - array; // pointer difference; if pos points one past the last
// element you get the *number* of elements retained
}
About *pos++ = *begin: That's nothing special and any good C book should explain that nicely to you...
It copies the value begin points to to the address pos points to and increments pos afterwards.
An indexing loop doing the same might look as follows:
size_t pos = 0;
for(size_t i = 0; i < length; ++i)
{
array[pos++] = array[i]
}
return pos;
I want to print the number of unique elements instead of show the elements For example show 4. Means we have 4 unique elements
#include<stdio.h>
#define max 100
int ifexists(int z[], int u, int v)
{
int i;
for (i=0; i<u;i++)
if (z[i]==v) return (1);
return (0);
}
void main()
{
int p[max], q[max];
int m;
int i,k;
k=0;
printf("Enter length of the array:");
scanf("%d",&m);
printf("Enter %d elements of the array\n",m);
for(i=0;i<m;i++ )
scanf("%d",&p[i]);
q[0]=p[0];
k=1;
for (i=1;i<m;i++)
{
if(!ifexists(q,k,p[i]))
{
q[k]=p[i];
k++;
}
}
printf("\nThe unique elements in the array are:\n");
for(i = 0;i<k;i++)
printf("%d\n",q[i]);
}
https://onlinegdb.com/Bk3tvQMpw
Sort the array then iterate through the elements and print out if the current element is different than the last:
int cmpint(const void *a, const void *b) {
return *(int *) a) < *(int *) b :
-1 ?
(
*(int *) b) < *(int *) a ?
1 :
0
);
}
int main() {
/* ... */
qsort(p, m, sizeof(*p), cmpint);
int n = 0;
for(int i = 0; i < m; i++) {
if(!i || p[i-1] != p[i]) n++;
}
printf("Number of unique elements: %d\n", n);
}
where p is your now sorted array and length is m as per example code. As qsort is expected O(m *log(m)) so will this aglorithm. If you don't sort the array it will be O(m^2) due to m linear searches.
If I have understood the question correctly what you need is to count unique elements in an array using a function and without defining an auxiliary array. That is there is no need to output the unique elements themselves.
In this case the corresponding function can look the following way as it is shown in the demonstrative program below.
#include <stdio.h>
int is_unique( const int a[], size_t n, int value )
{
while ( n != 0 && a[ n - 1 ] != value ) --n;
return n == 0;
}
int main(void)
{
int a[] = { 1, 2, 3, 3, 2, 1 };
const size_t N = sizeof( a ) / sizeof( *a );
size_t count = 0;
for ( size_t i = 0; i < N; i++ )
{
count += is_unique( a, count, a[i] );
}
printf( "There are %zu unique elements in the array.\n", count );
return 0;
}
The program output is
There are 3 unique elements in the array.
If you do not want to define one more function to count unique elements in an array then just move the loop in the function shown in the above demonstrative program inside main.
Here you are.
#include <stdio.h>
int main(void)
{
int a[] = { 1, 2, 3, 3, 2, 1 };
const size_t N = sizeof( a ) / sizeof( *a );
size_t count = 0;
for ( size_t i = 0; i < N; i++ )
{
size_t j = i;
while ( j != 0 && a[j - 1] != a[i] ) --j;
count += j == 0;
}
printf( "There are %zu unique elements in the array.\n", count );
return 0;
}
The program output is the same as shown above that is
There are 3 unique elements in the array.
Pay attention to that according to the C Standard the function main without parameters shall be declared like
int main( void )
instead of
void main()
I am trying to write a sorting algorithm using a function that finds the adress of the minimum element in the array:
#include <stdio.h>
int * findMin(int * start,int * end) ///function to return the adress of the smallest array element
{
int *min = start;
int x;
int size = (end - start);
for(x=0; x<size; x++)
{
if (*(start+x)<*min)
min = (start+x);
}
return min;
}
But here in my sort algorithm, since the last element has nothing more to compare itself with, is mistakenly left as it is
void sort(int * start, int * end) ///funtion to sort the array in ascending order
{
int x,temp;
int size = (end - start);
for (x = 0; x <size; x++)
{
if ( *(start+x) > *findMin(start,end))
{
temp = *findMin(start+x,end);
*findMin(start+x,end) = *(start+x);
*(start+x) = temp;
}
}
}
int main()
{
int arr[10]={5,11,3,12,17,25,1,9,14,2};
sort(arr,&arr[9]);
for(int i=0;i<10;i++)
printf("%d ",arr[i]);
printf("\n");
}
How can I correct this?
The expression in this declaration
int size = (end - start);
does not give the exact size of the array. At least you should write
int size = end - start + 1;
However it is not a good idea to pass the pointer to the last element of the array instead of the pointer to the memory after the last element of the array. In this case you can specify an empty range as start is equal to end.
Also if the function accepts two pointers then there is no need to introduce intermediate variables used as indices in loops.
And this code snippet
temp = *findMin(start+x,end);
*findMin(start+x,end) = *(start+x);
*(start+x) = temp;
is very inefficient.
Here is a demonstrative program that shows how the functions can be implemented.
#include <stdio.h>
int * findMin( const int * start, const int * end ) ///function to return the adress of the smallest array element
{
const int *min = start;
if ( start != end )
{
while ( ++start != end )
{
if ( *start < *min ) min = start;
}
}
return ( int * )min;
}
void selection_sort( int *start, int *end ) ///funtion to sort the array in ascending order
{
for ( ; start != end; ++start )
{
int *min = findMin( start, end );
if ( min != start )
{
int tmp = *start;
*start = *min;
*min = tmp;
}
}
}
int main(void)
{
int arr[] = { 5, 11, 3, 12, 17, 25, 1, 9, 14, 2 };
const size_t N = sizeof( arr ) / sizeof( *arr );
for ( const int *p = arr; p != arr + N; ++p )
{
printf( "%d ", *p );
}
putchar( '\n' );
selection_sort( arr, arr + N );
for ( const int *p = arr; p != arr + N; ++p )
{
printf( "%d ", *p );
}
putchar( '\n' );
return 0;
}
The program output is
5 11 3 12 17 25 1 9 14 2
1 2 3 5 9 11 12 14 17 25
But here in my sort algorithm, since the last element has nothing more to compare itself with, is mistakenly left as it is
No, that's at best a misleading characterization. Your findMin() does not specifically compare array elements to their immediate successors, so the fact that *end has no successor is irrelevant. The problem is (in part) simply that you have an off-by-one error, resulting in never comparing *end with *min. That mistake would be harder to make and easier to recognize if you relied more directly on pointer arithmetic and comparisons:
int *findMin(int *start, int *end) {
int *min = start;
// The original code is equivalent to this variant:
// for (int *x = start; x < end; x++) {
// but this is what you need for an inclusive upper bound:
// for (int *x = start; x <= end; x++) {
// or, since initially min == start, this would be even better:
for (int *x = start + 1; x <= end; x++) {
if (*x < *min) {
min = x;
}
}
return min;
}
I'm trying to recursively find a sum of perfect squares in a dynamically allocated list. For some reason, my function keeps overlooking the first element.
*A is the pointer to the first element of the array. n is the number of elements, meaning they are in range from 0 to n-1. When n is less than or equal to zero, n-1 isn't a valid index so I'm returning 0 to the sum of perfect squares.
int sum(int *A, int n)
{
int i, num = 0;
if (n <= 0)
return num;
for (i = 0; i < A[n - 1]; i++) {
if (i*i == A[n - 1]) {
num = A[n - 1];
}
}
return num + sum(A, n - 1);
}
Why does the first element always get overlooked? It works for all the other elements in the list.
EDIT: I've tried calling the function again and it seems that only number 1 got overlooked. That was fixed by modifying the for loop condition, so the solution would be:
int sum(int *A, int n)
{
int i, num = 0;
if (n <= 0)
return num;
for (i = 0; i <= A[n - 1]; i++) {
if (i*i == A[n - 1]) {
num = A[n - 1];
}
}
return num + sum(A, n - 1);
}
For starters as the array pointed to by A is not changed the pointer should be declared with the qualifier const.
Sizes of objects in C are estimated by using the type size_t. So the second parameter should be declared as having the type size_t.
Also the sum of perfect squares can be larger than an object of the type int can accomodate. So it is better to use the type long long int as the return type.
And if I am not mistaken 0 is not a perfect square. Though it is not very important nevertheless the loop can start with 1 instead of 0..
I can suggest the following solution.
#include <stdio.h>
long long int sum( const int *a, size_t n )
{
int perfect_square = 0;
if ( n )
{
int i = 1;
while ( i * i < a[n-1] ) i++;
if ( a[n-1] == i * i ) perfect_square = a[n-1];
}
return n == 0 ? perfect_square : perfect_square + sum( a, n -1 );
}
int main(void)
{
int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
const size_t N = sizeof( a ) / sizeof( *a );
printf( "The sum of perfect squares is %lld\n", sum( a, N ) );
return 0;
}
The program output is
The sum of perfect squares is 14
First element in an array is A[0]. You're returning 0 rather than the value of A[0] when you're calling sum(A,0).
Did you try changing the line to: if (n<=0) return A(0);?
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
array a1 = [1, 2, 3, 4, 5, 8];
array a2 = [1, 4, 5];
array a3 = a1 - a2; /* [2, 3, 8] */
array a4 = a2 - a1; /* print -None */
Here array would be the type my program uses to represent a struct which is used as a container. The rest of it is pseudo code, of course I'm not creating the arrays like that nor subtracting.
The simplest solution I can think of involves nested loops. any idea to solve an efficient way to solve this problem?
You want set difference. If both arrays are sorted, and contain no duplicates, you can iterate through both simultaneously:in linear time.
Whenever you encounter an element b in list B greater than the current element a of A, you can be sure that B does not contain a (or it would not be sorted). Then a is in A and not B, so it is in your output. Proceed to the next element of A, and compare it to the first element of B greater than the previous a, which is your current b. If b < a, it is also less than any remaining element of a, so you can advance to the next element of b. If you do encounter a == b, it is not in the set difference, so compare the next elements of both lists. If you reach the end of B first, add all remaining elements of A. When you reach the end of A, stop.
You can sort a list and remove duplicates in O(n log n) time, or faster if you can radix sort.
Sample Code
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
void print_set( const size_t asize, const int a[asize] )
{
const ptrdiff_t n = (ptrdiff_t)asize;
assert(n >= 0);
putchar('{');
if (n > 0) {
printf( "%d", a[0] );
for ( ptrdiff_t i = 1; i < n; ++i )
printf( ", %d", a[i] );
}
putchar('}');
fflush(stdout);
return;
}
size_t setdiff( const size_t asize, const int a[asize],
const size_t bsize, const int b[bsize],
const size_t csize, int c[csize] )
/* Calculates c = a - b, where a, b and c are sets. Returns the number of
* elements in c. The destination array c must be large enough to hold the
* result (asize elements are always enough). All sets must be sorted and
* contain no duplicates (checked at runtime).
*/
{
ptrdiff_t i = 0, j = 0, k = 0;
const ptrdiff_t m = (ptrdiff_t)asize;
const ptrdiff_t n = (ptrdiff_t)bsize;
const ptrdiff_t p = (ptrdiff_t)csize;
assert(m >= 0);
assert(n >= 0);
assert(p >= 0);
while ( i < m ) {
if ( j == n || a[i] < b[j] ) {
assert( k < p );
c[k++] = a[i++];
assert( i == m || a[i] > a[i-1]);
} else if ( a[i] > b[j] ) {
++j;
assert( j == n || b[j] > b[j-1]);
} else {
assert( a[i] == b[j] );
++i;
assert( i == m || a[i] > a[i-1]);
++j;
assert( j == n || b[j] > b[j-1]);
}
}
return (size_t)k;
}
int main(void)
{
static const int a[] = {1, 2, 3, 4, 5, 6};
static const size_t m = sizeof(a)/sizeof(a[0]);
static const int b[] = {1, 4, 5};
static const size_t n = sizeof(b)/sizeof(b[0]);
int c[6] = {0};
static const size_t p = sizeof(c)/sizeof(c[0]);
print_set( m, a );
printf(" - ");
print_set( n, b );
printf(" = ");
const size_t q = setdiff( m, a, n, b, p, c );
print_set( q, c );
printf(".\n");
print_set( n, b );
printf(" - ");
print_set( m, a );
printf(" = ");
const size_t r = setdiff( n, b, m, a, p, c );
print_set( r, c );
printf(".\n");
return EXIT_SUCCESS;
}
Assuming the two arrays are sorted, as in your examples, you should be able to locate common elements optimally using bsearch. I've provided an example, but in the future please make an effort to write your own C code in the future, then I/we might be able to help you better!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int compare(void const *x, void const *y) {
return memcmp(x, y, sizeof (int)); // XXX: This might not be what you expect for negative values!
}
size_t difference(void *dest, size_t dest_size, void const *x, size_t x_size, void const *y, size_t y_size, size_t size, int (*compare)(void const *, void const *)) {
typedef unsigned char item[size];
item const *a = x, *b = y;
item *d = dest;
size_t cursor = 0, d_size = 0;
for (size_t x = 0; x < x_size; x++) {
item *ptr = bsearch(a + x, b + cursor, y_size - cursor, size, compare);
if (ptr) {
cursor = ptr - b;
}
else {
memcpy(d[d_size++], a[x], sizeof (item));
}
}
return d_size;
}
void print(char *name, int array[], size_t array_size) {
printf("%s: %s", name, array_size ? "" : "NONE\n");
for (size_t x = 0; x < array_size; x++, putchar(x < array_size ? ',' : '\n')) {
printf("%d", array[x]);
}
}
int main(void) {
int a[] = { 1, 2, 3, 4, 5, 8 },
b[] = { 1, 4, 5 },
c[sizeof a / sizeof *a],
d[sizeof a / sizeof *a];
size_t c_size = difference(c, sizeof c / sizeof *c,
a, sizeof a / sizeof *a,
b, sizeof b / sizeof *b,
sizeof (int), compare);
size_t d_size = difference(d, sizeof d / sizeof *d,
b, sizeof b / sizeof *b,
a, sizeof a / sizeof *a,
sizeof (int), compare);
print("c", c, c_size);
print("d", d, d_size);
}
First, you will obviously need a find function:
int find(int val, const int* a, int na)
{
int i;
for (i = 0; i < na; ++i)
{
if (val == a[i])
return i;
}
return -1;
}
The diff function become quite trivial, assuming you have an allocated array for the result. r should be able to hold at least na elements.
int diff(int* r, const int* a, int na, const int* b, int nb)
{
// returns the number of elenment in resulting set.
// on output r contains the elements from a that are not found in b
// expects r to provide enough room for na elements
int i, nr;
nr = 0;
for (i = 0; i < na; ++i)
{
if (find(a[i], b, nb) < 0)
{
r[nr++] = a[i];
}
}
return nr;
}
I know that in a sense, this is still a nested loop. But it is much more readable. Plus, you've gained a generic find() function that you can use elsewhere in your code.
I thought the difference of two sets was not as you describe, but defined as A with intersection of A and B removed. i.e. If a value is found several times in A, but only once in B, only one element of A is removed from the result set. For this case, you'd need a remove function.
int remove(int at, int* a, int na)
{
// removes first occurence of val in a.
// returns the number of elements in a after remove op.
if (0 <= at && at < na)
{
memmove(&a[at], &a[at + 1], sizeof(int) * (na - (at + 1)));
return na - 1;
}
return na;
}
The diff when elements are not unique is not much more complex, we'll loop on b.
int difference(int* r, const int* a, int na, const int* b, int nb)
{
// returns elements from a, minus set b.
// handles non-unique cases, so this is the true difference or a-b
// returns the number of elements in resulting set
int nr, found;
memcpy(r, a, na * sizeof(int));
nr = na;
for (i = 0; i < nb; ++i)
{
found = find(b[i], r, nr);
if (found >= 0)
{
nr = remove(found, r, nr);
}
}
return nr;
}
I did not try to compile these, so there might be some typos, but it should be fairly close..
Edit: These algorithms have a complexity of O(N^2), so by sorting a (or b) and using a binary search, you could get them down to 1) O(2NlogN) 2) O(3NlogN), which is not bad, since you'd only need to change the find() function to implement optimization.