【问题标题】:How do I get the size of a list of lists of strings? [closed]如何获取字符串列表的大小? [关闭]
【发布时间】:2021-03-17 18:58:38
【问题描述】:

我不明白需要说明什么。请解释您的疑虑。 从我的角度来看,我提出了一个与所解决的技术领域相符的问题,我解释了我的困惑,我给出了一个说明我的问题的例子,我已经详细说明了收到的诊断信息。这个问题的受访者充分详细地理解了我的问题、示例和诊断信息,因此他们能够做出适当的回应并纠正我的错误和误解。通过什么方式可以使这个对话通过适当的问题变得更加尖锐?

@Ruzihm 表示没有列表,我想在我的示例中。我想解释一下为什么这种说法是错误的。几年前有一个 LIFO 堆栈和一个 FIFO 堆栈。我们将 LIFO 堆栈称为“堆栈”,将 FIFO 堆栈称为“队列”。在英国,排在前面的队伍,例如剧院票房是一个队列,而中国男人在蒙古征服中国后所戴的辫子也是一个队列。这一切都取决于上下文。

没有“列表”的抱怨可能源于没有<list> 对象的实例化的概念。但是这样的对象更恰当地称为链表,链表的链表称为图,参见例如Gnu gSlip 文档。没有涉及明确的链表。

在 C/C++ 中,可以形成一个非矩形的多维数组。此类对象在历史上被称为“列表列表”,而不是“数组数组”。原因很清楚,'list' 是一个包含项目的对象,用编程术语来说,可以通过索引访问,如 list[index]。这并不是说链表,a.k.a., <list> 也不是“链表”,但通常的约定更明确地表明 <list> 是链表。

如果问题改为“数组数组”,那么这些示例就没有什么意义了。在类似于使用<list> 的术语中,没有<array> 的。因此,任何对使用“列表列表”的批评都会被保留并与使用“数组数组”相关。如果一个不合适,另一个也是。

给出的答案,即使用向量的向量,是准确的,并且正确地回答了有关列表列表的问题。如有关向量的文档中所述,例如在https://cpluscplus.com 上,向量是一个列表,其中元素可以通过索引访问。在这种情况下,向量的向量是特定的列表列表,更具体地说,是锯齿状列表的列表,而不是必须是矩形的数组的数组。

我认为,任何声明发布示例以解释我在形成列表时的困惑是不恰当的,这表明对软件实践和行话的一些误解。问题形成正确,示例正确解决了问题。

如果此问题被删除,或以其他方式无法访问,则您支持有关该问题的格式错误的陈述。我希望不要这样做。

MSVS 16.9.1

我创建了一个字符串列表。我很难获得列表列表的大小或列表中字符串数组的大小。我收到相互矛盾的错误消息,我不知道如何解决它们。


# include <string>

using namespace std;

static const string   x[3] = { "a", "b", "c" };
static const string   y[]  = { "a", "b", "c" };
static const string*  z[]  = { x, y };
int xSize  = x->size();
int ySize  = y->size();
int zSize  = z.size();    // expression must have class type
int zpSize = z->size();   // expression must have pointer-to-class type
int xzSize = z[0]->size();
int yzSize = z[1]->size();

错误描述为:

C++ 中的表达式必须具有类类型错误上次更新时间:2021 年 1 月 14 日表达式必须具有类类型是当点 (.) 运算符用于访问对象的属性时引发的错误,用于指向对象。

还有:

好吧,我们有一个问题。我的 MSVS 使用 bing 进行网络搜索以寻找答案,但没有一个答案像上面的那样尖锐。要点是对象必须是指针,但不是。

结果是 zpSize 和 zSize 都不起作用,并且给出的错误是矛盾的。我被难住了。

【问题讨论】:

  • 此问题中没有任何列表...
  • 最好不要猜测它是如何工作的。 C 数组没有成员 size()
  • 另外,当您调用x-&gt;size()y-&gt;size() 时,您正在对数组的第一个元素调用string::size 函数。 z 是一个指针数组,它不是类,不能隐式转换为类,因此 expression must have class type 错误。它也不是指向类的指针,也不能隐式转换为指向类的指针,因此 expression must have pointer-to-class type 错误。
  • 您可以使用std::extent 找出数组的大小,但使用std::array 通常更容易。
  • 您不能将数组用作容器项。看这里有一些解释stackoverflow.com/questions/826935/…

标签: c++ pointers


【解决方案1】:

xy 是 3 个 string 元素的固定数组。仅通过名称引用固定数组将衰减为指向数组第一个元素的指针。因此,x-&gt;size()(&amp;x[0])-&gt;size() 相同,或者只是x[0].size()。与y-&gt;size() 相同。因此,您得到的是数组中第一个 strings 的大小,而不是数组本身的大小。为此,您可以改用std::size()std::extent,例如:

size_t xSize = std::size(x);
size_t ySize = std::size(y);
size_t xSize = std::extent<decltype(x)>::value;
size_t ySize = std::extent<decltype(y)>::value;

z 也是一个固定数组,包含 2 个 string* 元素。固定数组不是类的实例,因此不能在其上调用任何成员方法,这就是为什么z.size()z-&gt;size() 是非法的。同样,请改用std::size()std::extent,例如:

size_t zSize = std::size(z);
size_t zSize = std::extent<decltype(z)>::value;

另外,请注意,由于数组衰减,z 持有指向xy 中第一个strings 的string* 指针,而不是指向xy 本身的指针。因此xzSizeyzSize 将再次成为xy 数组中第一个strings 的大小,而不是xy 本身的大小。如果你想这样,你需要让z 直接指向xy,例如:

#include <string>

using namespace std;

typedef string stringArr3[3];

static const stringArr3 x = { "a", "b", "c" };
static const stringArr3 y = { "a", "b", "c" };
static const stringArr3* z[] = { &x, &y };
int xSize  = std::size(x);
int ySize  = std::size(y);
int zSize  = std::size(z);
int xzSize = std::size(*(z[0]));
int yzSize = std::size(*(z[1]));

话虽如此,现在考虑改用std::array,它有一个size() 成员方法,例如:

#include <string>
#include <array>

using namespace std;

using stringArr3 = array<string, 3>;

static const stringArr3 x{ "a", "b", "c" };
static const stringArr3 y{ "a", "b", "c" };
static const array<stringArr3*, 2> z{ &x, &y };
size_t xSize  = x.size();
size_t ySize  = y.size();
size_t zSize  = z.size();
size_t xzSize = z[0]->size();
size_t yzSize = z[1]->size();

【讨论】:

  • 这真的很有帮助,谢谢。我的实际解决方案需要我使用可变大小的字符串数组。如果您没有时间,我会尝试寻找答案。 “真相”是,我从 95 年开始就一直在编写 C++ 代码,但在过去的几年里,我已经“漂移”到了其他语言。我/我生锈了,也老了。谢谢
  • 请原谅。我的意思是可变大小的固定大小的数组。没有两个数组具有相同的大小,但是,每个数组的大小不会改变。我可以手动计算实际大小,如字符串 x[size] = {},然后 array,但我想知道是否还有其他方法。
  • @ArthurSchwarez "我的实际解决方案需要我使用可变大小的字符串数组" - 然后使用std::vector
  • @ArthurSchwarez "as in string x[size] = {}, 然后是 array" - 这些都不起作用。第一个是可变长度数组,即not standard or portable,第二个不会编译。两种类型的数组都需要编译时常量。如果仅在运行时知道数组的大小,请使用std::vector 作为数组。
  • 问题已解决。正如建议的那样, vector x(list of things);和vector> z {向量列表}。我还没有开始调试,但没有语法错误,我认为它应该可以工作。我在代码中使用 ``` for (vector name: z)。
【解决方案2】:

在学习时最好避免像 C-Arrays 这样的低级结构(有一些不明显的陷阱)。

使用 C++ 容器(std::liststd::vectorstd::array),您将获得所需的行为:

static const std::list<std::string>   x = { "a", "b", "c" };
static const std::list<std::string>   y = { "x", "y", "z" };

int xSize  = x.size();
int ySize  = y.size();

列表的列表变得有点复杂。不是因为它更难,而是您想要的实际上是其他列表的引用列表。制作列表很容易。

// A list of lists
std::list<std::list<string>> z = {{ "a", "b", "c" }, { "x", "y", "z" }};
int zSize  = z.size();

但如果您想保留原始列表以及新列表:

std::list<std:: reference_wrapper<const std::list<string>> z1 = {x,y};
int zSize1  = z1.size();

您当前代码的问题:

static const string   x[3] = { "a", "b", "c" };

这里的xstd::string 的C 数组。问题在于数组很容易衰减为指针。这就是这里发生的事情:

x->size(); // the array is converted into a pointer (to the first element).
           // So this will return the size of the string "a"
           // Which is 1.

你应该做的是:

x[0].size();

这是使用 C++ 容器而不是像 C-Arrays 这样的低级结构的一个很好的理由。如果你想要一个固定大小的数组,你可以使用std::array&lt;&gt;,它实现了与 C-Array 相同的效果(并且具有相同的足迹),但具有成为一个成熟类的所有保护。


查看您对 z 的访问权限:

static const string*  z[]  = { x, y };

所以z 是一个指向 std::string 指针的 C 数组。这有更多问题,因为内存管理不清楚(如果我没有查看这部分代码)。

但是你可以在这里创建 z,因为 x 和 y 都会自动从数组衰减为指针。

声明:

获取z 的第一个元素,它是指向X 中第一个元素的指针,然后调用该对象的size() 成员。

int xzSize = z[0]->size();

C-Array 没有成员,因此您无法获取它们的大小。从技术上讲,您可以计算它们的大小:

int xSize = sizeof(x) / sizeof(x[0]);

但是如果你对一个指针这样做,它将不起作用:

// This will fail as z stores the pointer not the array.
int xzSize = sizeof (z[0]) / sizeof(z[0][0]);

【讨论】:

  • @Remy Lebeau 感谢你们俩。我不那么困惑,但仍然迷茫。
  • @ArthurSchwarez 避免使用 C 阵列。如果您需要数组,请使用 C++ std::array,这将完全符合您的预期,并且没有额外的成本。如果你想要一个更通用的容器,如果你有一个特定的用例,大多数时候使用std::vector&lt;&gt;std::list&lt;&gt;。当你变得更有经验时,你可以开始在 C-Array 中混音。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-31
  • 2018-09-08
  • 2017-07-29
  • 2013-09-14
  • 1970-01-01
  • 1970-01-01
  • 2020-07-04
相关资源
最近更新 更多