kiraventom

Untitled

Jun 7th, 2023 (edited)
888
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.14 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. // Си работает "сверху вниз", поэтому мы не можем вызвать функцию, о которой нет информации
  5. // выше в файле. Чтобы не расставлять функции в файле в порядке их выполнения друг в друге,
  6. // используются так называемые "объявления функций". Это короткая запись функции, которая
  7. // описывает ее название, входные параметры и возвращаемый тип -- т.е., всю информацию, достаточную
  8. // для ее вызова (такая информация еще называется "сигнатурой функции"). Объявление функции предполагает, что где-то "внизу" по файлу будет и ее "определение" - то есть, сама функция с соответствующей объявлению сигнатурой.
  9. void print_matrix(int width, int height, int** matrix);
  10. void revert_rows_order(int height, int** matrix);
  11.  
  12. int main() {
  13.    int width, height;
  14.    printf("Enter width of matrix: ");
  15.    scanf("%d", &width);
  16.  
  17.    printf("\nEnter height of matrix: ");
  18.    scanf("%d", &height);
  19.  
  20.    // Здесь, при выделении памяти, можно заметить два отличия от того способа,
  21.    // которым я выделял память раньше.
  22.    // Раньше я бы записал эту строчку так:
  23.    // int** matrix = (int**)malloc(height * sizeof(int*);
  24.    // Эта запись тоже корректна, но в ней (как я узнал) есть две небольшие помарки:
  25.    // 1. Не рекомендуется явно приводить тип указателя, возвращаемого функцией malloc.
  26.    // Причин этому несколько и они не особо просты для понимания, но суть в том,
  27.    // что в Си, в отличие от C++, это делать не нужно.
  28.    // Итог: в новой записи пропадает явное приведение типа: (int**) перед malloc.
  29.    // 2. Рекомендуется вычислять размер элемента не при помощи типа, а при помощи значения.
  30.    // Это еще менее понятная вещь, но суть тут в следующем:
  31.    // Раньше я вычислял количество памяти так: брал количество элементов (height) и
  32.    // умножал его на sizeof(int*). int* - это тип элемента, а sizeof(int*) вернет количество байт,
  33.    // которое один элемент типа int* занимает на этом компьютереэ.
  34.    // Однако sizeof можно вызвать не только на тип, но и на конкретную переменную.
  35.    // При этом для такого вызова не нужно указывать скобки.
  36.    // Новая запись выглядит так: sizeof *matrix.
  37.    // Это означает, что я узнаю, сколько в байтах занимает один ТАКОЙ ЖЕ элемент (того же типа),
  38.    // как тот, что я указал после sizeof. В данном случае я передаю *matrix, то есть
  39.    // разыменовываю указатель matrix и получаю элемент типа int*.
  40.    // Функционально это делает то же самое, что и старая запись, но выглядит более компактно
  41.    // и более устойчиво к ошибкам. Например, если мы в будущем будем переписывать этот код и решим,
  42.    // что нам нужна матрица не целых чисел, а дробных, нам будет достаточно поменять тип на float**
  43.    // в начале строки, а внутри вызова malloc ничего менять уже будет не надо.
  44.    int** matrix = malloc(height * sizeof *matrix);
  45.    for (int i = 0; i < height; ++i) {
  46.       int* row = malloc(width * sizeof *row);
  47.       *(matrix + i) = row;
  48.    }
  49.  
  50.    for (int i = 0; i < height; ++i) {
  51.       for (int j = 0; j < width; ++j) {
  52.          printf("\nEnter value at row %d, column %d: ", i + 1, j + 1);
  53.          int value;
  54.          scanf("%d", &value);
  55.          *(*(matrix + i) + j) = value;
  56.       }
  57.    }
  58.  
  59.    printf("\nOriginal matrix:\n");
  60.    print_matrix(width, height, matrix);
  61.  
  62.    revert_rows_order(height, matrix);
  63.  
  64.    printf("\nMatrix with rows reversed:\n");
  65.    print_matrix(width, height, matrix);
  66. }
  67.  
  68. // Вынес вывод массива на экран в отдельную функцию, чтобы не дублировать код
  69. void print_matrix(int width, int height, int** matrix) {
  70.    for (int i = 0; i < height; ++i) {
  71.       for (int j = 0; j < width; ++j) {
  72.          printf("%d ", *(*(matrix + i) + j));
  73.       }
  74.  
  75.       printf("\n");
  76.    }
  77. }
  78.  
  79. // Инверсия массива -- тривиальная задача, и один из известных алгоритмов ее решения
  80. // называется "метод двух указателей".
  81. // Я не вижу смысла подробно расписывать, как именно он работает, в интернете есть много статей
  82. // про него. Он не привязан к конкретному языку программирования, достаточно понять концепцию.
  83. void revert_rows_order(int height, int** matrix) {
  84.    int** head = matrix;
  85.    int** tail = matrix + height - 1;
  86.  
  87.    while (head < tail) {
  88.       int* tail_temp = *tail;
  89.       *tail = *head;
  90.       *head = tail_temp;
  91.  
  92.       ++head;
  93.       --tail;
  94.    }
  95. }
  96.  
Advertisement
Add Comment
Please, Sign In to add comment