Shallow copy of two arrays in C - c

Is there a way to shallow copy the elements of a dynamically allocated array in C? Something like the following:
int size = 2;
int *arr1 = malloc(size*sizeof(int));
int *arr2 = malloc(size*sizeof(int));
arr1[0] = 1; arr1[1] = 2; // {1, 2}
arr2[0] = 3; arr2[1] = 4; // {3, 4}
// shallow copy here s.t. memadress(arr1[i]) == memadress(arr2[i])
// ...
arr1[0] = -1; // arr1 = {-1, 2} AND arr2 = {-1, 4}

"Shallow" or "soft" copy typically just means copying a pointer but not the pointed-at data. As opposed to "hard" copy which also copies the pointed-at data. In your case, for example:
int *arr1 = malloc(size*sizeof(int));
int *arr2 = arr1; // "soft copy"
int* arr3 = malloc(size*sizeof(int);
memcpy(arr3, arr1, size*sizeof(int)); // "hard copy"
Or if you will:
int *arr1 = malloc(size*sizeof(int));
int *arr2 = malloc(size*sizeof(int));
arr1[0] = 1; arr1[1] = 2; // {1, 2}
arr2[0] = 3; arr2[1] = 4; // {3, 4}
free(arr2);
arr2 = arr1;
arr1[0] = -1; // {-1, 2} AND arr2 --> {-1, 4}
This doesn't make much sense, since it implies a soft copy of the elements not of the arrays. Such a container is likely needlessly complicated and not very useful. It could be done with an array of pointers, however:
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
int size = 2;
int **arr1 = malloc(size*sizeof(int*));
int **arr2 = malloc(size*sizeof(int*));
// assign pointers to point at local compound literals:
arr1[0] = &(int){1}; arr1[1] = &(int){2}; // {1, 2}
arr2[0] = &(int){3}; arr2[1] = &(int){4}; // {3, 4}
arr2[0] = arr1[0]; // "soft copy"
*arr1[0] = -1;
printf("arr1: {%d %d}\n", *arr1[0], *arr1[1]);
printf("arr2: {%d %d}\n", *arr2[0], *arr2[1]);
free(arr1);
free(arr2);
}
Output:
arr1: {-1 2}
arr2: {-1 4}
But please avoid coming up with such obscure solutions just for the heck of it. Good programming = writing code as simple as possible.

Related

Exercise with array and pointer

I am a beginner in C. I want to write a function to return an array containing all elements common to two given arrays containing distinct positive integers.
Sample input/output is in the following table:
|input parameters | return |
| ---------- | -------- |
|{1, 8, 3, 2}, {4, 2, 6, 1} | {1, 2} |
|{1, 8, 3, 2, 6}, {2, 6, 1} | {2, 6, 1} |
|{1, 3, 7, 9}, {7, 1, 9, 3} | {1, 3, 7, 9}|
|{1, 2}, {3, 4} | {} |
|{}, {1, 2, 3} | {} |
|{1, 2}, {} | {} |
|{1, 2}, null | null |
|null, {} | null |
|null, null | null |
int f(int first[], int second[], int first_len, int second_len, int result_len)
{
if (first == NULL || second == NULL)
{
return NULL;
}
if (first_len == 0 || second_len == 0) return malloc(0);
int min = (first_len < second_len) ? first_len : second_len;
int *a, *b;
if (min == first_len)
{
a = first;
b = second;
}
else
{
a = second;
b = first;
}
int *c = malloc(min);
int k = 0;
for (int i = 0; i <sizeof(*a); i++)
{
for (int j = 0; j < sizeof(*b) ; j++)
{
if (a[i] == b[j])
{
c[k] = a[i];
k++;
}
}
}
int *retArray = malloc(k * result_len);
result_len = sizeof(retArray)/sizeof(*retArray);
for (int t = 0; t < result_len; t++)
{
retArray[t] = c[t];
}
return retArray;
}
int main()
{
int first[] = {1,3,8,9};
int second[] = {3,5,8};
int result_len;
int first_len = sizeof(first)/sizeof(*first);
int second_len = sizeof(second)/sizeof(*second);
printf("%d\n", f(first,second,first_len,first_len,result_len));
return 0;
}
This code doesn't give the result that I need can anyone help me out?
Without discussing the actual algorithmic exercise, the confusion here seems to be in the return type. You can't return more than one value in C code. The value can however be struct or a pointer to allocated memory. Code is worth a thousand words so consider the following example:
#include <stdio.h>
#include <stdlib.h>
void foo(char *arr)
{
// fill the given memory location with requested data
arr[0] = '4';
arr[1] = '2';
arr[2] = '0';
// note absent or empty return;
}
int main()
{
// allocate some space for return value
char *arr = malloc(3 * sizeof(char));
// tell the function where to store the result by passing the arr pointer
foo(arr);
// the function has filled the array with some data
printf("%c%c%c\n", arr[0], arr[1], arr[2]);
// don't forget to free the allocated memory when it's no longer in use
free(arr);
return 0;
}
This technique is generally called 'returning by reference', as you are using a reference (pointer) to return the data as opposed to 'returning by value' when you directly return the number (or other data type).
You can of course also allocate the new block of memory in the function and then return the pointer like so:
char *foo()
{
char *arr = malloc(3 * sizeof(char));
// fill with requested data
return arr;
}
Although this makes it easier to forget to free the memory IMO.

Replace a data sequence with another in an array

I would need to replace some data sequences with others, in an array, such as in this example (whose signature I imagined for the replacement function):
seq_replace(
int *array, size_t size0, // The array to modify + its size
int *to_replace, size_t size1, // The sequence to be replaced + its size
int *to_place, size_t size2); // The sequence to be placed + its size
int array[] = {0, 6, 3, 0, 6, 2};
seq_replace(
&array, 6,
(const int[]){0, 6}, 2,
(const int[]){9}, 1);
And would be obtain my array with values {9, 3, 9, 2}.
I imagine that linked lists would be more suitable for this style of task, but I work throughout my project with arrays, and making conversions between types of container would cost time.
Anyway, I don't know of any algorithm to do this kind of thing, and I haven't found anything interesting on the Internet either. I therefore turn to this site for advice on how to carry out this task.
Here is a code that works in the case array is known to be large enough for any replacement. The function returns the new logical size of array. The // p += size2; commented instruction makes it possible to recursively replace inside the result of to_place (as it is the case for a peephole optimizer). For instance in {0,6,6} replacing {0,6} by {0} gives {0}.
There is a main() to test various cases.
#include <stdio.h>
#include <string.h>
void show_array(const int *array, size_t size0)
{
int i;
for(i = 0; i < size0; i++)
printf("%3d", array[i]);
puts("");
}
int seq_replace(int *array, size_t size0, // The array to modify + its size
const int *to_replace, size_t size1, // The sequence to be replaced + its size
const int *to_place, size_t size2) // The sequence to be placed + its size
{
int *p = array, *end = array + size0;
while(p < end)
{
if (p + size1 <= end && memcmp(p, to_replace, size1 * sizeof(*p)) == 0)
{
memmove(p + size2, p + size1, (end - p - size1) * sizeof(*p));
memcpy(p, to_place, size2 * sizeof(*p));
// p += size2; // uncomment to avoid replacements in to_place itself
size0 = size0 - size1 + size2;
end = array + size0;
}
else
{
p++;
}
}
return size0; // return logical new size
}
#define N_ELEM(p) (sizeof(p) / sizeof(*(p)))
// array is physically large enough
int array[1000] = {0, 6, 6, 0, 6, 2, 0, 6, 0, 6};
int size0 = 10; // its logical length
int to_replace[] = {0, 6};
int to_place[] = {0}; // try {9, 8}, {9, 8, 7}, {9} and even {}
int main()
{
printf("initial array; length: %d\n", size0);
show_array(array, size0);
size0 = seq_replace(array, size0,
to_replace, N_ELEM(to_replace),
to_place, N_ELEM(to_place));
printf("final array, new length: %d\n", size0);
show_array(array, size0);
}

pointer to pointer as 2d array

My background is Java therefore I'm not used to pointers, the following code throws error and I can't see way:
#include <stdio.h>
#define DIM 2
void sort_intervals(int** intervals, int n);
int main()
{
int a[3][DIM] = {
{1, 6} ,
{4, 9} ,
{3,17} };
sort_intervals(a, 3);
return 0;
}
void sort_intervals(int** intervals, int n)
{
printf("%d ", intervals[0][0]);//<--- error here
}
Error: Access violation reading location
I'm not allowed to change the function signiture
Then you need an array of pointers that point to arrays.
int a_1[DIM] = {1, 6};
int a_2[DIM] = { ... };
int a_3[DIM] = { ... };
int *a[3] = { a_1, a_2, a_3, }; // array of 3 pointers
sort_intervals(a, 3);
or exactly equivalent using compound literals you can:
int *a[3] = { (int[DIM]){1, 6}, (int[DIM]){2, 7}, (int[DIM]){3, 17}};
sort_intervals(a, 3);
even:
sort_intervals((int*[3]){
(int[DIM]){1, 6},
(int[DIM]){2, 7},
(int[DIM]){3, 17},
}, 3);
I am assuming you can change main function.
You could also initialize a as double pointer such as:
int **a = (int**)calloc(3, sizeof(int*)); //setting a as array of 3 pointers
for (int i = 0; i < 3; i++)
*a = (int*) calloc(DIM, sizeof(int)); //assigning pointer to a[0], a[1] and a[2]
Here a is array of 3 integer pointers. a[0],a[1] and a[2] are int pointers.
You can modify a as a[0][0] = 5;
If you can't change the signature as you explained in your comment, then you can get it done using a jagged array:
#define DIM 2
void sort_intervals(int** intervals, int n);
int main()
{
int **a = malloc(3 * sizeof(int*));
for (int i = 0; i < 3; i++) {
a[i] = malloc(DIM * sizeof(int));
}
a[0][0] = 1; a[0][1] = 6;
a[1][0] = 4; a[1][1] = 9;
a[2][0] = 3; a[2][1] = 17;
sort_intervals(a, 3);
for (int i = 0; i < 3; i++) {
free(a[i]);
}
free(a);
return 0;
}
void sort_intervals(int** intervals, int n)
{
printf("%d ", intervals[2][0]);//<--- error here
}

compare arrays integer values with shifted values

I want create function which compares two arrays so that if they have the same values in a certain order (which may be maybe shifted) returns true.
For example
int arr1[] = {1,2,3,4,5}
int arr2[] = {3,4,5,1,2}
are the same, or true
while
int arr1[] = {1,2,3,4,5}
int arr2[] = {3,4,5,2,1}
are not same, and so false.
Any ideas?
Here you are
#include <stdio.h>
int is_equivalent(const int a[], const int b[], size_t n)
{
int success = 0;
for ( size_t m = 0; !success && m < n; )
{
// Try to find in the array a the first element of the array b
// If there is no such an element then the arrays are different.
// Otherwise compare elements of the arrays starting from the
// found element in a and the first element in b
while (m < n && a[m] != b[0]) ++m;
if (m != n)
{
size_t i = 1;
size_t j = ++m % n;
while (i < n && b[i] == a[j])
{
++i; ++j;
j %= n;
}
success = i == n;
}
}
return success;
}
int main( void )
{
{
int a[] = { 1, 2, 3, 4, 5 };
int b[] = { 3, 4, 5, 1, 2 };
printf("The arrays are equivalent: %d\n",
is_equivalent(a, b, sizeof(a) / sizeof(*a)));
}
{
int a[] = { 1, 2, 3, 4, 5 };
int b[] = { 3, 4, 5, 2, 1 };
printf("The arrays are equivalent: %d\n",
is_equivalent(a, b, sizeof(a) / sizeof(*a)));
}
return 0;
}
The program output is
The arrays are equivalent: 1
The arrays are equivalent: 0
try this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
bool check(size_t size, int arr1[], int arr2[]){
int *temp = malloc(size * 2 * sizeof *temp);
memcpy(temp, arr1, size * sizeof *temp);
memcpy(temp+size, arr1, size * sizeof *temp);//[1,2,3] --> [1,2,3,1,2,3]
size_t i;
for(i = 0; i < size; ++i)
if(memcmp(temp+i, arr2, size * sizeof *temp) == 0)
break;
free(temp);
return i != size;
}
#define TEST(size, a1, a2) puts(check(size, a1, a2) ? "same" : "not same")
int main(void) {
int arr1[] = {1,2,3,4,5};
int arr2[] = {3,4,5,1,2};
int arr3[] = {3,4,5,2,1};
int arr4[] = {1, 0, 1, 1, 0};
int arr5[] = {1, 0, 1, 0, 1};
size_t size = sizeof(arr1)/sizeof(*arr1);
TEST(size, arr1, arr2);
TEST(size, arr1, arr3);
TEST(size, arr4, arr5);
}
Well, if the arrays are just rotated versions of each other, they must be of equal length and there must exist at least one offset, such that rotate(arr1, offset) == arr2.
Thus we know that concat(arr2, arr2) must be equivalent to rotate(concat(arr1, arr1), offset) and thus must contain arr1 without rotation at position offset.
And there we are with the classical substring-matching problem. There won't be any better solution to this problem than the algorithms to solve the former simply because they are equivalent.
A pretty simple solution to this problem would be elimination of probable offsets:
//generate a list of offsets from the first element in arr1
list offsets = indicesOf(arr1[0], arr2)
int i = 0
while !offsets.empty && i < length(arr1):
//generate the rotational offsets of the next char
list nextoffsets = indicesOf(arr1[i], arr2)
//make offsets the list of offsets that are valid for all elements up to arr1[i]
offsets = intersection(offsets, nextoffsets)
i++
return !offsets.empty
#include <stdio.h>
int isArraySame(int arr1[], int arr2[], int len1, int len2){
int var1=0;
int var2=0;
int index=0;
for (index=0;index<len1;index++){
var1+=arr1[index];
}
for (index=0;index<len2;index++){
var2+=arr2[index];
}
if (var1==var2) return 1;
return 0;
}
int main(){
int arr1[] = {1,2,3,4,5};
int arr2[] = {3,4,5,1,2};
if (isArraySame(arr1, arr2, 5, 5)) {
printf("true");
} else {
printf("false");
}
return 0;
}
You may be interested in the C++ equivalent for this. It's instructive to see how the Standard Library provides much higher-level abstractions than are available to the C programmer.
First of all, we'll want a sensible signature for our function. Let's make it a template, so we can use std::array as happily as std::vector and struct Foo as happily as int:
template<typename T>
bool equals_rotated(const std::vector<T>& a, const std::vector<T>& b);
And some simple tests:
int main()
{
const auto e = equals_rotated<int>;
return !e({}, {})
+ e({1, 2, 3, 4} , {1, 2, 3})
+ !e({1, 2, 3} , {1, 2, 3})
+ e({1, 2, 3, 4} , {1, 2, 4, 3})
+ !e({1, 2, 3, 4} , {4, 1, 2, 3})
;
}
The implementation is straightforward. We know that if the arrays differ in length then they can't be equivalent; conversely, if they are identical, they must be equivalent. So let's return early in those cases:
if (a.size() != b.size())
return false;
if (a == b)
return true;
For the general case, we can make a concatenation of a and itself, and then test whether that contains b as a subsequence. This will have an impact on the memory requirement, but it makes for a simple implementation:
auto v = a;
v.reserve(2*a.size());
std::copy(a.begin(), a.end(), std::back_inserter(v));
return std::search(v.begin(), v.end(), b.begin(), b.end()) != v.end();
If we put that all together, include the necessary headers, and add a wrapper so that we can call it from C, we get:
#include <algorithm>
#include <iterator>
#include <vector>
template<typename IterA, typename IterB>
bool equals_rotated(IterA a_begin, IterA a_end, IterB b_begin, IterB b_end)
{
// trivial tests
if (a_end - a_begin != b_end - b_begin)
return false;
if (std::equal(a_begin, a_end, b_begin, b_end))
return true;
// Otherwise, make a copy of a+a
std::vector<typename std::iterator_traits<IterA>::value_type> v;
v.reserve(2 * (a_end - a_begin));
const auto ins = std::back_inserter(v);
std::copy(a_begin, a_end, ins);
std::copy(a_begin, a_end, ins);
// and test whether it contains b
return std::search(v.begin(), v.end(), b_begin, b_end) != v.end();
}
template<typename T>
bool equals_rotated(const std::vector<T>& a, const std::vector<T>& b)
{
return equals_rotated(a.begin(), a.end(), b.begin(), b.end());
}
extern "C" {
bool is_rotated_array(int *a, size_t a_len, int *b, size_t b_len)
{
return equals_rotated(a, a+a_len, b, b+b_len);
}
}
int main()
{
const auto e = equals_rotated<int>;
return !e({}, {})
+ e({1, 2, 3, 4} , {1, 2, 3})
+ !e({1, 2, 3} , {1, 2, 3})
+ e({1, 2, 3, 4} , {1, 2, 4, 3})
+ !e({1, 2, 3, 4} , {4, 1, 2, 3})
;
}

Array of arrays, with different sizes

I'm having an array, that has arrays in every cell. For example, the big array is called arr:
int a[3] = {3, 2, 1};
int b[2] = {2, 1};
int *arr[2] = {a, b}
Now the problem is, if I want to print the small arrs, inside the big array.
Here is my code:
#include <stdio.h>
void printArr(int arr [], int n)
{
for (int i = 0 ; i < n ; i++)
{
printf("%d ", *(arr + i));
}
printf("\n");
}
int main()
{
int a[5] = {1, 8, 4, 2, 0};
int b[3] = {1, 4, 2};
int *arr [2] = {a, b};
int n = 0;
for (int i = 0 ; i < 2 ; i++)
{
printArr(*(arr + i), n);
}
}
The output is supposed to be something like this:
1 8 4 2 0
1 4 2
But I can't get the size of each array, since sizeof(*(arr + i) gives me 4, which is the size of the pointer (the name of the array), and not all the array it self.
So what can I do?
Thanks!
The Problem:
The C language only provides a way of finding the size of types.
This gives the subtle differences between applying sizeof to:
1) An array of a type such as:
int a[3];
sizeof(a); // => 3 * sizeof(int)
2) A pointer to the type:
int *ptr;
sizeof(ptr); // => sizeof(int *)
or
int a[3] = {3, 2, 1};
int b[2] = {2, 1};
int *arr[2] = {a, b};
sizeof(arr[1]); // => sizeof(int *)
Some solutions:
Store the size
As jfly proposes store the size of the arrays.
Makes finding the size a constant time operation.
Append an end marker
Adding a end marker like '\0' as used for c-style strings.
You might use INT_MAX or INT_MIN in this case.
The printArr implementation would need to change to:
void printArr(int *arr)
{
int *it = arr;
while(arr != INT_MIN);
{
printf("%d ", *it);
}
printf("\n");
}
Disadvantages:
Finding the size of the array requires iterating over the full array.
Gives the risk of an actual value colliding with the end marker value.
Advantages:
The varying sized array can be passed as a single argument.
Using iterators
Store the pointer to the first and one past the last value.
void printArr(int *begin, int *end)
{
for (int *it = begin; it != end; it++)
{
printf("%d ", *it);
}
printf("\n");
}
int *end_arr[2] = {a + 3, b + 2};
for (int i = 0 ; i < 2 ; i++)
{
printArr(arr[i], end_arr[i]);
}
Can be extended to other data structures.
Since arr is an array of pointers, so you can't get the size of array from the pointer which points to an array, you need additional size info:
int size_arr[2] = {sizeof(a) / sizeof(int), sizeof(b) / sizeof(int)};
for (int i = 0 ; i < 2 ; i++)
{
printArr(arr[i], size_arr[i]);
}

Resources