Почему мой новый массив только копирует и переворачивает первые 10 элементов о старом массиве? - PullRequest
0 голосов
/ 17 января 2020

Я хочу скопировать и перевернуть массив в C указателе, но я обнаружил, что результат может показывать только первые 10 элементов, почему?

Original array: 0 1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361
Reversed array: 81 64 49 36 25 16 9 4 1 0 29274861 12333 14041000 14036848 0 0 14036820 0 14036816 0

Мое веселье c:

int * reverse_copy(int *A, int N) { 
    int *B,tmp; 
    for (B=A+N-1;A<B;A++,B--){
      tmp=*A;
      *A=*B;
      *B=tmp;
    }
}

основной

int * reverse_copy(int *A, int N);  
int main(int argc, char *argv[]) {   
    int N = 20;int i;int *A = NULL, *B = NULL;   
    if (argc > 1)   // first command line parameter
        N = atoi(argv[1]);  
    // allocate, fill, and print input array
    A = (int*) malloc(N * sizeof(int));
    for (i = 0; i < N; i++)
        A[i] = i*i;       
    // call task function
    B = reverse_copy(A, N);     
    // free allocated memory
    free(A);
    free(B);
    return 0;
}   

Ответы [ 2 ]

4 голосов
/ 17 января 2020

Для начала имя функции reverse_copy только сбивает с толку читателей, потому что функция ничего не копирует. Он переворачивает массив на месте.

Так что лучше назвать функцию просто как reverse.

Во-вторых, функция имеет тип возврата int *, но ничего не возвращает. Нет смысла объявлять тип возвращаемого значения функции как int * вместо void при условии, что функция не выделяет динамически новый массив ..

В результате этот оператор

B = reverse_copy(A, N);

не имеет смысла и вызывает неопределенное поведение.

Вы выделили только один массив, на который указывает указатель A. Указатель B не указывает на вновь динамически размещенный массив. Так что это утверждение

free(B);

снова вызывает неопределенное поведение.

Вот демонстрационная программа, которая показывает, как две функции, reverse и reverse_copy, могут быть реализованы с помощью указателей.

#include <stdio.h>
#include <stdlib.h>

void reverse( int *a, size_t n )
{
    if ( n != 0 )
    {
        for ( int *b = a + n; a < --b; ++a )
        {
            int tmp = *a;
            *a = *b;
            *b = tmp;
        }
    }
}

int * reverse_copy( const int *a, size_t n )
{
    int *b = NULL;

    if ( n != 0 )
    {
        b = malloc( n * sizeof( int ) );

        for ( int *p = b + n; p-- != b; ++a )
        {
            *p = *a; 
        }
    }

    return b;
}

int main(void) 
{
    int a[] = 
    { 
        0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361 
    };

    const size_t N = sizeof( a ) / sizeof( *a );

    printf( "Original array: " );
    for ( size_t i = 0; i < N; i++ )
    {
        printf( "%d ", a[i] );
    }

    putchar( '\n' );

    reverse( a, N );

    printf( "Reversed array: " );
    for ( size_t i = 0; i < N; i++ )
    {
        printf( "%d ", a[i] );
    }

    putchar( '\n' );

    putchar( '\n' );

    printf( "Original array: " );
    for ( size_t i = 0; i < N; i++ )
    {
        printf( "%d ", a[i] );
    }

    putchar( '\n' );

    int *b = reverse_copy( a, N );

    printf( "Reversed array: " );
    for ( size_t i = 0; i < N; i++ )
    {
        printf( "%d ", b[i] );
    }

    putchar( '\n' );

    free( b );

    return 0;
}

Вывод программы:

Original array: 0 1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361 
Reversed array: 361 324 289 256 225 196 169 144 121 100 81 64 49 36 25 16 9 4 1 0 

Original array: 361 324 289 256 225 196 169 144 121 100 81 64 49 36 25 16 9 4 1 0 
Reversed array: 0 1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361

Альтернативный и более гибкий подход реализации функции reverse_copy - предоставить функции уже существующий / выделенный массив.

Вот демонстрационная программа

#include <stdio.h>
#include <stdlib.h>

int * reverse_copy( const int *a, size_t n, int *b )
{
    for ( const int *p = a + n; p != a; ++b )
    {
        *b = *--p;
    }

    return b;
}

int main(void) 
{
    int a[] = { 0, 1, 2, 3, 4, 5 };

    const size_t N = sizeof( a ) / sizeof( *a );

    printf( "Original array: " );
    for ( size_t i = 0; i < N; i++ )
    {
        printf( "%d ", a[i] );
    }

    putchar( '\n' );


    int *b = malloc( 2 * N * sizeof( int ) );

    int *p = reverse_copy( a, N, b );;

    for ( const int *q = a; q != a + N; ++q, ++p )
    {
        *p = *q;
    }

    printf( "Reversed array: " );
    for ( size_t i = 0; i < 2 * N; i++ )
    {
        printf( "%d ", b[i] );
    }

    putchar( '\n' );

    free( b );

    return 0;
}

Вывод программы

Original array: 0 1 2 3 4 5 
Reversed array: 5 4 3 2 1 0 0 1 2 3 4 5 
1 голос
/ 17 января 2020
#include <stdio.h>
#include <stdlib.h>

void reverse_copy(int *A, int N) { 
    int *B,tmp; 
    for (B=A+N-1;A<B;A++,B--){
      tmp=*A;
      *A=*B;
      *B=tmp;
    }
}

int main(void) {

  int numbers[20] = {0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361};

  reverse_copy(numbers, 20);

  for( int i = 0; i < 20; i++ ) {
    printf("%d ", numbers[i]);
  }
  return 0;
}

Я предполагаю, что вы на самом деле не хотите новый массив, и вы хотите инвертировать числа в существующем массиве, потому что в противном случае вы просто не можете использовать для l oop для копирования из старый массив в обратном направлении? Поэтому я предполагаю, что вы хотите, чтобы reverse_copy вернул void, то есть ничего не возвращал.

Помимо типа возврата, ваша функция, кажется, работает нормально (хотя странным и опасным способом я я бы не написал функцию, которая на самом деле делает ++ для любого входного указателя).

Редактировать: Теперь я вижу ваш основной, если вы хотите новый массив, вот как вы бы написали все это:

#include <stdio.h>
#include <stdlib.h>

void reverse_copy(int *A, int * B, int N) { 
    for (int i = N-1;i>0;i--){
      B[N-i-1]=A[i];
    }
}

int main(void) {

  const int kLen = 20;
  int* A;
  int* B;
  A = (int*) malloc(kLen * sizeof(int));
  B = (int*) malloc(kLen * sizeof(int));

  for (int i = 0; i < kLen; i++){
    A[i] = i; 
  }

  reverse_copy(A, B, kLen);

  printf("A:");
  for( int i = 0; i < kLen; i++ ) {
    printf("%d ", A[i]);
  }

  printf("\nB:");
  for( int i = 0; i < kLen; i++ ) {
    printf("%d ", B[i]);
  }
  printf("\n");

  free(A);
  free(B);

  return 0;
}
...