Search code examples
arrayscreversefunction-definitionsub-array

How do I reverse runs of nonnegative integers in an array in C?


I need to create a random array in C, find nonnegative values in it, and when there are at least 2 in a row, reverse them. For example, if I have the random array 5 6 -7 -8 9 -4 7 8 2 -2 I need to get 6 5 -7 -8 9 -4 2 8 7 -2. This is what I've tried so far:

    #include <stdio.h>
#include <stdlib.h>
 int ARRAY[100];
int main(void) {
 int i;
 int nn; 
 int temp = ARRAY[i];
 rand();
 
 for (i=0; i<100; ARRAY[i++]=rand()%100-50 );

 printf("FIRST ARRAY:\n");
 for (i=0; i<100; i++)
    printf("%3d ",ARRAY[i]);
 putchar('\n');
 putchar('\n');



for(i=0; i<100; i++){
    if (ARRAY[i]<0) {
        if(!nn) {
            nn = 1;

        }
    }

        else {
            temp=ARRAY[i];
            ARRAY[i] = ARRAY[nn - 1];
            ARRAY[nn - 1] = temp;


            }
    }







 printf("Result:\n");

 putchar('\n');
 for (i=0; i<100; printf("%3d ",ARRAY[i++]));
 putchar('\n');
 return 0;
}

But had no luck with it.


Solution

  • For starters there is no any need to declare the array globally

    int ARRAY[100];
    

    Also never use magic numbers like 100. Use named constants.

    And it is a bad style of programming to name variables except constants with all upper case letters.

    You can write a separate function as it is shown in the demonstrative program below.

    #include <stdio.h>
    
    void reverse_non_negative( int a[], size_t n )
    {
        for (size_t i = 0; i < n; )
        {
            while (i < n && a[i] < 0) i++;
    
            size_t j = i;
    
            while (i < n && !( a[i] < 0 )) i++;
    
            for (size_t k = 0; k < ( i - j ) / 2; k++)
            {
                int tmp = a[j + k];
                a[j + k] = a[i - k - 1];
                a[i - k - 1] = tmp;
            }
        }
    }
    
    int main()
    {
        int a[] = { 5, 6, -7, -8, 9, -4, 7, 8, 2, -2 };
        const size_t N = sizeof( a ) / sizeof( *a );
    
        for (size_t i = 0; i < N; i++)
        {
            printf( "%d ", a[i] );
        }
        putchar( '\n' );
    
        reverse_non_negative( a, N );
    
        for (size_t i = 0; i < N; i++)
        {
            printf( "%d ", a[i] );
        }
        putchar( '\n' );
    }
    

    The program output is

    5 6 -7 -8 9 -4 7 8 2 -2
    6 5 -7 -8 9 -4 2 8 7 -2
    

    A more general approach can look the following way

    #include <stdio.h>
    
    void reverse_sub_ranges( int a[], size_t n, int predicate( int ) )
    {
        for (size_t i = 0; i < n; )
        {
            while (i < n && !predicate( a[i] )) i++;
    
            size_t j = i;
    
            while (i < n && predicate( a[i] )) i++;
    
            for (size_t k = 0; k < ( i - j ) / 2; k++)
            {
                int tmp = a[j + k];
                a[j + k] = a[i - k - 1];
                a[i - k - 1] = tmp;
            }
        }
    }
    
    int non_negative( int value )
    {
        return !( value < 0 );
    }
    
    int main()
    {
        int a[] = { 5, 6, -7, -8, 9, -4, 7, 8, 2, -2 };
        const size_t N = sizeof( a ) / sizeof( *a );
    
        for (size_t i = 0; i < N; i++)
        {
            printf( "%d ", a[i] );
        }
        putchar( '\n' );
    
        reverse_sub_ranges( a, N, non_negative );
    
        for (size_t i = 0; i < N; i++)
        {
            printf( "%d ", a[i] );
        }
        putchar( '\n' );
    }
    

    The program output is the same as shown above that is

    5 6 -7 -8 9 -4 7 8 2 -2
    6 5 -7 -8 9 -4 2 8 7 -2