Search code examples
arrayscpointerspointer-arithmetic

Insert numbers to array


I need to insert for every number sum of his digits in array using pointer arithmetic. Auxiliary arrays are not allowed.

Example:

123, 456, 789

Output:

123, 6, 456, 15, 789, 24

Code:

#include <stdio.h>
int sum_of_digits(int n){
    int sum=0;
    while(n!=0){
        sum=sum+n%10;
        n/=10;
    }
    return sum;
}

void add(int *arr, int n)
{
    int *p=arr, *y=arr+n*2-2,i;
    while(p++<arr+n);
    p-=2;
    while(p>arr)
    {
        *y=*p;
        *p=0;
        p--;
        y-=2;
    }
    p=arr;
    while(p<arr+n*2)
    {
        *(p+1)=sum_of_digits(*p);
        p+=2;
    }
    for(i=0;i<n;i++)
    printf("%d ", arr[i]);
}

void main() {
    int arr[20]={123, 456, 789},n=3;
    add(arr,n*2);
}

This works correct, but I don't understand the part of code with pointers. Could you explain me how this works?


Solution

  • I have formatted function add and added some comments to explain it, I hope they clarify what's happening. Note that arr[i] == *(arr + i) and *arr == arr[0]

    void add(int *arr, int n)
    {
        // p points to last number in arr
        // Equivalent to &arr[n-1]
        int *p = arr + n - 1;
        
        // y points to where last number will be after spreading
        // Equivalent to &arr[2*n - 2]
        int *y = arr + n * 2 - 2;
        
        // for n = 4 arr looks like this
        // [A, B, C, D, _, _, _, _]
        //           ^           ^
        //           p           y
        
        // Spread numbers of arr
        // [A, B, C, D, _, _, _, _] -> [A, _, B, _, C, _, D, _]
        while (p > arr)
        {
            // Copy D to last position
            *y = *p;
            // Zero original D location, unnecessary
            *p = 0;
            // Move p backwards by one
            p--;
            // Move y backwards by two
            y -= 2;
            
            // arr now looks like this
            // [A, B, C, _, _, _, D, _]
            //        ^     ^   
            //        p     y
            
            // After next iteration
            // [A, B, _, _, C, _, D, _]
            //     ^  ^         
            //     p  y      
            
            // After next iteration
            // [A, _, B, _, C, _, D, _]
        }
        
        // Iterate over every other value 
        // and assign arr[i+1] to sum_of_digits[i]
        p = arr;
        while (p < arr + n * 2)
        {
            *(p + 1) = sum_of_digits(*p);
            p += 2;
        }
        // Equivalent to
        // for (int i = 0; i < n * 2; i += 2) {
        //     arr[i + 1] = sum_of_digits(arr[i]);
        // }
        
        // [A, sum_of_digits(A), B, sum_of_digits(B), C, sum_of_digits(C), 
        //  D, sum_of_digits(D)]
    
        // Print array
        for (int i = 0; i < n; i++)
            printf("%d ", arr[i]);
    }