如何获取C++动态数组的大小

3

我正在学习C++,需要创建一个名为Airplane的结构体并对其进行操作。

我的结构体定义在Airplane.h文件中。

#include "stdafx.h"
using namespace std;

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

and it's my code

#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. 我无法输入"type"。
string type;
cout << "Input type: ";
getline(cin, type);
FindAirplanesAndPrint(airplaneList, n, type);

我的函数FindAirplanesAndPrint开始运行时没有任何类型的值。如何让我的程序获取值?
2. 在函数中如何获取动态数组的大小?因为似乎在每个函数中传递数组大小n是错误的方法。


2
在C++中,你无法直接获取动态分配数组的大小。你需要自己跟踪大小,可以通过保留一个变量、使用标准库容器或编写自己的动态数组包装器来实现。 - juanchopanza
1
你确定这是C++吗?我看到你使用了struct,而不是class;我看到你使用了数组,而不是std::vector或者std::array。我的意思是,如果你在使用C++,就没有必要用更复杂(也更容易出错)的方式来实现同样的功能。 - Jack
1
"我有两个问题。"--那你为什么只发了一个帖子?每个帖子只问一个问题。 - Benjamin Lindley
@Jack:struct是一种默认情况下每个成员都是公共的类。结构体还可以。此外, stringusing namespace std; 表明这是C ++程序。 - SigTerm
@Jack 我刚开始学习C++,需要使用struct因为这是学习目标的培训任务,而我还没有开始学习std::vectorstd::array - Heidel
显示剩余2条评论
6个回答

4

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

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

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


谢谢,我还没有开始学习std::vectorstd::array,但我希望很快能开始学习它们。 - Heidel

3
1)去除无关的内容后,这基本上是你得到的:
cin >> n;
getline(cin, type);

operator>>会在输入缓冲区留下一个新行字符,这是getline看到的第一个字符。由于'\n'是默认的行分隔符,所以你得到了一个空行。要解决这个问题,在调用getline之前调用cin.ignore()以丢弃'\n'

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


1

输入类型时的问题在于,在输入 n 后,输入缓冲区中包含换行符。在使用函数 getline 前,应该使用成员函数 ignore 来清除缓冲区。

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


0
你可能可以用0个项创建一个动态数组,创建一个int计数器,使用getline作为语句创建一个while循环,while (getline(cin, string_var) != SomeText) /* SomeText = 一些文本,以便用户告诉您不会再输入任何内容*/,您原来在for中要做的事情现在在while中完成,并在while结束时将计数器增加1,i++。关于对数组的访问,如果您的动态数组有0个项,则SomeDynamicArray[1].something = SomeValue只会向数组添加第二个项,并且该项的“something”将等于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++;
} 

我不知道这是否适用于你的情况,但如果你想尝试一下,可以试试看。还有,关于每个人都在谈论向量的问题,据我所知,向量更慢且占用更多内存,因为它们会将它们的大小翻倍,而不是每次需要时仅增加它们的大小。希望我的回答能对你有所帮助。


0

当我使用动态数组时,我常用的一种方法是将数组作为引用传递给函数。这将帮助您保留数组的大小信息。

例如:

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 存储了数组的正确大小信息。更多信息请点击这里

0
你无法直接查找动态分配数组的大小,但是可以通过访问指向数组对象之前的大小存储来获取具有析构函数对象数组的大小。需要注意的是,这种方法没有被任何标准或编译器供应商保证,并且可能随时更改。因为当你调用delete []时,C++必须以某种方式存储确切的大小才能知道要调用析构函数的对象数量。

对于那些有兴趣测试的人,这是代码: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

P.S. 在我看来,C++委员会应该考虑为所有new[]分配标准化访问数组大小,或提供一种新类型的类似new的操作符,它能够保证一个大小前缀。这有助于允许某些用于低级代码的new[](例如更容易的单指针不可变字符串)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接