在C++中正确返回一个uint16_t数组的方法

4

我有一段返回uint数组的C#代码,但我想用C++来实现。我查看了其他帖子;它们使用uint指针数组,而我的数组不是。请问有谁知道如何正确返回uint16_t数组?

这是正常运行的C#代码

  public static UInt16[] GetIntArrayFromByteArray(byte[] byteArray)
        {
            if ((byteArray.Length % 2) == 1)
                Array.Resize(ref byteArray, byteArray.Length + 1);


            UInt16[] intArray = new UInt16[byteArray.Length / 2];


            for (int i = 0; i < byteArray.Length; i += 2)
                intArray[i / 2] = (UInt16)((byteArray[i] << 8) | byteArray[i + 1]);


            return intArray;
        }

这是一个创建语法错误的 C++ 代码

uint16_t[] GetIntArrayFromByteArray(byte[] byteArray)
{
    //if ((byteArray.Length % 2) == 1)
        //Array.Resize(ref byteArray, byteArray.Length + 1);


    uint16_t[] intArray = new uint16_t[10];


    for (int i = 0; i < 10; i += 2)
        intArray[i / 2] = (uint16_t)((byteArray[i] << 8) | byteArray[i + 1]);


    return intArray;
}

1
什么是语法错误? - πάντα ῥεῖ
1
@πάνταῥεῖ说需要使用分号是因为返回语法。 - Selen
7
使用 std::arraystd::vector 怎么样? - JVApen
1
你需要找一本好的C++书籍。正如所示,你无法逻辑上知道byteArray有多大。在C++中,数组没有任何叫做“Length”的东西。如果你不知道如何“整合”,那么一本好的C++书籍会教你这个。这就是它存在的意义。stackoverflow.com不幸的是,不是一个交互式的网站,不能教你C++。只有一本好书才能做到。 - Sam Varshavchik
6
恰巧,同一本C++书也会解决你的主要问题。它会告诉你在C++中数组的确切含义(提示:在C++中没有真正的数组,它只是一种幻象。编译器看到你请求声明"uint16_t []",会微笑着做出完全不同的事情),以及数组和指针之间的关系。如果没有对C++的基本原理有深入了解,这里的简单答案(返回一个指向uint16_t的指针)实际上并不能帮助你多少。 - Sam Varshavchik
显示剩余3条评论
1个回答

7

永远不要使用 Type[]。请使用 std::vector

std::vector<uint16_t> GetIntArrayFromByteArray(std::vector<byte> byteArray)
{
    // If the number of bytes is not even, put a zero at the end
    if ((byteArray.size() % 2) == 1)
        byteArray.push_back(0);


    std::vector<uint16_t> intArray;

    for (int i = 0; i < byteArray.size(); i += 2)
        intArray.push_back((uint16_t)((byteArray[i] << 8) | byteArray[i + 1]));

    return intArray;
}

如果数组是固定大小的,您也可以使用std::array<Type, Size>

更优化的版本(感谢@Aconcagua)(演示

以下是具有更优化版本的完整代码,它不会复制或更改输入。如果您将拥有长输入数组,则此方法更好。虽然可能缩短代码,但我希望保持冗长且适合初学者阅读。

#include <iostream>
#include <vector>

using byte = unsigned char;

std::vector<uint16_t> GetIntArrayFromByteArray(const std::vector<byte>& byteArray)
{
    const int inputSize = byteArray.size();
    const bool inputIsOddCount = inputSize % 2 != 0;
    const int finalSize = (int)(inputSize/2.0 + 0.5);
    // Ignore the last odd item in loop and handle it later
    const int loopLength = inputIsOddCount ? inputSize - 1 : inputSize;

    std::vector<uint16_t> intArray;
    // Reserve space for all items
    intArray.reserve(finalSize);
    for (int i = 0; i < loopLength; i += 2) 
    {
      intArray.push_back((uint16_t)((byteArray[i] << 8) | byteArray[i + 1]));
    }

    // If the input was odd-count, we still have one byte to add, along with a zero
    if(inputIsOddCount) 
    {
      // The zero in this expression is redundant but illustrative
      intArray.push_back((uint16_t)((byteArray[inputSize-1] << 8) | 0));
    }
    return intArray;
}

int main() {
    const std::vector<byte> numbers{2,0,0,0,1,0,0,1};
    const std::vector<uint16_t> result(GetIntArrayFromByteArray(numbers));

    for(uint16_t num: result) {
        std::cout << num << "\n";
    }

    return 0;
}

byteArray.pushBack(0) 不正确,而且为什么不像 C# 代码预期的那样使用 byteArray.size() 进行 for 循环呢? - Ackdari
为什么要按值接受?通过const引用也可以 - 只是你需要在循环之后将最终的零附加到新向量中...并且你应该reserve足够的容量以防止重新分配。 - Aconcagua
1
@Selen 我根据Aconcagua提出的优点创建了一个更优化的版本。对于较大的输入大小,你应该使用它。 - Tomáš Zato

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