От новичка до гуру: Курсы программирования на CyberDuff

Реверс массива на месте

Итак, я попытался напечатать, а массив, а затем реверсировать, использует другой массив. Но я пытаюсь создать цикл For Loop, который возьмет массив и реверсирует все элементы на месте без необходимости проходить процесс создания совершенно новый массив.

Мой цикл for сталкивается с некоторыми проблемами, и я не уверен, куда идти дальше... я использую i, чтобы взять элемент в конце и переместить его вперед, а затем j используется в качестве счетчика для следите за элементами... если есть более простой способ сделать это, будем признательны за любые предложения.

Я новичок в этом языке программирования, поэтому любая дополнительная информация приветствуется.

#include <stdlib.h>
#include <time.h>

int Random(int Max) {
  return ( rand() % Max)+ 1;
}

void main() {
  const int len = 8;
  int a[len];
  int i;
  int j = 0;
  Randomize() ;

  srand(time(0));
  //Fill the Array
  for (i = 0; i < len; ++i) {
    a[i] = rand() % 100;
  }

  //Print the array after filled
  for (i = 0; i < len; ++i) {
    printf("%d ", a[i]);
  }
  printf("\n");
  getchar();

  //Reversing the array in place.
  for (i = a[len] -1; i >= 0, --i;) {
    a[i] = a[j];
    printf("%d ", a[j]);
    j++;
  }


}
10.04.2014

  • void main() может быть разрешен для вашей реализации, но лучше использовать стандартные int main(void) или int main(int argc, char* argv[]). 10.04.2014
  • да, я действительно столкнулся с этим предупреждением. это странная причина, когда я использую Xcode, он всегда запускает мой Main таким образом. поэтому мне и в голову не пришло его менять. @Дедупликатор 10.04.2014
  • Поэтому отправьте отчет об ошибке с помощью Xcode, если только они явно не предназначены только для платформ, имеющих это расширение (в чем я сомневаюсь). 10.04.2014

Ответы:


1

Цикл while может быть легче концептуализировать. Представьте, что вы начинаете с обоих концов и меняете местами два элемента, пока не дойдете до середины.

  i = len - 1;
  j = 0;
  while(i > j)
  {
    int temp = a[i];
    a[i] = a[j];
    a[j] = temp;
    i--;
    j++;
  }

  //Output contents of now-reversed array.
  for(i = 0; i < len; i++)
    printf("%d ", a[i])
10.04.2014
  • Когда я использую свой оператор printf, я буду печатать a[i] и a[j] вместе, так как они оба составляют половину массива. Поэтому, как только я это сделаю, я неправильно их организую. Мой возвращаемый массив выглядит примерно так: @liangricha 80 66 36 81 44 4 43 90 // 66 43 36 4 81 44 81 44 10.04.2014
  • Что я заметил, так это то, что i и j захватывают каждый второй элемент, а не все элементы в этой половине. поэтому мой массив выходит все перепутанным. @liangricha 10.04.2014
  • @ Зандерг не уверен, что понимаю. Если вы пройдете по элементам массива a после цикла while (реверс) и распечатаете их один за другим, вывод должен быть обратным вашему первому циклу printf. 10.04.2014
  • Итак, после отладки я знаю, что это работает... моя проблема в том, как я это печатаю. Поместив его после {} для цикла While, программа полностью пропустит printf. но если я помещу printf внутрь цикла, он будет помещать число каждый раз, когда он проходит через цикл, а не после его завершения. Я попробовал if (i == j), затем printf, но это тоже не работает. Я знаю, что это все в моем месте, я просто не могу понять, куда это идет. @liangricha 10.04.2014
  • Отредактировал мой ответ. Вам нужно написать еще один цикл for после цикла while, чтобы распечатать содержимое массива @Zanderg 10.04.2014
  • Что сложнее в for (i = len - 1, j = 0; i > j; i--, j++) ...? 06.08.2018

  • 2
    void reverse_range(int* buffer, int left, int right)
    {
        while (left < right)
        {
            int temp = buffer[left];
            buffer[left++] = buffer[right];
            buffer[right--] = temp;
        }
    }
    

    вызовите его для обратного массива

    int a[3] = {1, 2, 3};
    reverse_range(a, 0, 2);
    
    10.04.2014
  • API вызывает сомнения: следует ли включить right, как в опубликованном коде, или исключить, чтобы разрешить пустые диапазоны? Последнее является более распространенной идиомой в C и широко используемым соглашением в библиотеке C++ (с диапазонами указателей). 06.08.2018

  • 3

    Вы на правильном пути, но нужно немного подумать о последнем цикле for и операции присваивания внутри. Инициализация цикла отключена, так как i = a[len] - 1 скопирует значение последней записи в i. Поскольку это значение является случайным числом, ваш индекс, вероятно, выйдет за пределы допустимого диапазона.

    Затем вы копируете половину массива в другую половину, а затем обратно. Этот цикл делает следующее: a[7] = a[0] a[6] = a[1] a[5] = a[2] a[4] = a[3] ...

    К этому моменту вы потеряли все начальные значения от a[4] до a[7].

    Попробуй это:

    for( i = 0; i < len / 2; i++ ){
        int temp = a[i];
        a[i] = a[len - i];
        a[len - i] = temp;
    }
    

    Используйте отладчик и выполните цикл, наблюдая за значением i, temp и каждого элемента в массиве.

    10.04.2014

    4

    Просто мои 2 цента...

    #include <stdlib.h>
    #include <stdio.h>
    
    int main() {
          int arry[] = {0, 1, 2, 3, 4, 5};
          int* s = arry;
          int* e = arry + (sizeof(arry) / sizeof(arry[0])) - 1;
          while (s < e) {
            *e ^= *s;
            *s ^= *e;
            *e ^= *s;
            s++;
            e--;
          }
          for (size_t i = 0; i < (sizeof(arry) / sizeof(arry[0])); i++) {
            fprintf(stderr, "%d, ", arry[i]);
          }
          fprintf(stderr, "\n");
       }
    
    24.06.2016
  • Мне было интересно, работает ли это для нецелочисленных типов, например, вы можете XOR char? 17.08.2016
  • Все основные типы в C являются целыми типами... char - это 8-битное целое число с неправильным именем (в некоторых системах оно будет более 8-битным). Итак, отвечая на ваш вопрос, да. Указатели должны быть приведены к intptr_t до того, как будут выполнены арифметические действия (это сделано для ясности компилятора и целей, а не потому, что указатели не являются числами). 17.08.2016
  • Однако в последнее время мне посоветовали, чтобы компиляторы лучше оптимизировали переменную tmp, чем замену XOR. Об этом есть статья в Википедии... Я понятия не имею, правда ли это. 17.08.2016
  • да, это плохая идея, так как это делает код нечитаемым, и компилятор все равно это делает. Вот почему я не решался поставить +1, но, поскольку вы говорите «Просто мои 2 цента»… :) 17.08.2016
  • Интересное классическое любопытство, но потенциально неопределенное поведение, более медленное на архитектурах, где оно работает. Неопределенное поведение для пустых массивов. 06.08.2018
  • Почему это может быть неопределенным поведением для пустых массивов? В конце концов, если конец равен началу (e == s), на самом деле ничего не происходит (кроме печати маркера новой строки). 06.08.2018

  • 5

    Для начала вместо этого:

    for (i = a[len] -1; i >= 0, --i;) {
    

    Вы хотите это:

    for (i = len-1; i >= 0, --i;) {
    

    но вы также хотите пройти только половину массива, так что это будет

    for (i = len-1; i > j, --i;) {
    
    10.04.2014
  • Итак, я хочу пройти только половину пути, потому что, если бы я прошел весь массив, я бы просто перевернул его обратно в исходное положение? @Вон Катон 10.04.2014

  • 6

    Попробуй это;

    #include <stdlib.h>
    #include <time.h>
    
    int Random(int Max) {
      return ( rand() % Max)+ 1;
    }
    
    void main() {
      const int len = 8;
      int a[len];
      int i,end;
      int j = 0;
      Randomize() ;
    
      srand(time(0));
      //Fill the Array
      for (i = 0; i < len; ++i) {
        a[i] = rand() % 100;
      }
    
      //Print the array after filled
      for (i = 0; i < len; ++i) {
        printf("%d ", a[i]);
      }
      printf("\n");
      getchar();
    
      for (i = 0; i < n/2; i++) {
          t = a[i];
          a[i]   = a[end];
          a[end] = t;
          end--;
      }
    
    }
    

    Надеюсь это поможет... :)

    Просто для предложения. Попробуйте использовать осмысленное имя переменной вместо просто i,a.... Это поможет вам при написании большого кода. :)

    10.04.2014
  • Хорошо, теперь я столкнулся с этой глупой проблемой, когда оператор printf, который я использую, не хочет печатать весь массив. @Рашад 10.04.2014
  • Когда я использую свой оператор printf, я буду печатать a[i] и a[j] вместе, так как они оба составляют половину массива. Поэтому, как только я это сделаю, я неправильно их организую. Мой возвращаемый массив выглядит примерно так @Rashad 80 66 36 81 44 4 43 90//66 43 36 4 81 44 81 44 10.04.2014
  • @Zanderg ›› Распечатать массив после обращения. 10.04.2014
  • t не определено, а end не инициализировано... печать перевернутого массива поможет проверить успешность операции. 06.08.2018

  • 7

    Вы можете перевернуть массив на месте, для этого вам не нужен вспомогательный массив. Вот мой код C для этого

    #include <stdio.h>
    int main(void)
     {
        int arr[5]={1,2,3,4,5};
        int size=sizeof(arr)/sizeof(int);   
        int success= reverse(arr,size);
        if(success==1)
            printf("Array reversed properly");
        else
            printf("Array reversing failed");   
    
        return 0;
    }
    
    
    int reverse(int arr[], int size)
    {
        int temp=0;
        int i=0;
        if(size==0)
            return 0;
        if(size==1)
            return 1;
    
        int size1=size-1;
        for( i=0;i<(size/2);i++)
        {
            temp=arr[i];
            arr[i]=arr[size1-i];
            arr[size1-i]=temp;
        }
    
        printf("Numbers after reversal are ");
        for(i=0;i<size;i++)
        {
            printf("%d ",arr[i]);
        }
        return 1;
    
    }
    
    20.01.2018
  • Почему вы возвращаете 0 для пустого массива? разворот тривиально успешен. Эти тесты действительно не нужны. 06.08.2018

  • 8

    Вот простая и понятная функция для перелистывания массивов всех размеров. Измените параметры в соответствии с вашим типом массива:

    void flipArray(int *a, int asize){
                int b[asize];
                int *b_p = b;
    
                for(int i=0; i<asize; i++){
                        //backwardsOrientation = (arraySize-1)-increment
                        b_p[asize-1-i] = a[i];
                }
                for(int i=0; i<asize; i++){
                        a[i] = b_p[i];
                }
        }
    
    06.08.2018
  • функция для переворачивания массивов всех размеров... возможно, все маленькие ненулевые размеры, но массивы больших размеров (и отрицательные или нулевые значения asize) приведут к неопределенному поведению. Кроме того, нет необходимости в int *b_p = b;, просто используйте вместо него b. 06.08.2018
  • если вы измените тип данных переменных, вы можете иметь массивы всех размеров. Условные выражения - сука, я знаю. 08.08.2018

  • 9

    Если вы не заинтересованы в написании функций для любого числового типа, попробуйте макросы для этой задачи. Этот код одинаково работает с любым встроенным числовым типом: int, float, double.

    Он не поддерживает строки, так как любая строка заканчивается символом NULL \0. Более контролируемая версия, мой аналогичный ответ здесь https://stackoverflow.com/a/42063309/6003870 и содержит решение для перевернуть строку.


    Полный код

    #include <stdio.h>
    
    // print items of an array by a format
    #define PRINT_ARRAY(array, length, format) \
    { \
        putchar('['); \
        for (size_t i = 0; i < length; ++i) { \
            printf(format, array[i]); \
            if (i < length - 1) printf(", "); \
        } \
        puts("]"); \
    }
    
    
    // reverse an array in place
    #define REVERSE_ARRAY(array, length, status) \
        if (length > 0) { \
            for (int i = 0; i < length / 2; ++i) { \
                double temp; \
                temp = array[i]; \
                array[i] = array[length - i - 1]; \
                array[length - i - 1] = temp; \
            } \
            *status = 0; \
        } \
        else if (length < 0) *status = -1; \
        else *status = 1;
    
    #define SUCCESS_REVERSE_ARRAY_MSG "An array succefully reversed"
    #define FAILED_REVERSE_ARRAY_MSG "Failed reverse for an array"
    #define NO_CHANGED_REVERSE_ARRAY_MSG "An array no changed"
    
    
    /*
        Print message about status reverse an array
     */
    static void
    print_msg_reverse_array_status(const int status)
    {
        if (status == 0) printf("Status: %s\n", SUCCESS_REVERSE_ARRAY_MSG);
        else if (status == -1) printf("Status: %s\n", FAILED_REVERSE_ARRAY_MSG);
        else if (status == 1) printf("Status: %s\n", NO_CHANGED_REVERSE_ARRAY_MSG);
    }
    
    
    int
    main (const int argc, const char *argv[])
    {
        // keep value of status
        int status;
    
        puts("\tExample reverse of an integer array");
        int arr_int[5] = {1, 2, 3, 4, 5};
    
        status = 0;
        PRINT_ARRAY(arr_int, 5, "%d");
        REVERSE_ARRAY(arr_int, -1, &status);
    
        // will be an error, since a length is less 0, and the array is not changed
        print_msg_reverse_array_status(status);
        PRINT_ARRAY(arr_int, 5, "%d");
    
        status = 0;
        REVERSE_ARRAY(arr_int, 0, &status);
    
        // a length is equal to 0, so an array is not changed
        print_msg_reverse_array_status(status);
        PRINT_ARRAY(arr_int, 5, "%d");
    
        status = 0;
        REVERSE_ARRAY(arr_int, 5, &status);
        print_msg_reverse_array_status(status);
        PRINT_ARRAY(arr_int, 5, "%d");
    
        puts("\n\tExample reverse of an float array");
        float arr_float[5] = {0.78, 2.1, -3.1, 4, 5.012};
    
        status = 0;
        PRINT_ARRAY(arr_float, 5, "%5.3f");
        REVERSE_ARRAY(arr_float, 5, &status);
        print_msg_reverse_array_status(status);
        PRINT_ARRAY(arr_float, 5, "%5.3f");
    
        puts("\n\tExample reverse of an double array");
        double arr_double[5] = {0.00001, 20000.002, -3, 4, 5.29999999};
    
        status = 0;
        PRINT_ARRAY(arr_double, 5, "%8.5f");
        REVERSE_ARRAY(arr_double, 5, &status);
        print_msg_reverse_array_status(status);
        PRINT_ARRAY(arr_double, 5, "%8.5f");
        return 0;
    }
    

    Я использую GCC для компиляции, и ваш результат должен быть следующим

        Example reverse of an integer array
    [1, 2, 3, 4, 5]
    Status: Failed reverse for an array
    [1, 2, 3, 4, 5]
    Status: An array no changed
    [1, 2, 3, 4, 5]
    Status: An array succefully reversed
    [5, 4, 3, 2, 1]
    
        Example reverse of an float array
    [0.780, 2.100, -3.100, 4.000, 5.012]
    Status: An array succefully reversed
    [5.012, 4.000, -3.100, 2.100, 0.780]
    
        Example reverse of an double array
    [ 0.00001, 20000.00200, -3.00000,  4.00000,  5.30000]
    Status: An array succefully reversed
    [ 5.30000,  4.00000, -3.00000, 20000.00000,  0.00000]
    

    Среда тестирования

    $ lsb_release -a
    No LSB modules are available.
    Distributor ID: Debian
    Description:    Debian GNU/Linux 8.6 (jessie)
    Release:    8.6
    Codename:   jessie
    $ uname -a
    Linux localhost 3.16.0-4-amd64 #1 SMP Debian 3.16.36-1+deb8u2 (2016-10-19) x86_64 GNU/Linux
    $ gcc --version
    gcc (Debian 4.9.2-10) 4.9.2
    
    07.02.2017
  • Если вы собираетесь писать макросы, по крайней мере, заключайте аргументы в расширение в скобки и заключайте их в оператор do { ... } while (0)... Ваш код очень хрупок. Например, попробуйте int temp[20], i = 20, status; REVERSE_ARRAY(temp, i, &status); 06.08.2018

  • 10
  • // вы также можете найти sizeof(); очень удобно, если вы не хотите, чтобы это был массив символов в первую очередь и любой другой тип данных 01.01.2017
  • но если вы хотите сделать функцию самостоятельно, обратитесь к первому комментарию 01.01.2017
  • Потенциальное неопределенное поведение, поскольку C11 7.22.1 Функции числового преобразования Функции atof, atoi, atol и atoll не должны влиять на значение целочисленного выражения errno при ошибке. Если значение результата не может быть представлено, поведение не определено. 06.08.2018
  • Новые материалы

    Лама 2: новое поколение языковой модели с открытым исходным кодом от Meta и Microsoft
    Meta и Microsoft объединили усилия, чтобы представить Llama 2, последнюю версию их модели большого языка с открытым исходным кодом. С его выпуском Llama 2 теперь доступна как для исследований,..

    Окончательные классы и классы только для чтения в PHP
    выпускные классы В прошлом, когда вы не хотели, чтобы другие классы расширяли определенный класс, вы могли пометить его как final . Рассмотрим код ниже: <?php namespace App\Utils;..

    Понимание видео в 2 строки
    В этой статье я покажу вам, как выполнять задачи распознавания изображений и понимания видео всего за 2 строки кода, используя TensorFlow.JS . Для обнаружения объектов: модель =..

    Создание сайта по сбору средств для художников и благотворительных организаций за два уик-энда
    Вот как я это сделал. Использование Google Cloud, Grow.io и Stripe. Когда к власти пришла новая администрация и начали поступать распоряжения и политика, с которыми я был не согласен, я..

    Простая и согласованная среда разработки C++
    Обычной проблемой для изучающих C++ является выбор хорошей среды разработки. Множество вариантов выбора, большинство из которых существенно влияют на пользовательский опыт. Сегодня я проведу..

    Что такое кортеж в Python?
    Типы данных в Python В Python кортежи — это один из четырех встроенных типов данных, используемых для хранения коллекций данных. Другие три встроенных типа данных для этой цели включают..

    Логистическая регрессия — Теоретический путь
    Прежде чем двигаться дальше, я считаю, что вы должны иметь представление о линейной регрессии . Если нет, пожалуйста, просмотрите мои предыдущие статьи: Линейная регрессия I и Линейная..