How to append two arrays in C language? - c

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

Related

Using functions to lesser repetitiveness

I have been working on this problem for a while now: basically I need to put the for loop in a function so I can call for it, but I don't how to to make a function return a 2D array, I want to solve this by creating a 1D array, but the problem is that my task is to compute the sum of numbers under the diagonal of a matrix, so I need it to be 2D first, then it can only become 1D. Does anyone have a solution?
Maybe my thought process is just wrong and somebody could just recommend how to put the for loops in functions? If it was without the if clause inside then I might have an idea, but now I really don't.
#include <math.h>
#include <stdio.h>
#include <stdlib.h> // libraries added from example
#include <time.h>
//(*) For a square matrix calculate the sum of elements under the main diagonal excluding it.
#define A -10
#define B 10
int main() {
void enter(int *x, int *y);
int get_random(int lbound, int ubound); // telling the programs that functions are declared
int r;
int c;
int row, col, sum = 0;
enter(&r, &c); // calling the function
srand48(time(NULL)); //Call srand48 with current time reported by `time` casted to a long integer.
// srand48 is used to reinitialize the most recent 48-bit value in this storage
int array[r][c]; // we decided its gonna be r rows and c columns
int line[r * c]; // turning 2d into 1d array
for (row = 0; row < r; ++row) // we cycle numeration of rows of matrix
{
for (col = 0; col < c; col++) // we cycle numeration of columns of matrix
{
array[row][col] = get_random(B, A);// filling array with random numbers, taken from example
printf("%d ", array[row][col]);
if (row > col) { //since we want the sum numbers below the diagonal row>col must be true
sum = sum + array[row][col];// if row>col then we add the number to our sum;
};
}
printf("\n"); // this is to break line after row 1,2 col 3, so it looks nicer
}
for (row = 0; row < r; ++row) // we cycle numeration of rows of matrix
{
for (col = 0; col < c; col++) // we cycle numeration of columns of matrix
{
line[row * r + col] = array[row][col];
}
}
printf("the array in 1D: ");
for (row = 0; row < r * c; row++) {
printf("%d ", line[row]);
}
printf("\n");
printf("sum of array below the diagonal: %d\n", sum);
return 0;
}
void enter(int *x, int *y) { // we have to use pointers if we want more then one return from a function
printf("How man rows in array? "); // just like the last lab we decide how big the matrix will be
scanf("%d", x); // we use x instead of &x because we need the address of the number not the value
printf("How man columns in array? ");
scanf("%d", y); // we use y instead of &y because we need the address of the number not the value
}
int get_random(int lbound, int ubound) {
return mrand48() % (ubound - lbound + 1) + lbound; // function for generating random numbers
}
Conditions have to be met:
the user decides size of square matrix
the matrix has to be filled with random numbers
the array is called by the function has to be 1D using i*N+j, 2D array can't be passed
Let's consider your assignment
Conditions have to be met:
the user decides size of square matrix
the matrix has to be filled with random numbers
the array is called by the function has to be 1D using i*N+j, 2D
array can't be passed
Firstly the matrix must be square.
So this your function
void enter(int *x, int *y) { // we have to use pointers if we want more then one return from a function
printf("How man rows in array? "); // just like the last lab we decide how big the matrix will be
scanf("%d", x); // we use x instead of &x because we need the address of the number not the value
printf("How man columns in array? ");
scanf("%d", y); // we use y instead of &y because we need the address of the number not the value
}
does not make sense. The user can enter different values for the numbers of rows and columns of the matrix. You need to enter only one positive value.
Secondly as we are speaking about a matrix then it means that you have to define a two-dimensional array.
Also you need to write a function that will calculate the sum of elements under the main diagonal of a matrix. The function is declared such a way that it can accept only a one-dimensional array. This means that you need to pass your matrix to the function casting it to a pointer of the type int *. There is no need to create an auxiliary one-dimensional array,
Here is a demonstration program that shows how the function can be declared and defined and how the matrix can be passed to the function.
#include <stdio.h>
long long int sum_under_dioganal( const int a[], size_t n )
{
long long int sum = 0;
for (size_t i = 1; i < n; i++)
{
for (size_t j = 0; j < i; j++)
{
sum += a[i * n + j];
}
}
return sum;
}
int main( void )
{
enum { N = 5 };
int a[N][N] =
{
{ 0, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 0 },
{ 2, 3, 0, 0, 0 },
{ 4, 5, 6, 0, 0 },
{ 7, 8, 9, 10, 0 }
};
printf( "sum of elements under the main diagonal = %lld\n",
sum_under_dioganal( ( int * )a, N ) );
}
The program output is
sum of elements under the main diagonal = 55
Another approach to define the function and call it is the following
#include <stdio.h>
long long int sum_under_dioganal( const int a[], size_t n )
{
long long int sum = 0;
size_t m = 0;
while (m * m < n) ++m;
if (m * m == n)
{
for (size_t i = 1; i < m; i++)
{
for (size_t j = 0; j < i; j++)
{
sum += a[i * m + j];
}
}
}
return sum;
}
int main( void )
{
enum { N = 5 };
int a[N][N] =
{
{ 0, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 0 },
{ 2, 3, 0, 0, 0 },
{ 4, 5, 6, 0, 0 },
{ 7, 8, 9, 10, 0 }
};
printf( "sum of elements under the main diagonal = %lld\n",
sum_under_dioganal( ( int * )a, N * N ) );
}
The program output is the same as shown above.
sum of elements under the main diagonal = 55
2d arrays don't really exist. The compiler just allows you to write a[i][j] so that you can believe in them. Here's some simple code to demonstrate a few methods:
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
void *
make_array(size_t size)
{
int *a = malloc(sizeof *a * size * size);
int *t = a;
if( a == NULL ){
perror("malloc");
exit(1);
}
for( int row = 0; row < size; row += 1 ){
for( int col = 0; col < size; col += 1 ){
*t++ = rand() % 32 - 16;
}
}
return a;
}
int
trace(void *v, size_t s)
{
int *a = v;
int sum = 0;
for( size_t i = 0; i < s; i += 1 ){
sum += *a;
a += s + 1;
}
return sum;
}
int
main(int argc, char **argv)
{
srand(time(NULL));
size_t s = argc > 1 ? strtol(argv[1], NULL, 0) : 5;
void *v = make_array(s);
/* a, b, c, and d will demonstrate different access techniques */
int *a = v; /* a is the conventional "1-d array" (1)*/
int (*b)[s] = v; /* b is a "two-d" array */
int *c = v; /* c iterates through each element */
int *d = v; /* d treats each row as a 1-d array */
for( int i = 0; i < s; i += 1 ){
for( int j = 0; j < s; j += 1 ){
printf("%3d ", b[i][j]);
assert( a[i * s + j] == b[i][j] );
assert( *c == b[i][j] );
assert( d[j] == b[i][j] );
c += 1;
}
d += s;
putchar('\n');
}
printf("trace: %d\n", trace(v, s));
}
/* (1) These comments are not strictly accurate. `a` is *not* an
* array, and `b` is *not* a 2-d array. `a` is a pointer, and `b` is
* an array of pointers. Arrays are not pointers, and pointers are
* not arrays.
*/

Keeping two arrays in the same ordering when sorting

I have an integer array that I need to sort containing unix times. I was going to use qsort to sort it which is fairly trivial. However I also have an array of "strings" that needs to remain in the same order as the integer array.
So position 2 in the integer array would correspond with an element in position two of the other array.
Is there anyway using qsort to maintain such a relationship?
Do it like this
#include <stdlib.h>
#include <stdio.h>
struct Data
{
long int time;
const char *string;
};
int
datacmp(const void *const x, const void *const y)
{
return ((struct Data *) x)->time - ((struct Data *) y)->time;
}
int
main(void)
{
struct Data array[] = {
{1234, "1234 Text"},
{1034, "1034 Text"},
{1041, "1041 Text"}
};
size_t count;
count = sizeof(array) / sizeof(array[0]);
for (size_t i = 0 ; i < count ; ++i)
{
fprintf(stderr, "Entry %zu:\n\ttime : %ld\n\tstring: %s\n\n",
i, array[i].time, array[i].string);
}
fprintf(stderr, "\n");
qsort(array, count, sizeof(array[0]), datacmp);
fprintf(stderr, "---- Sorted array:\n");
for (size_t i = 0 ; i < count ; ++i)
{
fprintf(stderr, "Entry %zu:\n\ttime : %ld\n\tstring: %s\n\n",
i, array[i].time, array[i].string);
}
return 0;
}
A more generic solution that actually sorts 2 (or more) arrays, according to one of the arrays, by sorting an array of pointers to the key array, then reordering all of the arrays to sort them (it also restores the array of pointers back to their initial state). The compare function only needs to know the type that the pointers point to. The reorder in place takes O(n) (linear) time as every move places a value in it's final sorted location. In this example, a[] is an array of integers, b[] is an array of pointers to strings (char *).
int compare(const void *pp0, const void *pp1)
{
int i0 = **(int **)pp0;
int i1 = **(int **)pp1;
if(i0 > i1)return -1;
if(i0 < i1)return 1;
return 0;
}
/* ... */
int *pa = malloc(...); /* array of pointers */
int ta; /* temp value for a */
char *tb; /* temp value for b */
/* ... */
/* initialize array of pointers to a[] */
for(i = 0; i < sizeof(a)/sizeof(a[0]); i++)
pa[i] = &a[i];
/* sort array of pointers */
qsort(pa, sizeof(a)/sizeof(a[0]), sizeof(pa[0]), compare);
/* reorder a[] and b[] according to the array of pointers */
for(i = 0; i < sizeof(a)/sizeof(a[0]); i++){
if(i != pa[i]-a){
ta = a[i];
tb = b[i];
k = i;
while(i != (j = pa[k]-a)){
a[k] = a[j];
b[k] = b[j];
pa[k] = &a[k];
k = j;
}
a[k] = ta;
b[k] = tb;
pa[k] = &a[k];
}
}

how to compare two arrays in c?

I am creating a function which can compare two arrays. It returns 1 when they are the same and return 0 when they are not.
It required the program run as linear time, so i cannot use a for-for loop to compare it. Any suggestions for me?
Examples of arrays for which scrambled should return 1:
a = {10,15,20}, b = {10,15,20}
a = {1,2,3,4,5}, b = {5,3,4,2,1}
a = {}, b = {} (i.e. len = 0)
a = {2,1,3,4,5}, b = {1,2,4,3,5}
Examples of arrays for which scrambled should return 0:
a = {1,1}, b = {1,2}
a = {10,15,20}, b = {10,15,21}
a = {1,2,3,4,5}, b = {5,3,4,2,2}
If you can specify a maximum value for the array elements, you can compare them in linear time pretty easily, by just looping through each one and counting the values which are present, like so:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAX_ARRAY_VALUE 100
bool compare_arrays(int * arr1, size_t arr1_size,
int * arr2, size_t arr2_size)
{
/* Set up array to count elements */
int * table = calloc(MAX_ARRAY_VALUE + 1, sizeof * table);
if ( !table ) {
perror("couldn't allocate memory");
exit(EXIT_FAILURE);
}
/* Increment index if element is present in first array... */
for ( size_t i = 0; i < arr1_size; ++i ) {
table[arr1[i]]++;
}
/* ...and decrement index if element is present in second array. */
for ( size_t i = 0; i < arr2_size; ++i ) {
table[arr2[i]]--;
}
/* If any elements in array are not zero, then arrays are not equal */
for ( size_t i = 0; i < MAX_ARRAY_VALUE + 1; ++i ) {
if ( table[i] ) {
free(table);
return false;
}
}
free(table);
return true;
}
int main(void) {
int a1[] = {10, 20, 30, 10};
int a2[] = {20, 10, 10, 30};
int a3[] = {1, 4, 5};
int a4[] = {1, 3, 5};
if ( compare_arrays(a1, 4, a2, 4) ) {
puts("a1 and a2 are equal"); /* Should print */
}
else {
puts("a1 and a2 are not equal"); /* Should not print */
}
if ( compare_arrays(a3, 3, a4, 3) ) {
puts("a3 and a4 are equal"); /* Should not print */
}
else {
puts("a3 and a4 are not equal"); /* Should print */
}
if ( compare_arrays(a1, 4, a4, 3) ) {
puts("a1 and a4 are equal"); /* Should not print */
}
else {
puts("a1 and a4 are not equal"); /* Should print */
}
return 0;
}
which outputs:
paul#horus:~/src/sandbox$ ./lincmp
a1 and a2 are equal
a3 and a4 are not equal
a1 and a4 are not equal
paul#horus:~/src/sandbox$
Without specifying the maximum value, you can loop through each array and find the maximum. It'll still be linear time, but without an upper bound you might end up with a huge index table.
Because the comparison of the two arrays is independent of the order of the elements, both must be sorted before they can be compared. Because of this, you can't do this in linear time. The best you can do is O(n log n), as that is the best order of most sorting algorithms.
My C is pretty rusty so the may be some memory problem with the script below. However, the basic task is to sort the 2 arrays, compare them element by element. If they all match, scramble should return 1, other it's 0.
The script below works with GCC, haven't tested it with any other compiler. It compares arrays of equal length. The case of unequal length is left for the OP as an minor exercise.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int compare_ints(const void * a , const void * b)
{
const int * ia = (const int *)a;
const int * ib = (const int *)b;
return *ia > *ib;
}
int scramble(const int * a, const int * b, unsigned int len)
{
int * sorted_a = malloc(len * sizeof(int));
int * sorted_b = malloc(len * sizeof(int));
memcpy(sorted_a, a, len * sizeof(int));
memcpy(sorted_b, b, len * sizeof(int));
qsort(sorted_a, len, sizeof(int), compare_ints);
qsort(sorted_b, len, sizeof(int), compare_ints);
for (int i = 0; i < len; i++)
{
if (sorted_a[i] != sorted_b[i])
{
free(sorted_a);
free(sorted_b);
return 0;
}
}
free(sorted_a);
free(sorted_b);
return 1;
}
int main (int argc, char const *argv[])
{
int a[3] = {20, 10, 15};
int b[3] = {10, 15, 20};
int is_equal = scramble(a, b, 3);
printf("is_equal = %i\n", is_equal);
return 0;
}
FYI: you can't do it in linear time. qsort has O(n log n).
At a certain extent, you can obtain the sum of all the hashed values of the first array, and compare it to the sum of the hashed values of the second array. It'll work, but I don't know precise it is.
Here is my attempt, all my tests have given positive results so far :
#include <stdio.h>
unsigned int hash(unsigned int x) {
x = ((x >> 16) ^ x) * 0x45d9f3b;
x = ((x >> 16) ^ x) * 0x45d9f3b;
x = ((x >> 16) ^ x);
return x;
}
int compareArrays(int *arr1, int *arr2, int size) {
if (size == 0) return 1;
unsigned long sum1 = 0;
unsigned long sum2 = 0;
for (int i = 0; i < size; ++i) {
sum1 += hash(arr1[i]);
}
for (int i = 0; i < size; ++i)
sum2 += hash(arr2[i]) ;
return sum1 == sum2;
}
int main(void) {
int a[] = {1,2,3,4,5,6,7,8,255};
int b[] = {1,2,3,4,5,6,7,8,9};
int size = 9;
printf("Are they the same? %s.\n", compareArrays(a, b, size) ? "yes" : "no");
return 0;
}
You can use memcmp function with this format:
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
For example;
/* memcmp example */
#include <stdio.h>
#include <string.h>
int main ()
{
char buffer1[] = "abcde";
char buffer2[] = "abcde";
int n;
n=memcmp ( buffer1, buffer2, sizeof(buffer1) );
if (n>0) printf ("'%s' is greater than '%s'.\n",buffer1,buffer2);
else if (n<0) printf ("'%s' is less than '%s'.\n",buffer1,buffer2);
else printf ("'%s' is the same as '%s'.\n",buffer1,buffer2);
return 0;
}
output is:
'abcde' is same as 'abcde'.

keeping track of the original indices of an array after sorting in C

I have an array let's say A[5], the 5 elements are 5,4,1,2,3. Now I sort these arrays in ascending order. so the resulting array will now be 1,2,3,4,5. I use qsort() function of stdlib.h to sort this. The question is how can I get the indices of the original array with respect to my new array. originally my indices were 0,1,2,3,4 for corresponding values of 5,4,1,2,3 and now the indices have changed to 2,3,4,1,0. How can I get these indices efficiently in C? Thank you in advance(please write the code if possible)
There is also a method as follows under limited conditions.
#include <stdio.h>
int main(void){
int data[] ={ 5,4,1,2,3 }; //Without duplication, The number of limited range.
int size = sizeof(data)/sizeof(*data);
int keys[size];
int i;
printf("data :\n");
for(i=0;i<size;i++){
printf("%d ",data[i]);
}
for(i=0;i<size;i++){
keys[data[i]-1]=i;
}
printf("\n\ndata\tindex\n");
for(i=0;i<size;i++){
printf("%d\t%d\n", data[keys[i]], keys[i]);
}
return 0;
}
/* result sample
data :
5 4 1 2 3
data index
1 2
2 3
3 4
4 1
5 0
*/
How to sort an array of index #Kerrek is as proposed.
#include <stdio.h>
#include <stdlib.h>
int *array;
int cmp(const void *a, const void *b){
int ia = *(int *)a;
int ib = *(int *)b;
return array[ia] < array[ib] ? -1 : array[ia] > array[ib];
}
int main(void){
int data[] ={ 5,4,1,2,3 };
int size = sizeof(data)/sizeof(*data);
int index[size];//use malloc to large size array
int i;
for(i=0;i<size;i++){
index[i] = i;
}
array = data;
qsort(index, size, sizeof(*index), cmp);
printf("\n\ndata\tindex\n");
for(i=0;i<size;i++){
printf("%d\t%d\n", data[index[i]], index[i]);
}
return 0;
}
Take a 2D array. Store the numbers is first column and then corressponding indexes in second column. You can write your comparator function as:
int compare ( const void *pa, const void *pb )
{
const int *a = pa;
const int *b = pb;
if(a[0] == b[0])
return a[1] - b[1];
else
return a[0] - b[0];
}
Call to qsort should be:
qsort(array, n, sizeof array[0], compare); // n is representing rows
See the Live Demo
Based on Kerrek SB's brilliant idea I made an implementation that works for any array type by providing its element size and a comparator function for that type.
_Thread_local uint8_t *array_to_order;
_Thread_local size_t elem_size_to_order;
_Thread_local int (*cmp_for_ordering)(const void *, const void *);
int cmp_array_entry(const size_t *a, const size_t *b)
{
return cmp_for_ordering(&array_to_order[*a * elem_size_to_order], &array_to_order[*b * elem_size_to_order]);
}
size_t *make_order_index_array(void *array, size_t *order, size_t elem_count, size_t elem_size, int (*cmp)(const void *, const void *))
{
// If order is provided by the caller it should have suitable contents, such as when updating an order
// Initialise the order array if not already provided
if (order == NULL)
{
order = calloc(elem_count, sizeof(size_t));
// Initialise the order array to the unsorted indices
for (size_t i=0; i < elem_count; i++)
order[i] = i;
}
// Globals used by the comparison function to order the array
array_to_order = array;
elem_size_to_order = elem_size;
cmp_for_ordering = cmp;
// Order the order array
qsort(order, elem_count, sizeof(size_t), cmp_array_entry);
return order;
}
_Thread_local is something that we should be able to take for granted for writing such code when we're forced to use globals but should worry about thread safety. Mine is defined with the following macros:
#if defined(_MSC_VER) && !defined(_Thread_local)
#define _Thread_local __declspec(thread)
#endif
#if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201102L)) && !defined(_Thread_local)
#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
#define _Thread_local __thread
#endif
#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && (((__GNUC__ << 8) | __GNUC_MINOR__) < ((4 << 8) | 9))
#define _Thread_local __thread
#endif
#include <limits.h>
#include <stdio.h>
#define SIZE 5
int* sortArrayNKeepIndices(int arr[], int arrSize){
static int indexArr[SIZE];
int arr2[arrSize];
for (int i = 0; i < arrSize; i++) {
indexArr[i] = 0;
arr2[i] = arr[i];
}
int min = 0, temp = 0;
for (int i = 0; i < arrSize ; i++)
{
min = i; // record the position of the smallest
for (int j = i + 1; j < arrSize; j++)
{
// update min when finding a smaller element
if (arr[j] < arr[min])
min = j;
}
// put the smallest element at position i
temp = arr[i];
arr[i] = arr[min];
arr[min] = temp;
} // array sorting ends here
int ctr = 0;
while ( ctr < arrSize) {
min = 0; // restart from first element
for (int j = 0; j < arrSize; j++)
{
if (arr2[j] == INT_MAX) continue; // ignore already marked as minimum indices
// update min when finding a smaller element
if (arr2[j] < arr2[min])
min = j;
}
indexArr[ctr] = min; // updating indexArr with the index of the next minimum
arr2[min] = INT_MAX; // marking minimum element to be ignored next time
ctr++;
} //keeping track of previous indices of the array elements ends here
return indexArr;
} // function sortArrayKeepIndices ends here
int main () {
int arr[SIZE] = {16, 15, 12, 10, 13};
int* ptr = sortArrayNKeepIndices(arr, SIZE);
for (int dex = 0; dex < SIZE; dex++){
printf("%d (%d, %d)\t", arr[dex], * (ptr + dex), dex);}
}
// output will be 10 (3, 0) 12 (2, 1) 13 (4, 2) 15 (1, 3) 16 (0, 4)
// element (old index, new index)

C Malloc Multidimensional Char Array

I would like to dynamically allocate (malloc) a multidimensional character array in C. The array would have the following format:
char *array[3][2] = {
{"one","two"},
{"three","four"},
{"five","six"}
};
Before the array would be created, I would already know the number of rows and the lengths of all of the characters arrays in the multidimensional array.
How would I malloc such a character array?
Thanks in advance!
This is one way to allocate a two dimensional array of char *.
Afterwards, you can assign the contents like a[1][2] = "foo";
Note that the elements of the array are initialized to (char *)0.
#include <stdio.h>
#include <stdlib.h>
char ***alloc_array(int x, int y) {
char ***a = calloc(x, sizeof(char **));
for(int i = 0; i != x; i++) {
a[i] = calloc(y, sizeof(char *));
}
return a;
}
int main() {
char ***a = alloc_array(3, 2);
a[2][1] = "foo";
printf("%s\n", a[2][1]);
}
[Charlies-MacBook-Pro:~] crb% cc xx.c
[Charlies-MacBook-Pro:~] crb% a.out
foo
First of all, arrays are typically stored in Row Major form, so in reality you have a vector six elements long, each entry is a char * ptr. That is, the elements labelled by row, column are similar to:
char *r1c1, *r1c2, *r2c1, *r2c2, *r3c1, *r3c1;
Thus, do a SIMPLE malloc of:
char *matrix = malloc(3*2*sizeof(char *));
Then set the elements as:
matrix[0] = "one";
matrix[1] = "two";
matrix[2] = "three";
matrix[3] = "four";
matrix[4] = "five";
matrix[5] = "six";
Finally, to test this write a nested loop as:
for (int r=0; r<3; r++)
{
for (int c=0; c<2; c++);
{
printf("%s\n",matrix[r][c]);
}
}
Note, how a matrix is treated first as a vector then as a matrix. C doesn't care!!
char *array[3][2] is nothing but a two dimensional array of pointers. Hence you need the storage space of 3*2*sizeof(char *) to store the pointers.
As you mentioned, the pointers are actually pointing to zero-terminated strings and you may like the strings to be malloc'ed as well. Assuming the total length of all the strings to be N (including zero-termination), the storage space needed is (3*2*sizeof(char *) + N).
Allocate memory for the above mentioned size and the copy the strings yourselves as below.
In the following code, we assume that the number of columns (2) is a constant
char *(*dst)[2] = (char *(*)[2]) malloc(3*2*sizeof(char *) + N);
char * s = ((char *) dst) + (3*2*sizeof(char *));
for (i = 0; i < 3; i++)
{
for (j = 0; j < 2; j++)
{
strcpy(s, src[i][j]);
dst[i][j] = s;
s += strlen(s)+1;
}
}
NOTE: In the above code, 'dst' is a pointer that points to the first row of the 2D array of char *.
If the number of columns is not constant, the syntax changes a bit, but the storage size is the same.
char **dst = (char **) malloc(3*2*sizeof(char *) + N);
char * s = ((char *) dst) + (3*2*sizeof(char *));
for (i = 0; i < 3; i++)
{
for (j = 0; j < 2; j++)
{
strcpy(s, src[i][j]);
dst[i*2 + j] = s; /* 2 is the number of columns */
s += strlen(s)+1;
}
}
NOTE: Here 'dst' is a pointer that points to the first element of 1D array of char * and the 2D indexing is done manually.
The above examples assume that the string lengths will not change after allocation. If the strings can change at any point in time after allocation, then it is better to allocate for each string separately.
Keep it simple, Sheldon. The answer you've selected uses a char ***, which is not even close to the equivalent of a char *[2][3]. The difference is in the number of allocations... An array only ever requires one.
For example, here's how I'd retro-fit the answer you selected. Notice how much simpler it is?
#include <stdio.h>
#include <stdlib.h>
void *alloc_array(size_t x, size_t y) {
char *(*a)[y] = calloc(x, sizeof *a);
return a;
}
int main() {
char *(*a)[2] = alloc_array(3, 2);
a[2][1] = "foo";
printf("%s\n", a[2][1]);
}
In case you arrive in this page, wanting to create an array like int myarray[n][M] (which is slighly different from the question since they want an array of string), where M is fixed and n can vary (for example if you want an array of coordinates...), then you can just do:
int (*p)[M] = malloc(n*sizeof *p);
and then use p[i][j] as before. Then, you will get sizeof p[i] = M*sizeof(int):
#include <stdio.h>
#include <stdlib.h>
#define M 6
int main(int argc, char *argv[])
{
int n = 4;
int (*p)[M] = malloc(n*sizeof *p);
printf("Size of int: %lu\n", sizeof(int));
printf("n = %d, M = %d\n", n, M);
printf("Size of p: %lu (=8 because pointer in 64bits = 8 bytes)\n", sizeof p);
printf("Size of *p: %lu (=M*sizeof(int) because each case is an array of length M)\n", sizeof *p);
printf("Size of p[0]: %lu (=M*sizeof(int) because each case is an array of length M)\n", sizeof p[0]);
// Assign
for (int i=0; i<n; i++) {
for (int j=0; j<M; j++) {
(p[i])[j] = i*10+j;
}
}
// Display
for (int i=0; i<n; i++) {
for (int j=0; j<M; j++) {
printf("%2d; ", (p[i])[j]);
}
printf("\n");
}
return 0;
}
which gives:
Size of int: 4
n = 4, M = 6
Size of p: 8 (=8 because pointer in 64bits = 8 bytes)
Size of *p: 24 (=M*sizeof(int) because each case is an array of length M)
Size of p[0]: 24 (=M*sizeof(int) because each case is an array of length M)
0; 1; 2; 3; 4; 5;
10; 11; 12; 13; 14; 15;
20; 21; 22; 23; 24; 25;
30; 31; 32; 33; 34; 35;

Resources