// Необходимо заполнить матрицу MxN числами по спирали #include #include // memset #include // malloc, strtoul #include // Для обработки ошибок преобразования строки в число #define M 5 // Ширина #define N 4 // Высота // Состояние конечного автомата #define STATE_RIGHT 0 #define STATE_DOWN 1 #define STATE_LEFT 2 #define STATE_UP 3 //------------------------------------------------------------------- // Прототипы функций //------------------------------------------------------------------- // Выделяет память под массив matrix_buf, в котором будут храниться данные // матрицы размером width на height элементов и под массив указателей // на строки в массиве matrix_buf // Возвращает указатели на выделенную память или NULL при неудаче int** alloc_matrix( int** matrix_buf, size_t width, size_t height ); // Заполняет матрицу шириной width и высотой height числами по спирали, // начиная с числа start_n. В каждой последующей ячейке start_n // увеличивается на единицу void fill_matrix( int** m, size_t width, size_t height, int start_n ); // Выводит матрицу в stdout void show_matrix( int** m, size_t width, size_t height ); // Преобразует число в виде строки в unsigned long // Возвращает 1 в случае успеха и 0 при неудаче int str_to_ulong( char* str, unsigned long* ul ); //------------------------------------------------------------------- //------------------------------------------------------------------- // Реализация функций //------------------------------------------------------------------- void fill_matrix( int** m, size_t width, size_t height, int start_n ) { // Нам нужно заполнить не более чем width * height ячеек size_t max = width * height; // Количество заполненных ячеек size_t count = 0; size_t state = STATE_RIGHT; size_t x = 0; size_t min_x = 0; size_t max_x = width - 1; size_t y = 0; size_t min_y = 0; size_t max_y = height - 1; while( count < max ) { m[y][x] = start_n; switch( state ) { // Движемся слева на право case STATE_RIGHT: if( x == max_x) { state = STATE_DOWN; min_y++; y++; } else { x++; } start_n++; count++; break; case STATE_DOWN: if( y == max_y ) { state = STATE_LEFT; x--; max_x--; } else { y++; } start_n++; count++; break; case STATE_LEFT: if( x == min_x ) { state = STATE_UP; y--; max_y--; } else { x--; } start_n++; count++; break; case STATE_UP: if( y == min_y ) { state = STATE_RIGHT; x++; min_x++; } else { y--; } start_n++; count++; break; } } } //------------------------------------------------------------------- void show_matrix( int** m, size_t width, size_t height ) { size_t max = width* height; int column_width = 1; // Вычислим максимальное количество цифр, которое нам понадобится while( max >=10 ) { max = max / 10; column_width++; } printf("Матрица %lux%lu\n", width, height ); for( size_t y = 0; y < height; y++ ) { for( size_t x = 0; x < width; x++ ) { //printf( "[%02d]", m[y][x] ); printf( "[%0*d]", column_width, m[y][x] ); } printf("\n"); } } //------------------------------------------------------------------- int** alloc_matrix( int** matrix_buf, size_t width, size_t height ) { // Массив для хранения данных матрицы MxN int* matrix; // Матрица width * height int** m = NULL; // Очистим память *matrix_buf = NULL; // Выделим память под буфер для хранения данных матрицы matrix = (int*)malloc( sizeof(int) * width * height ); if( matrix ) { // Очистим память для хранения данных матрицы memset( matrix, 0, sizeof(int)* width * height ); // Выделим память под массив указателей на строки матрицы m = (int**)malloc( sizeof(int*) * height ); if( m ) { // Заполним массив указателей адресами начала строк матрицы for( int i = 0; i < height; i++ ) { m[i] = &matrix[ i * width ]; } } else { free( matrix ); matrix = NULL; perror("malloc:"); } // Сохраним указатель на буфер с данными матрицы *matrix_buf = matrix; } else { perror("malloc:"); } return m; } //------------------------------------------------------------------- // Преобразует число в виде строки в unsigned long // Возвращает 1 в случае успеха и 0 при неудаче int str_to_ulong( char* str, unsigned long* ul ) { int result = 0; // Остаток строки char* tail; unsigned long n; // Очистим мусор *ul = 0; errno = 0; // Попытаемся преобразовать строку в число n = strtoul( str, &tail, 0 ); if( errno == 0 ) { if( *tail == '\0' ) { *ul = n; result++; } else { if( tail == str ) { fprintf(stderr, "Строка '%s' не является числом!\n", str); } else { fprintf(stderr, "В строке '%s' обнаружен мусор '%s'!\n", str, tail ); } } } else { perror( "strtoul:" ); } return result; } //------------------------------------------------------------------- //------------------------------------------------------------------- int main( int argc, char* argv[] ) { // Массив для хранения данных матрицы MxN int* matrix; // Матрица MxN int** m; // Ширина матрицы size_t width; // Высота матрицы size_t height; unsigned long start_n = 0; if( argc > 2 ) { if( argc > 3 ) { if( !str_to_ulong( argv[3], &start_n ) ) { fprintf(stderr, "Будет использовано начальное значение по умолчанию!\n"); } } if(str_to_ulong(argv[1], &width) && str_to_ulong(argv[2], &height)) { // Попытаемся выделить память под матрицу m = alloc_matrix( &matrix, width, height ); if( m && matrix ) { printf( "Спиральное заполнение матрицы " "возрастающими числами начиная с %lu:\n", start_n ); fill_matrix( m, width, height, start_n ); show_matrix( m, width, height ); free( m ); free( matrix ); } } } else { printf( "Программа заполняет матрицу по спирали числами\n" ); printf( "Использование:\n" ); printf( "%s ширина высота [начальное_число]\n", argv[0] ); } return 0; } //-------------------------------------------------------------------