Array of arrays, with different sizes - c

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]);
}

Related

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
}

RUN FAILED exit value 5 trying to swap arrays

/*Jeremy Johnson 11-18-48
*
*The purpose of this program to to swap halves of an array. So {1 2 3 4 5 6}
*becomes {4 5 6 1 2 3} using pointer notation.
*/
#include <stdio.h>
#include <string.h>
int array[] = {1, 2, 3, 4, 5, 6}; //initialize array
void mirror(int* array, int from_index, int to_index); //prototype statment
int main() {
//define and assign pointer to array address
int *arrptr, i;
arrptr = &array[0];
//print original array
printf("Original Array: \n");
for (i = 0; i <= 5; i++) {
printf("%d", array[i]);
}
printf("\n");
//call function to swap values and mirror the array
mirror(arrptr, 0, 2);
mirror(arrptr, 3, 5);
mirror(arrptr, 0, 5);
mirror(arrptr, 1, 4);
mirror(arrptr, 2, 3);
//print final array
printf("Mirror Array: \n");
for (i = 0; i <= 5; i++) {
printf("%d", array[i]);
}
printf("\n");
return 0;
}
void mirror(int* array, int from_index, int to_index) {
//create pointer for temporary memory storage
int *temp, c[1];
temp = &c[0];
//Place to_index in temporary memory
*(temp) = *(array + to_index-1);
//Copy from_index to to_index
*(array + to_index-1) = *(array + from_index-1);
//Copy temporary value back into from_index
*(array + from_index-1) = *(temp);
return;
}
/* This code works for the function however I am not allowed to use array
notation.
c[1]=array[to_index];
array[to_index]=array[from_index];
array[from_index]=c[1]; */
I am trying to swap each half of the array; I have done so by switching the indices of the arrays by calling the mirror function 5 times and swapping the appropriate values. I was able to do so using the commented code at the bottom in place of the current function code, but now I receive and exit value 5, and I'm not sure why. (I receive no other errors within the code)
// perhaps swap the array by:
void mirror( int*, int* );
int main()
{
...
int *pSecondHalf = array[(sizeof(array)/sizeof(int))>>1];
// note: above line will not work for odd size array so:
if( array[(sizeof(array)/sizeof(int)] & 0x01 )
{
pSecondHalf++; // middle term in odd size array will not move
}
int *pFirstHalf = array;
const int *pLastHalf = array+((sizeof(array)/sizeof(int))>>1);
// note: following 'for' loop will execute one extra time
// for odd size array, but nothing will be changed
for( ; pFirstHalf < pLastHalf; pFirstHalf++, pSecondHalf++ )
{
mirror( pFirstHalf, pSecondHalf );
}
...
return(0);
}
// and in mirror()
void mirror( int *pVal1, int* pVal2)
{
int temp = *pVal1;
*pVal1 = *pVal2;
*pVal2 = temp;
}
The problem was in the mirror function. I did not move each element of the array to the temporary array using a for loop (aka counting loop). I added two loops to the function and it runs fine now.
/*Jeremy Johnson 11-18-48
*
*The purpose of this program to to swap halves of an array. So {1 2 3 4 5 6}
*becomes {4 5 6 1 2 3} using pointer notation.
*/
#include <stdio.h>
#include <string.h>
int array[] = {1, 2, 3, 4, 5, 6}; //initialize array
void mirror(int* array, int from_index, int to_index); //prototype statement
int main() {
//define and assign pointer to array address
int *arrptr, i;
arrptr = &array[0];
//print original array
printf("Original Array: \n");
for (i = 0; i <= 5; i++) {
printf("%d", array[i]);
}
printf("\n");
//call function to swap values and mirror the array
mirror(arrptr, 0, 2);
mirror(arrptr, 3, 5);
mirror(arrptr, 0, 5);
//print final array
printf("Mirror Array: \n");
for (i = 0; i <= 5; i++) {
printf("%d", array[i]);
}
printf("\n");
return 0;
}
void mirror(int* array, int from_index, int to_index) {
//create pointer for temporary memory storage
int *temp, c[6], j;
temp = &c[0];
//Place array elements in temporary memory
for (j = 0; j < 6; j++) {
*(temp + j) = *(array + j);
}
//Place mirrored halves in array respectively
for (j = 0; j <= (to_index - from_index); j++) {
*(array + from_index + j) = *(temp + to_index - j);
}
return;
}

Using a multi-dimensional array with a generic function

I've written the following generic function:
void* scramble(void* arr, int ElemSize, int n, int* indArr){
void * res = malloc(n * ElemSize);
int i;
for (i = 0 ; i < n ; i++)
memcpy((BYTE*)res+i*ElemSize, (BYTE*)arr+indArr[i]*ElemSize, ElemSize);
return res;
}
The function gets an array, the size of each element, and number of elements in the array.indArr is an array with indexes running from 0 to n-1 in any order.The function returns a new array arranged according to indArr.How can I use it to work with two dimensional arrays (or more)? I tried this, but it doesn't work:
int indArr[] = {2, 0, 1};
char names[][10] = {{"David"}, {"Daniel"}, {"Joni"}};
char **res;
res = (char**)scramble(names, sizeof(char*), 3, indArr);
for (i = 0 ; i < 3 ; i++)
printf("%s ", res[i]);
Any thoughts? Thanks
names is an array of arrays.
The scrambler referrs to the outer array. The elements of the latter are the "strings". The size of each string is 10.
So call the scrambler like this:
res = (char**)scramble(names, 10, 3, indArr);
or
res = (char**)scramble(names, sizeof(*names), 3, indArr);
Update:
To be able to access the single elements of the inner array do as follows:
char (*res)[10] = (char (*)[10]) scramble(names, sizeof(*names), 3, indArr);
for (int i = 0; i < 3; ++i)
printf("res[%d] = '%s'\n", i, res[i]);

How to append two arrays in C language?

How can I include the elements of array X and Y in to array total in C language ?
can you please show with an example.
X = (float*) malloc(4);
Y = (float*) malloc(4);
total = (float*) malloc(8);
for (i = 0; i < 4; i++)
{
h_x[i] = 1;
h_y[i] = 2;
}
//How can I make 'total' have both the arrays x and y
//for example I would like the following to print out
// 1, 1, 1, 1, 2, 2, 2, 2
for (i = 0; i < 8; i++)
printf("%.1f, ", total[i]);
Your existing code is allocating the wrong amount of memory because it doesn't take sizeof(float) into account at all.
Other than that, you can append one array to the other with memcpy:
float x[4] = { 1, 1, 1, 1 };
float y[4] = { 2, 2, 2, 2 };
float* total = malloc(8 * sizeof(float)); // array to hold the result
memcpy(total, x, 4 * sizeof(float)); // copy 4 floats from x to total[0]...total[3]
memcpy(total + 4, y, 4 * sizeof(float)); // copy 4 floats from y to total[4]...total[7]
for (i = 0; i < 4; i++)
{
total[i] =h_x[i] = 1;
total[i+4]=h_y[i] = 2;
}
A way to concatenate two C arrays when you know their size.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define ARRAY_CONCAT(TYPE, A, An, B, Bn) \
(TYPE *)array_concat((const void *)(A), (An), (const void *)(B), (Bn), sizeof(TYPE));
void *array_concat(const void *a, size_t an,
const void *b, size_t bn, size_t s)
{
char *p = malloc(s * (an + bn));
memcpy(p, a, an*s);
memcpy(p + an*s, b, bn*s);
return p;
}
// testing
const int a[] = { 1, 1, 1, 1 };
const int b[] = { 2, 2, 2, 2 };
int main(void)
{
unsigned int i;
int *total = ARRAY_CONCAT(int, a, 4, b, 4);
for(i = 0; i < 8; i++)
printf("%d\n", total[i]);
free(total);
return EXIT_SUCCCESS;
}
I thought I'd add this because I've found it necessary in the past to append values to a C array (like NSMutableArray in Objective-C). This code manages a C float array and appends values to it:
static float *arr;
static int length;
void appendFloat(float);
int main(int argc, const char * argv[]) {
float val = 0.1f;
appendFloat(val);
return 0;
}
void appendFloat(float val) {
/*
* How to manage a mutable C float array
*/
// Create temp array
float *temp = malloc(sizeof(float) * length + 1);
if (length > 0 && arr != NULL) {
// Copy value of arr into temp if arr has values
memccpy(temp, arr, length, sizeof(float));
// Free origional arr
free(arr);
}
// Length += 1
length++;
// Append the value
temp[length] = val;
// Set value of temp to arr
arr = temp;
}
may be this is simple.
#include <stdio.h>
int main()
{
int i,j,k,n,m,total,a[30],b[30],c[60];
//getting array a
printf("enter size of array A:");
scanf("%d",&n);
printf("enter %d elements \n",n);
for(i=0;i<n;++i)
{scanf("%d",&a[i]);}
//getting aaray b
printf("enter size of array b:");
scanf("%d",&m);
printf("enter %d elements \n",m);
for(j=0;j<m;++j)
{scanf("%d",&b[j]);}
total=m+n;
i=0,j=0;
//concating starts
for(i=0;i<n;++i)
{
c[i]=a[i];
}
for(j=0;j<m;++j,++n)
{
c[n]=b[j];
}
printf("printing c\n");
for(k=0;k<total;++k)
{printf("%d\n",c[k]);}
}
Here a solution to concatenate two or more statically-allocated arrays. Statically-allocated arrays are array whose length is defined at compile time. The sizeof operator returns the size (in bytes) of these arrays:
char Static[16]; // A statically allocated array
int n = sizeof(Static_array); // n1 == 16
We can use the operator sizeof to build a set of macros that will concatenate two or more arrays, and possibly returns the total array length.
Our macros:
#include <string.h>
#define cat(z, a) *((uint8_t *)memcpy(&(z), &(a), sizeof(a)) + sizeof(a))
#define cat1(z, a) cat((z),(a))
#define cat2(z, a, b) cat1(cat((z),(a)),b)
#define cat3(z, a, b...) cat2(cat((z),(a)),b)
#define cat4(z, a, b...) cat3(cat((z),(a)),b)
#define cat5(z, a, b...) cat4(cat((z),(a)),b)
// ... add more as necessary
#define catn(n, z, a ...) (&cat ## n((z), a) - (uint8_t *)&(z)) // Returns total length
An example of use:
char One[1] = { 0x11 };
char Two[2] = { 0x22, 0x22 };
char Three[3] = { 0x33, 0x33, 0x33 };
char Four[4] = { 0x44, 0x44, 0x44, 0x44 };
char All[10];
unsigned nAll = catn(4, All, One, Two, Three, Four);
However, thanks to the way we defined our macros, we can concatenate any type of objects as long as sizeof returns their size. For instance:
char One = 0x11; // A byte
char Two[2] = { 0x22, 0x22 }; // An array of two byte
char Three[] = "33"; // A string ! 3rd byte = '\x00'
struct {
char a[2];
short b;
} Four = { .a = { 0x44, 0x44}, .b = 0x4444 }; // A structure
void * Eight = &One; // A 64-bit pointer
char All[18];
unsigned nAll = catn(5, All, One, Two, Three, Four, Eight);
Using constant literals, one can also these macros to concatenate constants, results from functions, or even constant arrays:
// Here we concatenate a constant, a function result, and a constant array
cat2(All,(char){0x11},(unsigned){some_fct()},((uint8_t[4]){1,2,3,4}));
i like the answer from jon. In my case i had to use a static solution.
So if you are forced to not use dynamic memory allocation:
int arr1[5] = {11,2,33,45,5};
int arr2[3] = {16,73,80};
int final_arr[8];
memcpy(final_arr, arr1, 5 * sizeof(int));
memcpy(&final_arr[5], arr2, 3 * sizeof(int));
for(int i=0; i<(sizeof(final_arr)/sizeof(final_arr[0]));i++){
printf("final_arr: %i\n", final_arr[i]);
}
Why not use simple logic like this?
#include<stdio.h>
#define N 5
#define M (N * 2)
int main()
{
int a[N], b[N], c[M], i, index = 0;
printf("Enter %d integer numbers, for first array\n", N);
for(i = 0; i < N; i++)
scanf("%d", &a[i]);
printf("Enter %d integer numbers, for second array\n", N);
for(i = 0; i < N; i++)
scanf("%d", &b[i]);
printf("\nMerging a[%d] and b[%d] to form c[%d] ..\n", N, N, M);
for(i = 0; i < N; i++)
c[index++] = a[i];
for(i = 0; i < N; i++)
c[index++] = b[i];
printf("\nElements of c[%d] is ..\n", M);
for(i = 0; i < M; i++)
printf("%d\n", c[i]);
return 0;
}
Resultant array size must be equal to the size of array a and b.
Source: C Program To Concatenate Two Arrays

value of pointer to a char array vs plain char pointer

I am having a hard time understanding where I can use a pointer to an array,
e.g: char (*a)[10];.
So two basic questions.
Please give me a simple example of how just a pointer to an array can be used in C code.
Why would one use it as apposed to just declaring a variable as a pointer and then incrementing/decrementing the address after that point.
Say you have a database query that returns a set of strings. Further, say that you know that these strings are no longer than 9 characters in length. Only, you don't know how many elements are in the set returned by the query.
char (*a)[10] = malloc( NumRecords * sizeof *a );
if ( a == NULL )
{
/* Handle error appropriately */
return EXIT_FAILURE; /* Naive */
}
for ( i = 0 ; i < NumRecords ; ++i )
{
assert(strlen(DbRecordSet[i]) < 10);
strcpy(a[i], DbRecordSet[i]);
}
Example: how to print the elements of an array of num_row rows and 3 columns:
#include <stdio.h>
#define NUM_ROW(x) (sizeof (x) / sizeof *(x))
// print elements of an array of num_row rows and 3 columns
void print(int (*a)[3], size_t num_row)
{
size_t num_col = sizeof *a / sizeof **a;
for (int i = 0; i < num_row; i++) {
for (int j = 0; j < num_col; j++) {
printf("%d\n", a[i][j]);
}
}
}
int main(void)
{
int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
int b[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
print(a, NUM_ROW(a));
print(b, NUM_ROW(b));
return 0;
}
Any time you pass an expression with a multi-dimensioned array type to a function, you're going to be working with a pointer to an array:
int a[10][20];
foo(a);
void foo(int (*p)[20]) // or int p[][20]
{ ... }

Resources