用不同的值填充数组/矢量的边缘和中心

Fill edges and center of array/vector with different values

本文关键字:边缘 数组 填充      更新时间:2023-10-16

我想创建一个函数来初始化大小为width * height的向量或数组,但它也会在这些值周围创建边框。

外部周围的值也需要初始化为与中心值不同的值。

我存储的对象没有默认构造函数,因此我不能依赖它进行初始化。

这是我到目前为止的代码,但感觉应该有一种更简单或更惯用的方法。

我可以使用最多和包括 C++1z 在内的任何功能。

#include <iostream>
#include <vector>
void fill_values(const unsigned width, const unsigned height, std::vector<int> &values) {
for(unsigned y=0; y<height+2; ++y) {
for(unsigned x=0; x<width+2; ++x) {
if(x==0 || x==width+1 || y==0 || y==height+1) {
values.push_back(1);
} else {
values.push_back(0);
}
}
}
}
int main(int argc, char *argv[]) {
const unsigned width = 4;
const unsigned height = 3;
std::vector<int> values;
fill_values(width, height, values);
for(unsigned y=0; y<height+2; ++y) {
for(unsigned x=0; x<width+2; ++x) {
std::cout << values[y * (width+2) + x];
}
std::cout << 'n';
}
return 0;
}

输出:-

111111
100001
100001
100001
111111

老实说,你的代码很好。我很容易理解它的作用。

但本着提出替代复杂实现的精神,我会提出以下建议。填充矩阵的另一种方法是添加一整行 1,然后height添加一整行1000...001,然后是另一整行 1。我们可以更明确一点。另外,建议返回vector而不是填充它:

std::vector<int> fill_values(const unsigned width, const unsigned height) {
std::vector<int> m;
m.reserve((width + 2) * (height + 2));
// add row of 1s
m.insert(m.end(), width + 2, 1);
// add height middle rows
for (int i = 0; i < height; ++i) {
m.push_back(1);
m.insert(m.end(), width, 0);
m.push_back(1);
}
// and a final row of 1s
m.insert(m.end(), width + 2, 1);
return m;
}

正如@Fedorico评论中所说,使用向量向量是值变量的更好表示。 与其通过引用将值作为参数传递,不如依靠复制省略来获取返回值。 我还发现将设置的高度和宽度用作数据中的行和列的总数更容易,这样就无需添加两个。

以下代码依赖于 c++11 或更高版本:

#include <iostream>
#include <vector>
using namespace std;
// Fills the 2D matrix with 1s on the border and 0s in the middle.
vector<vector<int>> generate_matrix(int rows, int cols);
void print_matrix(const vector<vector<int>>& matrix);
int main()
{
// Don't sync I/O with C stdio.
ios_base::sync_with_stdio(false);
// Height and Width of the entire 2D matrix.
const int rows = 6;
const int cols = 5;
vector<vector<int>> matrix = generate_matrix(rows, cols);
print_matrix(matrix);
return 0;
}
vector<vector<int>> generate_matrix(int rows, int cols)
{
// fill a rows x cols 2D vector with 0s.
vector<vector<int>> matrix(rows, vector<int>(cols, 0));
// fill in 1s on top and bottom rows.
if (rows > 0)
{
for (int i = 0; i < cols; ++i)
{
matrix[0][i] = 1;
matrix[rows-1][i] = 1;
}
}
// fill in 1s on the left and right columns.
if (cols > 0)
{
for (int i = 0; i < rows; ++i)
{
matrix[i][0] = 1;
matrix[i][cols-1] = 1;
}
}
return matrix;
}
void print_matrix(const vector<vector<int>>& matrix)
{
// Use a reference for the row iterator to prevent a vector copy.
for (auto& row : matrix)
{
for (auto element : row)
{
cout << element;
}
cout << 'n';
}
}

差别不大,但您可以将std::generate_n()(从 c++11 开始)与 lambda 函数一起使用。

以下是完整的工作示例

#include <vector>
#include <iostream>
#include <algorithm>
int main ()
{
constexpr std::size_t  width  { 4U };
constexpr std::size_t  height { 3U };
constexpr std::size_t  w2     { width + 2U };
constexpr std::size_t  h2     { height + 2U };
std::vector<int> values;
values.resize ( w2 * h2 );
std::generate_n(values.begin(), w2 * h2, [=]() -> int
{ 
static std::size_t i = -1;
++i;
return     ( 0U == i / w2 ) || ( h2 - 1U == i / w2 ) 
|| ( 0U == i % w2 ) || ( w2 - 1U == i % w2 );
});
for(unsigned y=0; y<height+2; ++y) {
for(unsigned x=0; x<width+2; ++x) {
std::cout << values[y * (width+2) + x] << ' ';
}
std::cout << 'n';
}
return 0;
}

如果在编译时知道widthheigth,您可以使用一些模板工作(给我一些时间,我将展示一个例子)使用初始值设定项列表初始化std::vector(或std::array?)(给我一些时间,我将展示一个例子)。