0

I'm writing a function that takes as argument an array of integers and returns an array that is left shifted by one -- so { 6, 2, 5, 3 } returns { 2, 5, 3, 6 }.

Here's what I tried, but have issues with pointers probably. Anyone got an idea of what I'm doing wrong here?

int shiftLeft(int nums[MAX_SIZE]) {
    int i, tmp, size;
    tmp = nums[0];
    size = sizeof(nums) / sizeof(nums[0]);
    for (i = 0; i < size - 1; i++) {
        nums[i] = nums[i + 1];
    }
    nums[size] = tmp;
    return nums;
}

int main() {
    int numss[MAX_SIZE] = { 6, 2, 5, 3 };
    printf("%d", shiftLeft(numss));

    return 0;
}

It prints 644032.

wovano
  • 4,543
  • 5
  • 22
  • 49
Kan Peljto
  • 17
  • 1
  • 1
    Have you tried printing out size ? Also return type on shiftLeft vs the printf ? – John3136 Jun 16 '22 at 11:01
  • 1
    When you pass an array in C, you pass a pointer to it and that's all. You have to pass the size of the array separately, you can't calculate it. – tevemadar Jun 16 '22 at 11:01
  • In theory you could do `int shiftLeft(int (*nums)[MAX_SIZE]) { ... sizeof(*nums)` but it's better to pass the size separately: `int shiftLeft(size_t size, int nums[size])` – Lundin Jun 16 '22 at 12:43

1 Answers1

2

Let's consider this function

int shiftLeft(int nums[MAX_SIZE]){

int i,tmp,size;
tmp=nums[0];
size=sizeof(nums) / sizeof(nums[0]);
for(i=0;i<size-1;i++)
{
    nums[i]=nums[i+1];
}
nums[size]=tmp;
return nums;
}

Its return type is int. However you return the object nums that is declared as the array int nums[MAX_SIZE] in the function parameter list. So the function already is wrong.

Correspondingly this call of printf

printf("%d",shiftLeft(numss));

does not make a sense. To output elements of an array you need to use a loop.

Function parameters having array types are adjusted by the compiler to pointers to the array element types. It means that this function declaration

int shiftLeft(int nums[MAX_SIZE]){

actually represents the following declaration

int shiftLeft(int *nums){

It means in turn that this expression

sizeof(nums) / sizeof(nums[0])

is equivalent to

sizeof(int * ) / sizeof(int )

and equal either 2 or 1 depending on sizes of pointer objects of the type int * and objects of the type int. That is the expression does not depend on the number of elements of the array used as a function argument.

You need to pass explicitly to the function the number of elements in the array.

Taking all this into account the function can look like

void shiftLeft( int nums[], size_t n )
{
    if ( !( n < 2 ) )
    {
        int tmp = nums[0];
        for ( size_t i = 1; i < n; i++ )
        {
            nums[i-1] = nums[i];
        }
        nums[n-1] = tmp;
    }
}

And the function can be called like

int nums[] = { 6, 2, 5, 3 };
const size_t N = sizeof( nums ) / sizeof( *nums );

for ( size_t i = 0; i < N; i++ )
{
    printf( "%d ", nums[i] );
}
putchar( '\n' );

shiftLeft( nums, N  );

for ( size_t i = 0; i < N; i++ )
{
    printf( "%d ", nums[i] );
}
putchar( '\n' );

Within the function instead of this for loop

for ( size_t i = 1; i < n; i++ )
{
    nums[i-1] = nums[i];
}

you can use standard function memmove declared in the header <string.h>. For example

memmove( nums, nums + 1, ( n - 1 ) * sizeof( *nums ) );

Here is a demonstration program where all the code snippets are combined together.

#include <stdio.h>
#include <string.h>

void shiftLeft( int nums[], size_t n )
{
    if ( !( n < 2 ) )
    {
        int tmp = nums[0];
        memmove( nums, nums + 1, ( n - 1 ) * sizeof( *nums ) );
        nums[n-1] = tmp;
    }
}


int main( void )
{
    int nums[] = { 6, 2, 5, 3 };
    const size_t N = sizeof( nums ) / sizeof( *nums );

    for ( size_t i = 0; i < N; i++ )
    {
        printf( "%d ", nums[i] );
    }
    putchar( '\n' );

    shiftLeft( nums, N );

    for ( size_t i = 0; i < N; i++ )
    {
        printf( "%d ", nums[i] );
    }
    putchar( '\n' );
}

The program output is

6 2 5 3 
2 5 3 6 

Based on the function definition it is easy to write a recursive function that will shift to left an array by the specified number of positions.

Here you are.

#include <stdio.h>
#include <string.h>

void shiftLeft( int nums[], size_t n, size_t m )
{
    if ( n ) m %= n;
    if ( !( n < 2 ) && m )
    {
        int tmp = nums[0];
        memmove( nums, nums + 1, ( n - 1 ) * sizeof( *nums ) );
        nums[n-1] = tmp;
        shiftLeft( nums, n, m - 1 );
    }
}


int main( void )
{
    int nums[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    const size_t N = sizeof( nums ) / sizeof( *nums );

    for ( size_t i = 0; i < N; i++ )
    {
        printf( "%d ", nums[i] );
    }
    putchar( '\n' );

    for ( size_t i = 1; i < N / 2 ; i++ )
    {
        shiftLeft( nums, N, i );

        for ( size_t i = 0; i < N; i++ )
        {
            printf( "%d ", nums[i] );
        }
        putchar( '\n' );
    }
}

The program output is

0 1 2 3 4 5 6 7 8 9 
1 2 3 4 5 6 7 8 9 0 
3 4 5 6 7 8 9 0 1 2 
6 7 8 9 0 1 2 3 4 5 
0 1 2 3 4 5 6 7 8 9 
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335