【问题标题】:How to get size c++ dynamic array如何获取大小c ++动态数组
【发布时间】:2013-10-22 02:28:09
【问题描述】:

我正在学习 C++,我需要创建结构 Airplane 并使用它。

我的结构Airplane.h

#include "stdafx.h"
using namespace std;

struct Airplane {
    string destination;
    int number;
    string type;
};

这是我的代码

#include "stdafx.h"
#include "Airplane.h"

string SetDestination(int n);
string SetType(int n);
void PrintAirplaneList(Airplane * &airplaneList, int n, string title);
void SortByDestination (Airplane *&airplaneList, int n);
void FindAirplanesAndPrint(Airplane *&airplaneList, int n, string type);

int _tmain(int argc, _TCHAR* argv[])
{
using namespace std;

srand((unsigned)time(NULL));

int n;
cout << "Input n = ";
cin >> n;

Airplane * airplaneList = new Airplane[n];

for (int i = 0; i < n; ++i)
{
    airplaneList[i].destination = SetDestination(rand()%5);
    airplaneList[i].number = rand()%9001 + 1000;
    airplaneList[i].type = SetType(rand()%3);
}

PrintAirplaneList(airplaneList, n, "List:");
SortByDestination (airplaneList, n);
PrintAirplaneList(airplaneList, n, "Sorted list (by destination):");

string type;
cout << "Input type: ";
getline(cin, type);
FindAirplanesAndPrint(airplaneList, n, type);

delete [] airplaneList;

system("PAUSE");
return 0;
}

string SetDestination (int n)
{
    string destination;
    switch(n){
    case 0: destination = "Tokio"; break;
    case 1: destination = "Amsterdam"; break;
    case 2: destination = "Moscow"; break;
    case 3: destination = "Philadelphia"; break;
    case 4: destination = "San Diego"; break;
    default: destination = "Unknown city"; break;
    }
    return destination;
}

string SetType (int n)
{
    string type;
    switch(n){
    case 0: type = "passenger"; break;
    case 1: type = "cargo"; break;
    case 2: type = "post"; break;
    default: type = "unknown type"; break;
    }
    return type;
}

void PrintAirplaneList(Airplane *&airplaneList, int n, string title)
{
    cout << "\n";
    cout << title << "\n\n";
    for (int i = 0; i < n; ++i)
    {
        cout << "Destination: " << airplaneList[i].destination << "\n";
        cout << "Number: " << airplaneList[i].number << "\n";
        cout << "Type: " << airplaneList[i].type << "\n\n";
    }
}

void SortByDestination (Airplane *&airplaneList, int n)
{
    for (int i = 0; i < n - 1; ++i)
    {
        for (int j = 0; j < n -1; ++j)
        {
            if(airplaneList[j + 1].destination > airplaneList[j].destination) continue;
            Airplane tempAirplane = airplaneList[j];
            airplaneList[j] = airplaneList[j + 1];
            airplaneList[j + 1] = tempAirplane;
        }
    }
}

void FindAirplanesAndPrint(Airplane *&airplaneList, int n, string type) {
    cout << "Type - " << type << "\n";
    int count = 0;
    for (int i = 0; i < n; ++i)
    {
        if (airplaneList[i].type == type)
        {
            cout << "Destination: " << airplaneList[i].destination << "\n";
            cout << "Number: " << airplaneList[i].number << "\n";
            ++count;
        }
    }
    if (count == 0)
    {
        cout << "Not found\n";
    }
}

我有两个问题。
1. 无法输入类型

string type;
cout << "Input type: ";
getline(cin, type);
FindAirplanesAndPrint(airplaneList, n, type);

我的函数FindAirplanesAndPrint 开始工作,没有任何类型值。如何让我的程序获得价值?
2. 如何获取函数中动态数组的大小?因为似乎每个函数中数组n的传递大小是错误的方式。

【问题讨论】:

  • 你不能通过 C++ 中动态分配数组的大小来计算。您必须自己跟踪大小,方法是为其保留一个变量、使用标准库容器或编写自己的动态数组包装器。
  • 使用 std::vector 或 std:;array 然后 size 方法会做你想要的。
  • 你确定这是 C++ 吗?当你有classes 时我看到structs,当你有std::vector 或std::array 时我看到数组。我的意思是,如果您使用 C++,则无需以复杂(且更容易出错)的方式进行操作。
  • “我有两个问题。” -- 那你为什么只发一个帖子?每个帖子问一个问题。

标签: c++ arrays


【解决方案1】:

“如何在函数中获取动态数组的大小?因为似乎每个函数中数组n的传递大小是错误的方式。”

然而,当您使用动态分配的 C 样式数组时,这是唯一的方法。

如果您想避免显式发送大小,则传递一些包装此原始内存缓冲区并提供其他检索大小的方法的对象。这里最合理的解决方案是使用std::vector&lt;Airplane&gt;。

【讨论】:

  • 谢谢,std::vector 和std::array 还没开始学,但我希望我能尽快开始学习。
【解决方案2】:

1)省略不相关的,这基本上就是你得到的:

cin >> n;
getline(cin, type);

operator&gt;&gt; 在输入缓冲区中留下一个换行符,这是getline 看到的第一个字符。因为'\n' 是默认的行分隔符,所以你得到一个空行。要修复它,请先调用 cin.ignore(),然后再调用 getline 以丢弃 '\n'。

2) 如果您希望坚持使用原始指针,则将大小作为参数传递是您唯一的选择。切换到std::vector,得到size()方法,可以随时查询。

【讨论】:

    【解决方案3】:

    输入type的问题是输入缓冲区包含输入n后的换行符。在使用函数 getline 之前,您应该使用成员函数 ignore 清除缓冲区。

    至于您的第二个问题,一般来说,您应该自己跟踪动态分配数组的大小。或者您可以将数组的最后一个元素设置为 NULL 并将其用作哨兵。

    【讨论】:

      【解决方案4】:

      您可能会创建一个包含 0 个项目的动态数组,创建一个 int 计数器,使用 getline 作为语句创建一个 while 循环,while (getline(cin, string_var) != SomeText) /* SomeText = some kind of text so用户向您展示将不再有任何输入*/,您将在 for 中执行的操作在 while 中执行,在 while 结束时将计数器增加一,i++。关于对数组的访问,如果您的动态数组有 0 个项目,那么 SomeDynamicArray[1].something = SomeValue 只会向数组添加第二个项目,并且该项目的“某物”将等于 SomeValue。

      type *ArrayPointer = new type[0];
      string StringVar;
      int i = 0;
      while (getline(cin, StringVar) != "Text that show there are not going to be any more inputs") {
           /*code*/
           i++;
      } 
      

      如果它适用于您的情况,请尝试,但如果您愿意,请尝试。此外,关于每个人都在谈论向量,至少据我所知,向量速度较慢并且占用更多内存,因为它们的大小会加倍,而不是每次需要时都增加它。我希望我会有所帮助。

      【讨论】:

        【解决方案5】:

        我在处理动态数组时使用的一种方法是将数组作为对函数的引用。这将帮助您保留数组的大小信息。

        例如:

        string list1[3] = {
            "item1",
            "item2",
            "item3"
        };
        
        string list2[2] = {
            "item1",
            "item2"
        };
        
        template<typename T, size_t N>
        void PrintItems(T(&items)[N]) {
            for (int i = 0; i < N; i++) {
                cout << items[i] << endl;
            }
        }
        
        int main() {
            PrintItems(list1);
            PrintItems(list2);
        }
        

        在前面的示例中,N 存储了数组的正确大小信息。更多信息here

        【讨论】:

          【解决方案6】:

          你不能通过 C++ 中动态分配数组的大小来计算。

          这实际上并不完全正确。广泛支持特定类型的大小检索 - 具有析构函数的对象数组的大小。

          但是,对于任何考虑使用此功能的人 - 我必须警告您,据我所知,任何标准或编译器供应商都不以任何方式保证这一点。它可能随时发生变化,不应依赖于业余项目以外的任何事情。

          可破坏对象数组的大小存储在对象本身之前,可以通过基本指针转换访问:((size_t*)mem)[-1]。

          当你想一想 - 当你调用 delete [] 时,你并没有传递数组的大小,所以 C++ 必须 以某种方式存储确切的大小以知道有多少对象要调用析构函数on,以一种可以从指针本身轻松有效地访问的方式。然而 - 不能保证它必须是元素的数量 - 它也可以是字节数或结束指针,可能混合了一些标志位。也就是说,一旦他们决定了一个约定,它可能会破坏某种向后兼容性以在以后进行更改。

          对于那些有兴趣对此进行测试的人,这里是代码:https://ideone.com/Z0Sta1

          #include <stdio.h>
          
          struct bytes10
          {
              ~bytes10() { printf("dtor %p", this); }
              char _[10]; // to test whether the size or the count is returned
          };
          
          int main()
          {
              size_t size1 = ((size_t*)new int[10])[-1]; // doesn't work (pointer on some platforms, allocation size-based number on others)
              printf("%zu (0x%zx)\n", size1, size1);
              printf("%zu\n", ((size_t*)new bytes10[5])[-1]);
              printf("%zu\n", ((size_t*)new bytes10[6])[-1]);
              printf("%zu\n", ((size_t*)new bytes10[7])[-1]);
              printf("%zu\n", ((size_t*)new bytes10[65536])[-1]);
              return 0;
          }
          

          可能的输出(第一个值可能不同):

          49 (0x31)
          5
          6
          7
          65536
          

          附:在我看来,C++ 委员会应该考虑对所有new[] 分配的数组大小的访问标准化,或者提供一种能够保证大小前缀的新型new-like 运算符。这允许将new[] 用于较低级别的代码(例如更简单的单指针不可变字符串)。

          【讨论】:

            猜你喜欢
            • 2021-03-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-09-05
            • 1970-01-01
            • 2011-05-03
            • 2014-12-29
            相关资源
            最近更新 更多