Lets say I have two arrays, A[5] and B[3]. I want to create another array C[8] that will contain all the elements from A and B. First it will store A elements and then B. I am a beginner in C. So anyone can help?
You can use memcpy. Below I have assumed these are arrays of ints, but you could replace sizeof(int) with the type you are actually doing.
memcpy(C, A, 5 * sizeof(int));
memcpy(C + 5, B, 3 * sizeof(int));
The first line says copy 5 ints from the start of A to the start of C. The second line says copy 3 ints from the start of B to C starting at index 5.
Edit: As pointed out in the comments, I overcomplicated this. You can use the following and not have to worry about types:
memcpy(C, A, 5 * sizeof(C[0]));
memcpy(C + 5, B, 3 * sizeof(C[0]));
You can achieve this with two for loops. First copy the content from A to C:
for(int i = 0; i < 5; i++)
C[i] = A[i];
And then, copy the content of B to C, from the position where you inserted the last element of A:
for(int i = 5; i < 8; i++)
C[i] = B[i-5];
Note that the loop now starts with 5 and ends in 8, this is because we want to start copying the values of B into C after the positions already filled with the values of A. The position of B where we are reading is i - 5, which gives the positions 0, 1, 2... for B. We are doing this here because the loop starts in 5.
You can also do this with just one for loop in the following way:
for(int i = 0; i < 5; i++){
C[i] = A[i];
if(i < 3)
C[i+5] = B[i];
}
universal function
void *copy(void * restrict dest, const void * restrict src, const void * restrict src1, const size_t len1, const size_t len2, const size_t elemsize)
{
unsigned char *restrict ucdest = dest;
if(dest && src && src1)
{
memcpy(ucdest, src, elemsize * len1);
memcpy(ucdest + elemsize * len1, src1, elemsize * len2);
}
return dest;
}
Related
I have done something by looking to the internet but something is missing here is my code
void draw_way(int *arr,int lenght_row,int lenght_column) {
int s1 = 0, s2 = 0;
for (s1 = 0; s1 < lenght_row; s1++)
{
for (s2 = 0; s2 < lenght_column; s2++) {
if (*((arr + s1 * lenght_row) + s2) == 1)
{
printf("S");
}
else if (*((arr + s1 * lenght_row) + s2) == 2)
{
printf("G");
}
else if(*((arr + s1 * lenght_row) + s2) == 3)
{
printf("#");
}
else if (*((arr + s1 * lenght_row) + s2) == 4)
{
printf(".");
}
}
printf("\n");
}
it is actually printing a maze but is is not important. The thing I want to understand is why ı had to use *((arr + s1 * lenght_row) + s2) why this is not working if ı use *(*(arr+s1)+s2) what 'lenght_row' does.
For any array or pointer arr and index i, the expression *(arr + i) is exactly equal to arr[i].
If we do this translation for *(*(arr+s1)+s2) that would be (arr[s1])[s2] (or arr[s1][s2]). Since arr isn't a pointer to a pointer (or array of arrays) then arr[s1][s2] doesn't make sense.
Instead you kind of emulate a 2d array (array of arrays) using a array (whose first element is pointed to by arr) and use arithmetic to calculate the single index into this array.
This is very common for dynamically allocated memory, where instead of using a jagged array (using pointers to pointers) you use a single contiguous area or memory.
It might be easier to understand with an illustration...
Lets say we want a 2d array of 2 by 3 elements. We can create it using dynamic allocation as a jagged array:
int **arr;
arr = malloc(2 * sizeof *arr); // First dimension
for (size_t i = 0; i < 2; ++i)
arr[i] = malloc(3 * sizeof *arr[i]); // Second dimension
Since we have multiple allocations, there's no locality in the array, arr[0][2] might not be followed by arr[1][0]. Locality and having the 2d array being contiguous could be good for some algorithm and use-cases.
A contiguous 2d array would be an array of arrays like
int arr[2][3];
but this is harder to handle dynamically, so instead we allocate a single contiguous memory area of 2 * 3 elements:
int *arr;
arr = malloc(2 * 3 * sizeof *arr);
Unfortunately this can't be indexed in the same intuitive way as a jagged array or array of arrays (i.e. arr[0][1] isn't possible). But with some clever arithmetic it is possible: arr[row_index * row_length + column_index] will be like arr[row_index][column_index] (for a jagged array or array of arrays).
arr is a flat array, not a multi-dimensional array. It emulates a mult-dimensional array by way of passing in the grid size. So, if it was 5x2, then arr as a flat array would be 10 integers long, not an array of 5 rows of another array of 2 columns.
Hence, it uses simple pointer arithmetic to emulate the r,c dimensions by way of the flat array index calculation
((arr + s1 * lenght_row) + s2)
if you reduce number of paranthises it will easier to understand: if (*(arr + s1 * lenght_row + s2) == 2)
2D array has c columns and r rows. They are stored in the memory continuously row0 then row 1 them row2 ...
So to access the particular element (row, column) you need multiply row by 'r' (whics is how many elements we hae in the row and add column.
For starters the expression in if-else statements like this
if (*((arr + s1 * lenght_row) + s2) == 1)
is incorrect. There should be
if (*((arr + s1 * lenght_column) + s2) == 1)
The parameter arr declared like
int *arr
has the type int *. So dereferencing the pointer like *arr you will get an object of the type int for which you may not apply the dereferncing operator.
So this expression
*(*(arr+s1)+s2)
is incorrect. The sub-expression *(arr+s1) has the type int. So the second use of the operator * produce a compilation error.
In the shown function there is emulated a two dimensional array using a pointer to a one-dimensional array. That is the one-dimensional array is logically split into chunks by length_column elements.
Here is a demonstrative program.
#include <stdio.h>
#define ROW_LENGTH 2
#define COLUMN_LENGTH 3
void display( const int *arr, size_t row_length, size_t column_length )
{
for ( size_t i = 0; i < row_length; i++ )
{
for ( size_t j = 0; j < column_length; j++ )
{
printf( "%d ", *( arr + i * column_length + j ) );
}
putchar( '\n' );
}
}
int main(void)
{
int arr[ROW_LENGTH * COLUMN_LENGTH] = { 1, 2, 3, 4, 5, 6 };
display( arr, ROW_LENGTH, COLUMN_LENGTH );
return 0;
}
Its output is
1 2 3
4 5 6
I am learning C, and I came across this problem I can't figure it out. Write a function that computes the element of an integer array a plus 6 modulus 10 and store the result in array b. For example, if 5 is the second element of array a, then the second element of array b should be (5+6)%10, which is 1. The function has the following prototype, n is the length of the arrays, a and b are the integer arrays.
I did:
void arithmetic (int *a, int n, int *b)
{
int *arr1; arr1=a; int *arr2; arr2=b;
int i;
for(i = 0; i < n; i++) {
*arr1 = *(((a + i) + 6) % 10);
*arr2 = *arr1;
}
}//don't know if the function is correct.
A couple things:
No need to update the actual content of the first array (which fixes the error pointed out about your code always storing the result in the first element of a)
Use some parens to make sure you get the right order of operations.
void newArr(int *a, int n, int *b) {
int *arr1; arr1 = a; int *arr2; arr2 = b;
for (int i = 0; i < n; i++) {
*(arr2 + i) = (*(arr1 + i) + 6) % 10;
}
}
Think about your title "...using Pointer arithemtic". You need to add the loop counter to the array pointer for both arr1 and arr2 so that it steps through each element of each array: *(arr2 + i) and *(arr1 + i).
This is also a good place to reinforce the fact that the pointers are passed by value and that the function receives copy of each pointer which it is free to iterate with to affect the copy without effecting the pointers in the caller. So it would also be perfectly valid to do:
void arithmetic (int *a, int *b, size_t n)
{
if (!a || !b)
return;
for(size_t i = 0; i < n; i++, a++, b++)
*b = (*a + 6) % 10;
}
(good job Pablo with the use of size_t for the length (or number of elements) parameter)
No, your function is not correct.
*arr1 = *((a+i)+6)%10);
You are only writing the values in the first element of the array.
arr1 points to a which already has the values. You want to do the
calculation with a value stored in a and then save it to b, so don't modify
a.
*((a+i+6)%10) is completely wrong. a+i+6 is the same as &a[i+6]. The %10
applies to the value &a[i+6] (which is the address of the i+6th element), and returns a value between 0 and 9 (let's call
it x). When do *(x) you are interpreting the x as a pointer and it
dereferences (=access the value through the pointer) it, but this is not a valid
address at all. You will also eventually access a out of bounds.
*arr2 = *arr1; here you also only storing the values in the first element of arr2.
You function has no name.
int *arr1; arr1=a; this is unnecessary, you can access a directly, no
need to create a copy of the pointer.
The +6 % 10 rule applies to the values stored in the array, not the indices.
The correct function should look like this:
void compute(int *a, int *b, size_t len)
{
if(a == NULL || b == NULL)
return;
for(size_t i = 0; i < len; ++i)
b[i] = (a[i] + 6) % 10;
}
And if your assignment says you should do it with pointer arithmetic instead of
using array indexing:
void compute(int *a, int *b, size_t len)
{
if(a == NULL || b == NULL)
return;
for(size_t i = 0; i < len; ++i)
*(b+i) = (*(a + i) + 6) % 10;
}
I have a 2 dimensional array that I am trying to sort in ascending order. For example, say the array looks like this:
4, 5
2, 6
7, 2
8, 4
I would like it to look like this:
2, 6
4, 5
7, 2
8, 4
The code that I have so far:
int temp = 0;
for(int m = 0; m<=nonZeroLength-1; m++){
for(int n = m+1; n<=nonZeroLength-1; n++){
if(nonZeroScoreSorcting[m] > nonZeroScoreSorcting[m+1]){
temp = nonZeroScoreSorcting[m];
strcpy(nonZeroScoreSorcting[m], nonZeroScoreSorcting[n]);
strcpy(nonZeroScoreSorcting[n], temp);
}
}
}
Assume that nonZeroLength has a value of 4 for this example. I am using strcpy() because I read that that is the only way to change elements of an array in C. When I run the program I get the following error:
passing argument 1 of ‘strcpy’ from incompatible pointer type [-Wincompatible-pointer-types]
I have also tried the regular assign method:
if(nonZeroScoreSorcting[m] > nonZeroScoreSorcting[m+1]){
temp = nonZeroScoreSorcting[m];
nonZeroScoreSorcting[m] = nonZeroScoreSorcting[n];
nonZeroScoreSorcting[n] = temp;
}
If you do in fact have a 2D array of int as you indicate, the key to sorting the array by row is understanding that during the sort, you will need to swap rows, not simply values. This is how you preserve the row-wise relationship during the sort.
You cannot do that treating each row of int as a string and attempting a row-wise copy using strcpy. This will result in Undefined Behavior when strcpy accesses values in the src argument outside the array bounds looking for a nul-terminating character that isn't present.
(though technically, providing a properly sized array for each src and dest and sizing 'n' in strncpy to copy 2 * sizeof(int) bytes can copy rows by virtue of limiting the read to n chars where no nul-terminating character is present -- but DON'T do it -- that's what memcpy (or memmove) is for).
Though the recommended way to sort in C is using the qsort function provided in stdlib.h, you can provide whatever sort algorithm you want. It will likely not be anywhere close to the efficiency of qsort, and certainly will be nowhere near as thoroughly tested. A simple row-sort using the slow old insertion sort could be done as follows:
#include <stdio.h>
#include <string.h>
int main (void) {
int a[][2] = {{ 4, 5 },
{ 2, 6 },
{ 7, 2 },
{ 8, 4 }},
n = sizeof a / sizeof *a,
col = sizeof *a / sizeof **a;
for (int i = 0; i < n; i++) /* insertion sort of a by row */
for (int j = i; j > 0 && *a[j] < *a[j-1]; j--) {
int tmp[col]; /* temporary VLA */
memcpy (tmp, a[j], sizeof *a);
memcpy (a[j], a[j-1], sizeof *a);
memcpy (a[j-1], tmp, sizeof *a);
}
for (int (*p)[2] = a; p < a + n; p++) /* output results */
printf ("%d, %d\n", (*p)[0], (*p)[1]);
return 0;
}
Example Use/Output
$ ./bin/inssort2d
2, 6
4, 5
7, 2
8, 4
With qsort most new C programmers are stumped by having to write a compare function to pass to qsort to let it do its job. It is really not that difficult at all. You know qsort will pass pointers to two of whatever you are sorting as arguments to your compare function.
In this case you will be sorting rows of integers (1D arrays of integers) based on the first element of each row. So qsort will compare two int * (pointers to int). You only care about the first element in each array (which you can obtain simply by dereferencing the pointer). A compare here can be a simple:
int cmp (const void *a, const void *b)
{
/* (a > b) - (a < b) */
return (*(int *)a > *(int *)b) - (*(int *)a < *(int *)b);
}
(note: by using the result of the two inequalities you protect against over/underflow that could occur if you simply returned the result of a subtraction alone).
The complete qsort implementation would be:
#include <stdio.h>
#include <stdlib.h>
int cmp (const void *a, const void *b)
{
/* (a > b) - (a < b) */
return (*(int *)a > *(int *)b) - (*(int *)a < *(int *)b);
}
int main (void) {
int a[][2] = {{ 4, 5 },
{ 2, 6 },
{ 7, 2 },
{ 8, 4 }},
n = sizeof a / sizeof *a;
qsort (a, n, sizeof *a, cmp); /* qsort array of pointers */
for (int (*p)[2] = a; p < a + n; p++) /* output results */
printf ("%d, %d\n", (*p)[0], (*p)[1]);
return 0;
}
(output is the same)
Look over both methods and know that qsort is the preferred method, but for learning, there is nothing wrong with doing it by hand to gain experience. Let me know if you have further questions.
I'm trying to make a generic quicksort function, and I fail to understand what's wrong with what I'm doing, because it's not working properly.
Here is my code:
typedef bool (*CmpFunction)(void*, void*);
void swap(void *c1, void *c2)
{
assert(c1 && c2);
int c = *(int*)c1;
*(int*)c1 = *(int*)c2;
*(int*)c2 = c;
}
void quick_sort(void* a, int n, CmpFunction swap)
{
int p, b = 1, t = n - 1;
if (n < 2)
return;
swap((char*)a, (char*)a+n/2);
p = *(int*)a;
while(b <= t) {
while(t >= b && (char*)a + t >= p )
t--;
while(b <= t && (char*)a + b < p)
b++;
if ( b < t)
swap((char*)a+(b++), (char*)a+(t--));
}
swap((char*)a, (char*)a+t);
quick_sort(a, t, swap);
n=n-t-1;
quick_sort(a + t + 1, n, swap);
}
While the original quicksort function, without me trying to make it generic is:
void quick_sort(int a[], int n)
{
int p, b = 1, t = n - 1;
if (n < 2)
return;
swap(&a[0], &a[n/2]);
p = a[0];
while(b <= t) {
while(t >= b && a[t] >= p )
t--;
while(b <= t && a[b] < p)
b++;
if ( b < t)
swap(&a[b++], &a[t--]);
}
swap(&a[0], &a[t]);
quick_sort(a, t);
n=n-t-1;
quick_sort(a + t + 1, n);
}
void swap(int *c1, int *c2)
{
int c = *c1;
*c1 = *c2;
*c2 = c;
}
I'm using this main():
int main(){
char b[] = {'a','t','b','c','y','s'};
int c[] = {1,4,6,3,5,7};
quick_sort(c, 6, &swap);
for (int i=0;i<6;i++)
printf("%d | ", c[i]);
return 0;
}
Now we all agree that the output should be:
1, 3, 4, 5, 6, 7
which is indeed what I get when running the NOT generic function.
When I run my generic(upper) function I get basically trash.
You all have any ideas where I'm wrong? :)
The most obvious issue: Your input data is an int array, typecasted into a void * pointer, then forced into a char * pointer:
swap((char*)a, (char*)a+n/2);
Here you force that into a char * pointer, and jumping n/2 into it.
char * is an array of 1 byte size elements
int * is an array of 2, 4 or 8 byte size elements depending on compiler/OS/CPU.
So char *a +1, void give you the second byte of the first element of the initial array.
qsort is a generic sorting function. You give it an array, the size of the elements in the array, the number of elements, and a comparison function.
typedef int(*compare)(const void*, const void*);
void quicksort(void *base, size_t num_elements, size_t width, compare *cmp);
To move through the array the sorting function needs to know the width of each element so it can do the pointer arithmetic correctly. An array of char will be 1 byte per element. An array of int is probably 4 bytes. double will be 8. base[4] of a char array is base + 4*1, but it's base + 4*4 for an int array. Ultimately base[n] is base + (n * width).
To avoid making assumptions about the data in the elements, or how you want them sorted, the compare is used to compare elements for sorting. It returns < 0 if a < b, 0 if a == b and > 0 if a > b. This allows it to be as simple as return a - b for most numbers.
An example function for comparing integers:
int cmp_int(const void* _a, const void* _b) {
/* Do the casting separately for clarity */
int *a = (int *)_a;
int *b = (int *)_b;
return *a - *b;
}
There's no need to pass in a swap function. So long as you know the size of the elements a single swap function will serve. The one from #HonzaRemeš' answer works.
void swap(void * a, void * b, size_t size) {
/* Temp buffer large enough to contain an element */
char tmp[size];
memcpy(tmp, a, size);
memcpy(a, b, size);
memcpy(b, tmp, size);
}
With all this in mind, your function is not being given the element size (ie. width) so it cannot correctly move through the array. It's also unnecessarily passing in a swap function, but there's no need for this if you know the size of the elements. And you're lacking a proper comparison function to compare elements. Not much of a generic sort function if it can't compare things to sort them.
You are trying to do something the C language is not very appropriate for. If you want to do it, you need some background knowledge about pointer arithmetics.
Specifically, for a T *, where T is a type with size N (sizeof(T) == N),
T * ptr;
ptr = (T *) 0x0100;
ptr = ptr + 1;
// ptr now has value 0x100 + N
That means you can't have a generic function which will operate on data arrays without knowing the size of the array element.
So I suggest you rewrite your quick_sort and swap functions to incorporate size parameters. You then cast your pointers to char * and use the size parameter to make the functions work correctly. Example swap function follows.
void swap(void * c1, void * c2, size_t size) {
char tmp[size]; // temporary buffer big enough to contain c1 data
memcpy(tmp, c1, size);
memcpy(c1, c2, size);
memcpy(c2, tmp, size);
}
Modifying quick_sort is left as an exercise :). Remember though that when you don't know the size of your data, you must use memcpy(dst, src, size) instead of dst = src, you must use memcmp(a1, a2, size) >= 0 instead of a1 >= a2 and that your pointer access must be multiplied by size (exerpt from quick_sort follows):
EDIT: #Schwern points out in the comments why using memcmp() may not work. Comparing values of unknown size and format (endianness, float X int) would probably require a generic comparison function (which would likely be next to impossible to write). That takes us back to C's ill-suitedness for this task.
void quick_sort(void *a, int n, size_t size) {
char[size] p;
int b = 1, t = n - 1;
if(n < 2)
return;
// Using new swap with 'size' parameter
swap(&a[0], &((char *)a)[n / 2 * size], size);
// or swap((char *)a + 0, (char*)a + (n / 2 * size), size);
memcpy(p, a, size);
while(b <= t) {
while(t >= b && memcmp((char *)a[t * size], p, size) >= 0) {
...
}
You can then write wrapper macros to pass the size parameter to the quick_sort function.
#define QSORT(arr, n) quick_sort((arr), (n), sizeof((arr)[0]))
I have array A and i want to copy this array from position x till y to another array in C language. Please help in creating it in c.
Using memcpy copies array from beginning only. I want to copy from particular position to another position.
int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int b[5];
memcpy( b, a + 5, 5 * sizeof( int ) );
Also you can do this using an ordinary for loop
for ( int i = 0; i < 5; i++ ) b[i] = a[i+5];
Since you are copying into another array, you can use memcpy():
memcpy(another_array, array + x, (y - x) * sizeof(*array));
If you were copying into the same array, you should use memmove() instead.
memmove(array + z, array + x, (y - x) * sizeof(*array));
For each, the first parameter denotes the destination, and the functions assume the destination has enough space to accept the complete copy.
memcpy only copies from the beginning of an array if that's what address you pass it. The name of an array a is synonymous with the address of the first element &a[0], so if you do memcpy(dest, src, size), then the copy will be from the start of the array src.
Pointer arithmetic can be used to start the copy from a point further along in your array. For example, to copy 10 elements starting from element 2 in array src, you can do this:
size_t size = 10 * sizeof (int);
int * dest = malloc(size);
memcpy(dest, src + 2, size); // or equivalently, &src[2]
for(i=x, j=0; i<=y; i++, j++)
AnotherArray[j]= A[i];
Copy arrays with memcpy
void * memcpy (void * destination, void * source, size_t size)
The memcpy function copies an certain amount of bytes from a source memory location and writes them to a destinaction location. (Documentation)
Example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int some_array[] = {10, 11, 12, 13, 14};
int memory_amount = sizeof(some_array);
int item_count = memory_amount / sizeof(some_array[0]);
int *pointer = malloc(memory_amount);
memcpy(pointer, &some_array, memory_amount);
while (item_count--)
printf("%d=%d\n", item_count, *(pointer + item_count));
free(pointer);
return 0;
}
Output
$ ./a.out
4=14
3=13
2=12
1=11
0=10