0

Как реализовать цикл с помощью указателей без использования i,j? Примерно таким методом(если получится)

int *p; ... for (p = &a[0][0]; p <= &a[NUM_ROWS-1][NUM_COLS-1]; p++)

int schet = 0;

for (int i = 0; i < cols - 1; i++) { for (int j = i + 2; j < cols; j++) { if (matrix[i][j] != 0) schet++; }

}

qqueeez
  • 27

2 Answers2

0
for (int ** i = matrix; i != matrix + cols - 1; i++) {
    for (int * j = *i; j != *i + cols; j++) {
        if (*j != 0) {
            schet++;
        }
    }
}

i проходит по указателям на строки матрицы, а j по самим строкам.

  • добро пожаловать на Stack Overflow на русском! пожалуйста, постарайтесь оставлять чуть более развёрнутые ответы. дополнить ответ можно, нажав [edit] – aleksandr barakin May 29 '22 at 10:26
0

Как раз таким методом, как вы просили:

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

#define NUM_ROWS 3 #define NUM_COLS 5

int main() { //динамически выделяем память под матрицу NUM_ROWSNUM_COLS int (matrix)[NUM_COLS] = new int[NUM_ROWS][NUM_COLS];

//для примера: заполняем матрицу случайными значениями [-3..4]...
//...и выводим её
srand(time(NULL));
puts(&quot;Matrix:&quot;);
for (int i=0; i&lt;NUM_ROWS; ++i)
{
    for (int j=0; j&lt;NUM_COLS; ++j)
        printf(&quot;%2d &quot;, matrix[i][j] = (rand()&amp;7) - 3);
    puts(&quot;&quot;);
}
puts(&quot;&quot;);

//подсчитываем количество ненулевых элементов, используя указатель
int schet = 0;
for (int* p = &amp;matrix[0][0]; p &lt; &amp;matrix[NUM_ROWS][0]; ++p)
    if (*p) ++schet;

//выводим результат
printf(&quot;Number of the non-zero elements is %d!\n&quot;, schet);

//освобождаем память
delete[] matrix;

return 0;

}

Поясню. Матрица с размером MxN в C/C++ представляется в памяти, как обычный одномерный массив из M*N элементов. Соответственно, выражение [i][j] преобразуется компилятором в [i*N+j], где N - число столбцов (а M, соответственно, это число строк). Следовательно, с помощью указателя мы можем пройтись по матрице, как по одномерному массиву, начиная с элемента [0][0] (который имеет эквивалентный индекс 0 в одномерном массиве) и заканчивая элементом [NUM_ROWS-1][NUM_COLS-1] (эквивалентный индекс которого (NUM_ROWS-1)*NUM_COLS+(NUM_COLS-1) = NUM_ROWS*NUM_COLS-1). Несуществующий "элемент", следующий за последним (которого мы не должны достигнуть), соответственно имеет двухмерный индекс [NUM_ROWS][0] (потому что NUM_ROWS*NUM_COLS, как известно - это количество элементов в матрице).

LShadow77
  • 2,157
  • Не могли бы вы дать ответ в вопросе по ссылке,там указан полный код программы, и подробное задание,прошу прощение за неудобства. Тут немного не то что нужно,я так понимаю у вас цикл пробегается по всем элементам матрицы и подсчитывает количество ненулевых элементов. Также, можно ли обойтись без "puts" пока еще не знаком с этим. https://ru.stackoverflow.com/questions/1414829/%d0%a3%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d0%b8-%d0%bd%d0%b0-%d0%b4%d0%b2%d1%83%d0%bc%d0%b5%d1%80%d0%bd%d1%8b%d0%b5-%d0%bc%d0%b0%d1%81%d1%81%d0%b8%d0%b2%d1%8b/1414873#1414873 – qqueeez May 29 '22 at 13:03
  • Заголовок вопроса "Указатели на двумерные массивы",я новый пользователь,не в курсе, возможно ссылки не отображаются – qqueeez May 29 '22 at 13:06
  • @qqueeez ответил в контексте данного вопроса. А puts("") - то же самое, что printf("\n"), переход на следующую строку при выводе. – LShadow77 May 29 '22 at 13:10
  • 1
    Работа с двумерным массивом как с одномерным, формально вызывает неопределённое поведение. Поведение выражения &matrix[NUM_ROWS][0] также не определено. – wololo May 30 '22 at 18:15
  • @wololo Если так, то уж очень формально. Настолько формально, что это ub фактически можно не брать в расчёт. Ведь написано же чётко: "consists of a contiguously allocated", т.е. n-мерный массив можно смело "растягивать" в одномерный. Хотя я, к примеру, всё же предпочитаю представлять матрицы в виде исключительно одномерных массивов и явно вычислять индексы типа i*NUM_COLS+j. А ещё лучше (i<<pitch_shift) | j, для пущей производительности. – LShadow77 May 31 '22 at 15:58
  • это ub фактически можно не брать в расчёт Возможно так и есть. Ведь написано же чётко: "consists of a contiguously allocated", т.е. n-мерный массив можно смело "растягивать" в одномерный. Знание фактического расположения объектов в памяти относительно друг друга не гарантирует, что некое UB будет работать ожидаемым образом. Просто для примера: 1, 2. – wololo May 31 '22 at 22:54
  • @wololo ха, так первый пример не про массивы, а про то, в каком порядке компилятор распределяет переменные в памяти - это другое. А второй пример вообще должен выдать синтаксическую ошибку, и он так же про другое. – LShadow77 Jun 01 '22 at 11:08
  • @LShadow77, эти примеры про то, что знание фактического расположения объектов в памяти относительно друг друга не гарантирует корректность работы с указателями. второй пример вообще должен выдать синтаксическую ошибку Какую? – wololo Jun 03 '22 at 21:15
  • @wololo "что знание фактического расположения объектов в памяти"... Мы знаем, что элементы массивов и матриц следуют в памяти один за другим - про это сказано в документации. Но как именно компилятор располагает в памяти отдельные переменные, как раз таки мы не знаем! Даже если, допустим, они следуют в порядке объявления, то как минимум между ними может оказаться заранее неизвестное выравнивание, зависящее от компилятора и платформы, под которую компилируем. По-этому пример 1 вызывает реальное ub, а не формальное, как в случае с указателями на элементы матрицы. – LShadow77 Jun 03 '22 at 23:01
  • @wololo int* p1 = malloc(sizeof(int)); - error: invalid conversion from 'void*' to 'int*'. То же самое с realloc(). – LShadow77 Jun 03 '22 at 23:06
  • @wololo однако, не смотря на приведённые вами не совсем удачные примеры, c утверждением "знание фактического расположения объектов в памяти относительно друг друга не гарантирует корректность работы с указателями" я всё же вынужден согласиться. Вернее, я бы так выразился: *не всегда* гарантирует. Потому что всё испортить может его вреднейшество Оптимизатор. И я с таким примером однажды столкнулся на личном опыте: https://ru.stackoverflow.com/q/1105521/381066 (мой первый вопрос на SO, кстати)) ) – LShadow77 Jun 03 '22 at 23:32
  • Мы знаем, что элементы массивов и матриц следуют в памяти один за другим - про это сказано в документации — это не важно. Да, между подмассивами нет паддингов, но это не важно. Не могу понять вашу логику. Каким образом из непрерывности матрицы следует законность произвольных манипуляций с указателем? Когда в стандарте языка написано ровно противоположное: The behavior is undefined ... An array subscript is out of range, even if an object is apparently accessible with the given subscript (as in the lvalue expression a[1][7] given the declaration int a[4][5]). – wololo Jun 05 '22 at 13:43
  • Вся формальность этого UB состоит только в том, что компилятор обрабатывает данное UB ожидаемым образом. По крайней мере пока. Обратите внимание, что в первом примере фактически никаких паддингов между двумя переменными нет. И два побайтово равных указателя (memcmp возвращает ноль) при сравнении оператором == оказываются неравными. int* p1 = malloc(sizeof(int)); — это код на языке C. – wololo Jun 05 '22 at 13:44