get columns quantity for each row of array

Greetings!
I have some data included in array with 100 rows and 100 columns.
i need to roll through all of rows and columns, but i dont know actual columns quantity
How can i get quantity of columns,as i get quantity of rows by size()

#include<iostream>
using namespace std;

int main()
{
// an array with 3 rows and 2 columns.
int x[100][100] = {{0,1}, {2,3}, {4,5}};
}
In C/C++, in a 2D array, each "row" has the exactly same number of "columns".

You can get the total size of array, in bytes, with the sizeof() operator. To get the number of elements, in each dimension, some calculations are needed. This is best done with a helper macro. See here, for an example:
https://stackoverflow.com/a/34135270
Last edited on
i have different column number for each row in this array, how can i get column quantity?
No, you don't! At least if the array was defined as in your example code ;-)

In C/C++, a "2D" array is defined as int array[N][M], and in this array each of the N "rows" has exactly M "columns". It's as simple as that. It is not possible to have different number of "columns" in a "row".

If you really want a different number of columns for each row, then instead of using a "2D" array, you have to use an array of pointers and allocate a separate buffer, e.g. via new operator, for each row:
1
2
3
4
5
6
int *array[N];
for (size_t i = 0; i < N; ++i)
{
    size_t m = get_number_of_columns_for_row(i);
    array[i] = new int[m];
}


Don't forget to delete[] the buffers, or you will get a memory leak!
Last edited on
i have different column number for each row in this array, how can i get column quantity?
You need store these sizes separately [in it's own 1d-array].
if i use vector of vectors?
how can i get column quantityy?
If you use std::vector, then you can get the size, i.e. number of elements, via vector.size().

But be aware that an std::vector is something different from a "raw" array!

Anyway, std::vector can be nested:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
std::vector<int> inner_a;
inner_a.push_back(42);

std::vector<int> inner_b;
inner_b.push_back(666);
inner_b.push_back(13);

std::vector<std::vector<int>> outer;
outer.push_back(inner_a);
outer.push_back(inner_b);

for (size_t i = 0; i < outer.size(); ++i) // <-- loop "outer" vector (vector of vectors)
{
	std::vector<int> &inner = outer[i];
	for (size_t j = 0; j < inner.size(); ++j) // <-- loop the current "inner" vector
	{
		std::cout << '[' << i << ',' << j << "] = " << inner[j] << std::endl;
	}
}
Last edited on
sorry! i actually use vector of vectors, so dumb to mention array :)
I need to loop through this
std::vector<std::vector<cv::Point> > contours3 {{{1,2},{3,4},{5,6}}};
Well, see std::vector sample code above!
Last edited on
bro, no clue how to amend your sample to my case :) please assisst :)
For example:
1
2
3
4
5
6
7
8
9
for (size_t i = 0; i < contours3.size(); ++i)
{
	std::vector<cv::Point> &currentRow = outer[i];
	for (size_t j = 0; j < currentRow.size(); ++j)
	{
		cv::Point &point = currentRow[j];
                do_whatever_with(point);
	}
}


You could also work with iterators here:
https://www.cplusplus.com/reference/vector/vector/begin/
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <vector>
#include <iostream>

struct Point {
	int x {}, y {};
};

std::ostream& operator<<(std::ostream& os, const Point& p) {
	return os << '(' << p.x << ',' << p.y << ')';
}

int main() {
	const std::vector<std::vector<Point> > contours3 {{{1,2},{3,4},{5,6}}};

	for (const auto& c1 : contours3)
		for (const auto& c2 : c1)
			std::cout << c2 << ' ';

	std::cout << '\n';
}



(1,2) (3,4) (5,6)

If you have vector< vector<T> > A (and it is not ragged) then:
- the number of rows is A.size()
- the number of columns is A[0].size()
Last edited on
Using regular for loops for a 2D vector:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <vector>

int main()
{
   std::vector<std::vector<int>> vec { { 1, 2, 3 }, { 4, 5 }, { 6, 7, 8, 9 } };

   for (size_t row { }; row < vec.size(); ++row)
   {
      std::cout << vec[row].size() << ": ";
      
      for (size_t col { }; col < vec[row].size(); ++col)
      {
         std::cout << vec[row][col] << ' ';
      }

      std::cout << '\n';
   }
}
3: 1 2 3
2: 4 5
4: 6 7 8 9

Using iterators in for loops:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <vector>

int main()
{
   std::vector<std::vector<int>> vec { { 1, 2, 3 }, { 4, 5 }, { 6, 7, 8, 9 } };

   for (auto row { vec.cbegin() }; row != vec.cend(); ++row)
   {
      std::cout << row->size() << ": ";
      
      for (auto col { row->cbegin() }; col != row->cend(); ++col)
      {
         std::cout << *col << ' ';
      }

      std::cout << '\n';
   }
}

Using range-based for loops:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <vector>

int main()
{
   std::vector<std::vector<int>> vec { { 1, 2, 3 }, { 4, 5 }, { 6, 7, 8, 9 } };

   for (const auto& row : vec)
   {
      std::cout << row.size() << ": ";
      
      for (const auto& col : row)
      {
         std::cout << col << ' ';
      }

      std::cout << '\n';
   }
}

We could get really fancy and override iostream's insertion operator<< to make displaying a 2D vector as easy as POD (Plain Old Data) like an int.
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
#include <iostream>
#include <vector>

template <typename T>
std::ostream& operator<<(std::ostream&, const std::vector<T>&);
template <typename T>
std::ostream& operator<<(std::ostream&, const std::vector<std::vector<T>>&);

int main()
{
   std::vector<std::vector<int>> vec { { 1, 2, 3 }, { 4, 5 }, { 6, 7, 8, 9 } };

   std::cout << vec;
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v)
{
   std::cout << v.size() << ": ";

   for (auto const& x : v)
   {
      os << x << ' ';
   }

   return os;
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<std::vector<T>>& v)
{
   for (auto const& x : v)
   {
      os << x << '\n';
   }

   return os;
}

One beneficial side effect of overriding operator<< to display a 2D vector is the code for displaying a 1D vector is already written code:
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
#include <iostream>
#include <vector>

template <typename T>
std::ostream& operator<<(std::ostream&, const std::vector<T>&);
template <typename T>
std::ostream& operator<<(std::ostream&, const std::vector<std::vector<T>>&);

int main()
{
   std::vector vec { 1, 2, 4, 20, 9 };

   std::cout << vec << '\n';
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v)
{
   std::cout << v.size() << ": ";

   for (auto const& x : v)
   {
      os << x << ' ';
   }

   return os;
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<std::vector<T>>& v)
{
   for (auto const& x : v)
   {
      os << x << '\n';
   }

   return os;
}
5: 1 2 4 20 9

Please note line 11 uses a C++17 deduction guide to determine the type.
https://en.cppreference.com/w/cpp/container/vector/deduction_guides

When creating a multi-dimensional container OTOH the type must be specified, as it was in the previous code snippets.
This thread is kinda crazy, anything beyond https://www.cplusplus.com/forum/beginner/283582/#msg1227829 just seems like noise, as that post explains all.
You could just have a regular 2D array with a maximal number of available columns and only use as many columns as necessary.

Keeping track of the number of columns used per row can be done any number of ways: a sentinal value to terminate the row, using the first elemnt of the row for the count, using yet another array for number of rows, using a large struct with size+array for each row, etc.

The vector of vector is your nicest option in C++, though...
Topic archived. No new replies allowed.