Advertisement
Guest User

spiral_matrix.c

a guest
Mar 3rd, 2023
52
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.26 KB | None | 0 0
  1. //  Необходимо заполнить матрицу MxN числами по спирали
  2. #include <stdio.h>
  3. #include <string.h> //  memset
  4. #include <stdlib.h> //  malloc, strtoul
  5. #include <errno.h>  //  Для обработки ошибок преобразования строки в число
  6.  
  7. #define M   5   //  Ширина
  8. #define N   4   //  Высота
  9.  
  10. //  Состояние конечного автомата
  11. #define STATE_RIGHT 0
  12. #define STATE_DOWN  1
  13. #define STATE_LEFT  2
  14. #define STATE_UP    3
  15.  
  16. //-------------------------------------------------------------------
  17. //  Прототипы функций
  18. //-------------------------------------------------------------------
  19. //  Выделяет память под массив matrix_buf, в котором будут храниться данные
  20. //  матрицы размером width на height элементов и под массив указателей
  21. //  на строки в массиве matrix_buf
  22. //  Возвращает указатели на выделенную память или NULL при неудаче
  23. int**   alloc_matrix( int** matrix_buf, size_t width, size_t height );
  24. //  Заполняет матрицу шириной width и высотой height числами по спирали,
  25. //  начиная с числа start_n. В каждой последующей ячейке start_n
  26. //  увеличивается на единицу
  27. void    fill_matrix( int** m, size_t width, size_t height, int start_n );
  28. //  Выводит матрицу в stdout
  29. void    show_matrix( int** m, size_t width, size_t height );
  30. //  Преобразует число в виде строки в unsigned long
  31. //  Возвращает 1 в случае успеха и 0 при неудаче
  32. int str_to_ulong( char* str, unsigned long* ul );
  33. //-------------------------------------------------------------------
  34.  
  35. //-------------------------------------------------------------------
  36. //  Реализация функций
  37. //-------------------------------------------------------------------
  38. void    fill_matrix( int** m, size_t width, size_t height, int start_n )
  39. {
  40.     //  Нам нужно заполнить не более чем width * height ячеек
  41.     size_t  max = width * height;
  42.     //  Количество заполненных ячеек
  43.     size_t  count = 0;
  44.     size_t  state = STATE_RIGHT;
  45.     size_t  x = 0;
  46.     size_t  min_x = 0;
  47.     size_t  max_x = width - 1;
  48.     size_t  y = 0;
  49.     size_t  min_y = 0;
  50.     size_t  max_y = height - 1;
  51.     while( count < max )
  52.     {
  53.         m[y][x] = start_n;
  54.         switch( state )
  55.         {
  56.             //  Движемся слева на право
  57.             case    STATE_RIGHT:
  58.                 if( x == max_x)
  59.                 {
  60.                     state = STATE_DOWN;
  61.                     min_y++;
  62.                     y++;
  63.                 }
  64.                 else
  65.                 {
  66.                     x++;
  67.                 }
  68.                 start_n++;
  69.                 count++;
  70.                 break;
  71.             case    STATE_DOWN:
  72.                 if( y == max_y )
  73.                 {
  74.                     state = STATE_LEFT;
  75.                     x--;
  76.                     max_x--;
  77.                 }
  78.                 else
  79.                 {
  80.                     y++;
  81.                 }
  82.                 start_n++;
  83.                 count++;
  84.                 break;
  85.             case    STATE_LEFT:
  86.                 if( x == min_x )
  87.                 {
  88.                     state = STATE_UP;
  89.                     y--;
  90.                     max_y--;
  91.                 }
  92.                 else
  93.                 {
  94.                     x--;
  95.                 }
  96.                 start_n++;
  97.                 count++;
  98.                 break;
  99.             case    STATE_UP:
  100.                 if( y == min_y )
  101.                 {
  102.                     state = STATE_RIGHT;
  103.                     x++;
  104.                     min_x++;
  105.                 }
  106.                 else
  107.                 {
  108.                     y--;
  109.                 }
  110.                 start_n++;
  111.                 count++;
  112.                 break;
  113.         }
  114.     }
  115. }
  116. //-------------------------------------------------------------------
  117. void    show_matrix( int** m, size_t width, size_t height )
  118. {
  119.     size_t  max = width* height;
  120.     int column_width = 1;
  121.     //  Вычислим максимальное количество цифр, которое нам понадобится
  122.     while( max >=10 )
  123.     {
  124.         max = max / 10;
  125.         column_width++;
  126.     }
  127.     printf("Матрица %lux%lu\n", width, height );
  128.     for( size_t y = 0; y < height; y++ )
  129.     {
  130.         for( size_t x = 0; x < width; x++ )
  131.         {
  132.             //printf( "[%02d]", m[y][x] );
  133.             printf( "[%0*d]", column_width, m[y][x] );
  134.         }
  135.         printf("\n");
  136.     }
  137. }
  138. //-------------------------------------------------------------------
  139. int**   alloc_matrix( int** matrix_buf, size_t width, size_t height )
  140. {
  141.     //  Массив для хранения данных матрицы MxN
  142.     int*    matrix;
  143.     //  Матрица width * height
  144.     int**   m = NULL;
  145.    
  146.     //  Очистим память
  147.     *matrix_buf = NULL;
  148.     //  Выделим память под буфер для хранения данных матрицы
  149.     matrix = (int*)malloc( sizeof(int) * width * height );
  150.     if( matrix )
  151.     {
  152.         //  Очистим память для хранения данных матрицы
  153.         memset( matrix, 0, sizeof(int)* width * height );
  154.         //  Выделим память под массив указателей на строки матрицы
  155.         m = (int**)malloc( sizeof(int*) * height );
  156.         if( m )
  157.         {
  158.             //  Заполним массив указателей адресами начала строк матрицы
  159.             for( int i = 0; i < height; i++ )
  160.             {
  161.                 m[i] = &matrix[ i * width ];
  162.             }
  163.         }
  164.         else
  165.         {
  166.             free( matrix );
  167.             matrix = NULL;
  168.             perror("malloc:");
  169.         }
  170.         //  Сохраним указатель на буфер с данными матрицы
  171.         *matrix_buf = matrix;
  172.     }
  173.     else
  174.     {
  175.         perror("malloc:");
  176.     }
  177.     return  m;
  178. }
  179. //-------------------------------------------------------------------
  180. //  Преобразует число в виде строки в unsigned long
  181. //  Возвращает 1 в случае успеха и 0 при неудаче
  182. int str_to_ulong( char* str, unsigned long* ul )
  183. {
  184.     int result = 0;
  185.     //  Остаток строки
  186.     char*   tail;
  187.     unsigned long   n;
  188.  
  189.     //  Очистим мусор
  190.     *ul = 0;
  191.     errno = 0;
  192.     //  Попытаемся преобразовать строку в число
  193.     n = strtoul( str, &tail, 0 );
  194.     if( errno == 0 )
  195.     {
  196.         if( *tail == '\0' )
  197.         {
  198.             *ul = n;
  199.             result++;
  200.         }
  201.         else
  202.         {
  203.             if( tail == str )
  204.             {
  205.                 fprintf(stderr, "Строка '%s' не является числом!\n", str);
  206.             }
  207.             else
  208.             {
  209.                 fprintf(stderr, "В строке '%s' обнаружен мусор '%s'!\n",
  210.                         str, tail );
  211.             }
  212.         }
  213.     }
  214.     else
  215.     {
  216.         perror( "strtoul:" );
  217.     }
  218.  
  219.     return  result;
  220. }
  221. //-------------------------------------------------------------------
  222.  
  223. //-------------------------------------------------------------------
  224. int main( int argc, char* argv[] )
  225. {
  226.     //  Массив для хранения данных матрицы MxN
  227.     int*    matrix;
  228.     //  Матрица MxN
  229.     int**   m;
  230.     //  Ширина матрицы
  231.     size_t  width;
  232.     //  Высота матрицы
  233.     size_t  height;
  234.     unsigned long   start_n = 0;
  235.  
  236.     if( argc > 2 )
  237.     {
  238.         if( argc > 3 )
  239.         {
  240.             if( !str_to_ulong( argv[3], &start_n ) )
  241.             {
  242.                 fprintf(stderr,
  243.                     "Будет использовано начальное значение по умолчанию!\n");
  244.             }
  245.         }
  246.         if(str_to_ulong(argv[1], &width) && str_to_ulong(argv[2], &height))
  247.         {
  248.             //  Попытаемся выделить память под матрицу
  249.             m = alloc_matrix( &matrix, width, height );
  250.             if( m && matrix )
  251.             {
  252.                 printf( "Спиральное заполнение матрицы "
  253.                     "возрастающими числами начиная с %lu:\n", start_n );
  254.                 fill_matrix( m, width, height, start_n );
  255.                 show_matrix( m, width, height );
  256.                 free( m );
  257.                 free( matrix );
  258.             }
  259.         }
  260.     }
  261.     else
  262.     {
  263.         printf( "Программа заполняет матрицу по спирали числами\n" );
  264.         printf( "Использование:\n" );
  265.         printf( "%s ширина высота [начальное_число]\n", argv[0] );
  266.     }
  267.     return  0;
  268. }
  269. //-------------------------------------------------------------------
  270.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement