Найти сумму элементов выше главной диагонали через указатель на массив
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 шт):
Попробовал решить, получился такой код:
#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. Возможно есть более компактный код, как смог)
Просто, вместо элементов используйте указатели:
int k = 0, sum = 0;
while (k < X - 1) {
for (int* first = &c[k][k] + 1; first != c[k + 1]; ++first) {
sum += *first;
}
++k;
}
Решил тремя способами. По-скольку в заданном вопросе стоит метка с++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;
}