Using STL on matrix?

Hello. May I use STL algorithm on char matrix?

1
2
3
4
5
6
7
8
9
10
11
12
13
  bool isdot(const char &s)
{
	return s == '.';
}


int main()
{
	char matrix[100][100];
do
{
//...
} while (!all_of(matrix, matrix + n, isdot));
Last edited on
yeah, a matrix is just a chunk of memory as well.

just like any algorithm: std::all_of(matrix, matrix + 100*100, isdot);
Last edited on
error C2664: 'bool (const char &)' : cannot convert argument 1 from 'char [100]' to 'const char &'
hm... try it like this:
std::all_of(matrix[0], matrix[0] + 100*100, isdot);
You need to pass the address of the first char element (a char*) to all_of().

1
2
3
4
5
6
7
char matrix[100][100];

const int elem_count = sizeof(matrix)/sizeof(matrix[0][0]);
// i.e. elem count = size of whole matrix / size of one element

std::all_of(matrix[0], matrix[0] + elem_count, isdot);
// 100*100 is dangerous 


or

6
7
std::all_of(&matrix[0][0], &matrix[0][0] + elem_count, isdot);
// 100*100 is dangerous 


(I prefer the latter; more long winded but clearer to me?)

Andy

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <iostream>
#include <string>
#include <algorithm>
#include <cstdlib>
using namespace std;

// not worth using const ref for a char
// (unlike a std::string)
bool isdot(char ch)
{
    return ch == '.';
}

template<int R, int C>
void dump(char (&matrix)[R][C])
{
    for(int r = 0; r < R; ++r)
    {
        for(int c = 0; c < C; ++c)
        {
            cout << " " << matrix[r][c];
        }
        cout << "\n";
    }
}

int main()
{
    srand(123); // use fixed seed for testing

    const int row_count = 3;
    const int col_count = 4;

    char matrix[row_count][col_count];

    int elem_count = sizeof(matrix)/sizeof(matrix[0][0]);

    fill_n(&matrix[0][0], elem_count, '_');

    do
    {
        dump(matrix);
        cout << "\n";

        int r = (rand() % row_count);
        int c = (rand() % col_count);
        cout << "set ["<< r << "][" << c << "]\n\n";
        matrix[r][c] = '.';
    }
    while (!all_of(&matrix[0][0], &matrix[0][0] + elem_count, isdot));

    cout << "final result:"
         << "\n";

    dump(matrix);

    return 0;
}

Last edited on
Thank you both. This seems to work. But I still don't get what does this do:
int elem_count = sizeof(matrix)/sizeof(matrix[0][0]);
sizeof matrix gives you the total size of the matrix and sizeof matrix[0][0] gives you the size of a single element in matrix.

with that you can count the number of elements in your matrix.
number_of_elements = total_space / space_from_1_element
Last edited on
sizeof matrix gives you the total size of the matrix and sizeof matrix[0][0] gives you the size of a single element in matrix.


So, sizeof(matrix) is always 100*100? And sizeof(matrix[0][0]) is 1? Still don't get why I need to do this.
Also, how could I use functions on diagonals or rows?
Traversing a row would be easy, as you may simply use the pointers to the start of the rows as iterators [beg, end)
By instance std::all_of( &matrix[K][0], &matrix[K+1][0], isdot)

For columns and diagonals, I suppose that you'll need to code your own iterator.
I have some issues when comparing with end (considering that the algorithms may use the == operator)
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include <iostream>
#include <iterator>
#include <algorithm>

class step_iterator
	: public std::iterator<
		std::forward_iterator_tag,
		int
	>
{
public:
	step_iterator():
		here(nullptr),
		step(0)
	{}
	step_iterator(pointer here, difference_type step=0):
		here(here),
		step(step)
	{}
	reference operator*(){
		return *here;
	}
	step_iterator operator++(){
		here += step;
		return *this;
	}
	step_iterator operator++(int){
		step_iterator it(*this);
		++it;
		return it;
	}
	//iterators from different containers are not comparable
	bool operator==(const step_iterator &that){
		if(this->is_end() and that.is_end())
			return true;
		if(this->is_end())
			return this->here <= that.here;
		if(that.is_end())
			return that.here <= this->here;

		return this->here == that.here;
	}

	bool operator not_eq(const step_iterator &that){
		return not (*this == that);
	}

	pointer operator->(){
		return here;
	}
private:
	pointer here;
	difference_type step;
	bool is_end() const{
		return step==0;
	}
};

template<class Iter>
void print(Iter beg, Iter end, std::ostream &out = std::cout){
	std::copy(
		beg, 
		end,
		std::ostream_iterator<
			typename std::iterator_traits<Iter>::value_type
		> (out, " ")
	);

	out << '\n';
}

int main(){
	const int n = 3;
	int m[3][3];
	for(int K=0; K<n; ++K)
		for(int L=0; L<n; ++L)
			m[K][L] = K*n+L;

	//show all
	for(int K=0; K<n; ++K){
		for(int L=0; L<n; ++L)
			std::cout << m[K][L] << ' ';
		std::cout << '\n';
	}

	std::cout << "one row\n";
	print(&m[2][0], &m[3][0]);

	std::cout << "one column\n";
	print(
		step_iterator(&m[0][1], n),
		step_iterator(&m[n][0])
	);

	std::cout << "diagonal\n";
	print(
		step_iterator(&m[0][0], n+1),
		step_iterator(&m[n][0])
	);

	std::cout << "another diagonal\n";
	print(
		step_iterator(&m[0][1], n-1),
		step_iterator(&m[n][0]-1)
	);
}
0 1 2 
3 4 5 
6 7 8 
one row
6 7 8 
one column
1 4 7 
diagonal
0 4 8 
another diagonal
1 3 5 7 
(you may also note the issue when doing the diagonal to the left)


> So, sizeof(matrix) is always 100*100? And sizeof(matrix[0][0]) is 1? Still don't get why I need to do this.
Because later you may want to change the size of the matrix, or its type.
That way you need to touch less code, so it's less error prone
Last edited on
Topic archived. No new replies allowed.