Эта тема возникла на основе исходного вопроса на Stackoverflow по ссылке
Printing an array sideways (transpose) only using pointers В заголовке темы трудно передать полностью смысл задания, поэтому опишу его более подробно. Имеется массив массивов
All, как это задано в исходном вопросе
int A[] = { 5,-5,14,5,2 };
int B[] = { 3,6,11 };
int C[] = { 4,1,-3,4 };
int D[] = { 6,2,7,1,8,2 };
int E[] = { 2,15 };
int F[] = { 3,4,-2 };
int *All[] = { A,B,C,D,E,F,NULL };
Последней элемент массива
All является нуль-указателем, то есть граничным значением массива.
Требуется вывести этот массива на консоль без использования синтаксиса индексации элементов массива, а используя только указатели, операцию разыменования указателей и арифметику указателей. Как сказано в исходном вопросе на Stackoverflow
цитата: |
only using pointers, even int i as an index is unaccepted. |
|
даже объявления целочисленных переменных, как, например,
int i;
запрещены.
Первый элемент каждого под-массива содержит число элементов в под-массиве и не должен выводиться на консоль..
То есть вывод должен выглядеть следующим образом:
-5 6 1 2 15 4
14 11 -3 7 -2
5 4 1
2 8
2
Сделайте в этом месте паузу и попробуйте написать такую функцию вывода самостоятельно.
----------------------------------------------------------------------------------------------------------------------
Если у вас не получилось, то для начала будет проще написать функцию вывода с использованием индексации массивов, чтобы на основе этой функции написать функцию, которая использует только индексы.
Ниже приведена демонстрационная программа.
#include <stdio.h>
void print_transpose( int *a[] )
{
int n = 0;
while ( a[n] ) ++n;
if ( n )
{
int m = a[0][0];
for ( int j = 1; j < n; j++ )
{
if ( m < a[j][0] ) m = a[j][0];
}
if ( m ) --m;
for ( int i = 0; i < m; i++ )
{
for ( int j = 0; j < n; j++ )
{
if ( i + 1 < a[j][0] )
{
printf( "%2d ", a[j][i + 1] );
}
else
{
printf( "%3c", ' ' );
}
}
putchar( '\n' );
}
}
}
int main( void )
{
int A[] = { 5, -5, 14, 5, 2 };
int B[] = { 3, 6, 11 };
int C[] = { 4, 1, -3, 4 };
int D[] = { 6, 2, 7, 1, 8, 2 };
int E[] = { 2, 15 };
int F[] = { 3, 4, -2 };
int *All[] = { A, B, C, D, E, F, NULL };
print_transpose( All );
}
Ее вывод на консоль, как и требуется, выглядит следующим образом
-5 6 1 2 15 4
14 11 -3 7 -2
5 4 1
2 8
2
Сначала в этом предложении
while ( a[n] ) ++n;
определяется сколько актуальных элементов (под-массивов) содержит исходный массив, то есть не является ли он пустой. Это значение также задает число колонок выводимых под-массивов.
Если массив содержит под-массивы, то вычисляется максимальное значение для возможного числа строк.
if ( n )
{
int m = a[0][0];
for ( int j = 1; j < n; j++ )
{
if ( m < a[j][0] ) m = a[j][0];
}
if ( m ) --m;
//...
Так как первый (нулевой) элемент каждого под-массива не выводится на консоль, так как он содержит число элементов в под-массиве, то максимальное число строк, заданное в переменной
m, уменьшается на единицу.
Итак, мы имеем общее число строк и колонок в выводимой таблице. Все, что теперь требуется при выводе конкретного элемента под-массива, - это проверить не выходит ли индекс общего числа строк значение для числа элементов в под-массиве, содержащим этот элемент.
Как теперь написать тоже самое, но с использованием только указателей и арифметики указателей?
Очевидно, что необходимо найти тот под-массив (указатель на него), который содержит больше всего элементов. Зная этот под-массив, не трудно с помощью указателей записать предложения циклов и выражения обращения к каждому выводимому элементу.
Ниже показано, как в этом случае функция вывода на консоль может выглядеть.
#include <stdio.h>
void print_transpose( int *a[] )
{
if ( *a )
{
int **m = a;
for ( int **j = a + 1; *j; ++j )
{
if ( **m < **j ) m = j;
}
for ( int *i = *m + 1 ; i < *m + **m; ++i )
{
for ( int **j = a; *j; j++ )
{
if ( i - *m < **j )
{
printf( "%2d ", *( *j + ( i - *m ) ) );
}
else
{
printf( "%3c", ' ' );
}
}
putchar( '\n' );
}
}
}
int main( void )
{
int A[] = { 5, -5, 14, 5, 2 };
int B[] = { 3, 6, 11 };
int C[] = { 4, 1, -3, 4 };
int D[] = { 6, 2, 7, 1, 8, 2 };
int E[] = { 2, 15 };
int F[] = { 3, 4, -2 };
int *All[] = { A, B, C, D, E, F, NULL };
print_transpose( All );
}
Итак, если исходный массив содержит актуальные элементы
if ( *a )
{
int **m = a;
for ( int **j = a + 1; *j; ++j )
{
if ( **m < **j ) m = j;
}
//...
мы находим тот под-массив, который содержит максимальное число элементов. А далее, используя арифметику указателей, выводим конкретные элементы под-массивов.-