获取结构数组 c++ 中的元素数

Get the number of elements in a struct array c++

本文关键字:元素 c++ 结构 数组 获取      更新时间:2023-10-16

我需要在结构数组中查找元素的数量

我有这个结构

struct Features {
    int feature1;
    string feature2;
    string feature3;
    string feature4;
    bool feature5;
};

然后我把它变成了一个数组

Features *feature = new Features[100];

然后我输入了一些值

for(int i = 0; i < 3; i++)
{
    feature[i].feature1 = 5;
    feature[i].feature2 = "test";
    feature[i].feature3 = "test2";
    feature[i].feature4 = "test3";
    feature[i].feature5 = true;
}

现在我想获取数组的大小,应该是 3 (2)

我该怎么做?

cout << (sizeof feature / sizeof *feature) << endl;

似乎不起作用,因为它打印了不正确的值。(它保持打印4)

对不起,如果这是一个愚蠢的问题,我还在学习c ++

cout << (sizeof feature / sizeof *feature) << endl;

应该是

cout << (sizeof(feature) / sizeof(*feature)) << endl;

请注意括号。可悲的是,由于几个原因,它无法告诉您想要什么。

  1. feature是一个指针。

指针是存储中的位置,一个地址,您可能遇到的系统上的所有地址都将具有相同的大小,可能是 4 或 8 个字节。现在让我们假设 4 并将其代入等式。

cout << (4 / sizeof(*feature)) << endl;

这肯定会打印 0,因为*feature肯定大于 4,并且在整数数学中,4 / <anything greater than 4>将被截断为 0。

如果定义了feature

Features feature[100];

除非需要更改所指向的数据块的大小,否则没有理由不应该更改。无论如何,现在功能不仅仅是指向某个任意内存块的指针。这是一个正好 100 Features的块。它的大小为 100 * sizeof(feature[0])。这是数组和指针之间的根本区别,所以下次有人告诉你"数组是指针!"你可以告诉他们自己去咒骂删除

例如:

cout << (sizeof(feature) / sizeof(feature[0])) << endl;

将打印 100,而不是我们在feature是指针时返回的 0。 0 != 100。数组不是指针。数组在很多情况下都可以指针一样使用。

Feature feature2d[100][100];
Feature ** feature2dptr = feature2d;

不是其中之一。当您必须将 2D 数组传递到函数中时,请记住这一点。

  1. 数组知道它的大小,但不知道使用了多少。

从大小来看,我们可以像上面一样计算容量,但坦率地说,这是一个愚蠢的赌注。 可以定义feature

constexpr int MAX_FEATURES = 100;
Features feature[MAX_FEATURES];

然后而不是这个:

cout << (sizeof(feature) / sizeof(feature[0])) << endl;

我们打印的复杂程度要低得多

cout << MAX_FEATURES << endl;

但这仍然不是我们想要的。

那么我们如何做对呢?

首选C++解决方案是使用 std::vector . vector为您做各种很酷的事情,例如调整自身大小并计算实际使用了多少。此外,它符合三规则,与典型的指针和动态数组方法不同。什么是三法则?嗯,这真的很重要。我建议阅读链接。

定义Featuresvector

std::vector<Features> feature;

存储Feature

Feature temp;
feature.push_back(temp);

通常更好的方法是为 Feature

feature.emplace_back(feature1, feature2, feature3, feature4, feature5);

因为这消除了创建和复制临时Feature的需要。

获取feature中的Features

feature.size();

很简单吧?

还行。所以有些人认为你不应该使用vector,直到你长大了,更有经验。他们希望你在内存管理中遭受困境,而你仍在学习编写一个体面的、结构良好的程序,并弄清楚如何调试新程序员所犯的琐碎错误。我对此并不失望,但这似乎是统治这片土地的教育范式。

让我们从固定数组开始,因为它很简单,而且不那么复杂。

constexpr int MAX_FEATURES = 100;
Features feature[MAX_FEATURES];
int num_features = 0;

每次需要向数组添加Feature时,首先要确保有空间。

if(num_features < MAX_FEATURES)

然后添加Feature

feature[num_features] = new_feature;

然后递增,加一个,num_features.

num_features++;

你有多少Features

cout << num_features << endl;

如果您绝对必须使用指针执行此操作

int capacity = 100;
Features * feature = new Feature[capacity];
int num_features = 0;

现在你必须保持capacitynum_features,因为你会做这么愚蠢的事情的唯一原因是能够根据需要调整内存块feature指向的大小。

if(num_features >= MAX_FEATURES)
{

做更大的feature

    capacity = capacity * 1.5; // why 1.5? Because I felt like it.
    Features * bigger_feature = new Features[capacity];

复制从featurebigger_feature的所有内容

    for (int index = 0; index < num_features; index++
    {
        bigger_feature[index] = feature[index];
    }

释放feature使用的内存

    delete[] feature;

feature替换为bigger_feature

    feature = bigger_feature;
}

现在你可以

feature[num_features] = new_feature;
num_features++;

这是在一个漂亮的可剪切和粘贴的斑点中的那个斑点:

if(num_features == MAX_FEATURES)
{
    capacity = capacity * 1.5; // why 1.5? Because I felt like it.
    Features * bigger_feature = new Features[capacity];
    for (int index = 0; index < num_features; index++
    {
        bigger_feature[index] = feature[index];
    }
    delete[] feature;
    feature = bigger_feature;
}
feature[num_features] = new_feature;
num_features++;

等等。而且这个指针大杂烩绝对不符合三规则,所以你可能必须编写复制和移动构造函数、赋值和移动运算符以及析构函数。

最后,当你完成时,你必须

delete[] feature;

你有多少Features

cout << num_features << endl;

不,实际上数组的大小是 100,而不是 3,因为您分配了一个 100 元素的数组,new .您在数组中初始化了 3 个元素这一事实并不重要。它仍然是一个 100 元素的数组。

但无论是 3 还是 100,都没关系。由您来跟踪分配的数组的大小。C++不会为你做这件事。

但是,如果您确实希望C++跟踪数组的大小,请使用 std::vector 。这就是它的目的。

你需要跟踪它。当您为 100 个功能分配足够的空间时,您得到了确切的......足够容纳 100 个功能的空间。跟踪您随后初始化了多少个等是您需要做的事情。

我确定它正在按照编程打印正确的值。但sizeof只告诉您分配了多少空间,而不是有多少成员包含有意义的值。

如果你想要一个可变大小的数组,请使用 std::vector。否则,保留您拥有的设置,但将成员(例如 feature1 )初始化为可识别的值(例如 -999 或其他您不希望有意义使用的值),然后查看在找到该值之前可以循环多远;