Найти сумму элементов выше главной диагонали через указатель на массив

const int X = 3;
int c[X][X] = { 3,4,8,
               -2,5,6,
                1,2,3 };
int *pc;
pc = c[0];

Нужно найти сумму элементов выше главной диагонали, используя указатель на массив pc, сказали, что можно обойтись одним циклом, если использовать в цикле for pc. Я только до этого додумалась

for (int i = 0; i < X - 1; ++i) for (int j = i + 1; j < X; ++j) sum += *(*(c + i) + j); Но мне надо как-то обойтись без i и j в for, решать через указатель на массив


Ответы (3 шт):

Автор решения: Smoliarick

Попробовал решить, получился такой код:

#include <iostream>

int main() {
    const int X = 4;

    int c[X][X] = { {3,4,8,4}, {-2,5,6,4}, {1,2,3,4}, {1,2,3,4} };
    int* end = c[0] + X * X - 1; // указатель на последний элемент массива
    int sum = 0;
    for (int* pc = c[0], index = 0, col = 0; pc <= end; pc++, col++) {
        if (col <= X - 1 && col >= index) {
            sum += *pc;
        }

        if (col == X - 1) {
            index++;
            col = -1;
        }
    }
    std::cout << "Sum = " << sum << std::endl;
    return 0;
}

Что есть что:

  • end - это указатель на последний элемент массива
  • pc - непосредственно указывает на сам элемент
  • index - указывает с какого элемента (по порядку) строки надо прибавлять - т.е показывает находимся ли мы выше главное диагонали или нет при сравнении (если необходимо исключить диагональ из суммы, то оставляем строгое неравенство col > index)
  • col - указывает на каком элементе (по порядку) строки мы находимся (при достижении конца строки обнуляется)

P.S. Возможно есть более компактный код, как смог)

→ Ссылка
Автор решения: AR Hovsepyan

Просто, вместо элементов используйте указатели:

int k = 0, sum = 0;
while (k < X - 1) {
    for (int* first = &c[k][k] + 1; first != c[k + 1]; ++first) {
        sum += *first;           
    }  
    ++k;       
}
→ Ссылка
Автор решения: Majestio

Решил тремя способами. По-скольку в заданном вопросе стоит метка с++11, я бы рекомендовал первый способ. Но, если это какое-то учебное задание - то лучше преподу первый способ не показывать, положительно не оценит.

EDIT: В комментариях есть хороший вариант оптимизации проверки индекса!

Способ 1 (без явных циклов)

#include <algorithm>
#include <iostream>
#include <iterator>
#include <numeric>
#include <vector>

using namespace std;

const int X = 6;

int main() {
  std::vector<int> v = {
     0,  1,  2,  3,  4,  5,
     6,  7,  8,  9, 10, 11,
    12, 13, 14, 15, 16, 17,
    18, 19, 20, 21, 22, 23,
    24, 25, 26, 27, 28, 29,
    30, 31, 32, 33, 34, 35
  };

  int sum = std::accumulate(v.begin(), std::partition(v.begin(), v.end(), [] (int i) {
    return ((((i % X) > (i % (X+1))) && ((i % (X+1))!=0)) || (i>0 && i<X));
  }), 0);

  cout << sum;
}

Запустить

Способ 2.1 (с одним циклом, используя int-счетчик)

#include <iostream>

using namespace std;

const int X = 6;

int main() {

  #pragma pack(push, sizeof(int))

  int c[X][X] = {
     0,  1,  2,  3,  4,  5,
     6,  7,  8,  9, 10, 11,
    12, 13, 14, 15, 16, 17,
    18, 19, 20, 21, 22, 23,
    24, 25, 26, 27, 28, 29,
    30, 31, 32, 33, 34, 35
  };

  #pragma pack(pop)

  int sum=0;

  for(int i=0; i<X*X; i++)
    if (((((i % X) > (i % (X+1))) && ((i % (X+1))!=0)) || (i>0 && i<X))) 
      sum += (*(int*)c+i);

  cout << sum;
}

Запустить

Способ 2.2 (с одним циклом, не используя int-счетчик)

#include <iostream>
using namespace std;

const int X = 6;

int main() {

  #pragma pack(push, sizeof(int)) 

  int c[X][X] = {
     0,  1,  2,  3,  4,  5,
     6,  7,  8,  9, 10, 11,
    12, 13, 14, 15, 16, 17,
    18, 19, 20, 21, 22, 23,
    24, 25, 26, 27, 28, 29,
    30, 31, 32, 33, 34, 35
  };

  #pragma pack(pop)

  int sum = 0;

  int *curr  = (int*)c;
  int *first = (int*)c;
  int *last  = first+(X*X);

  for(; curr<last; curr++)
    if ((((((curr-first) % X) > ((curr-first) % (X+1))) && (((curr-first) % (X+1))!=0)) ||
        ((curr-first)>0 && (curr-first)<X))) 
      sum += *curr;

  cout << sum;
}

Запустить

→ Ссылка