【问题标题】:How to copy elements from std::list to an array of struct?如何将元素从 std::list 复制到结构数组?
【发布时间】:2019-08-20 08:05:06
【问题描述】:

我需要将std::list 的内容复制到一个数组,其中数组是数组的结构。下面是它的代码实现。

#include <iostream>
#include <string>
using namespace std;

typedef struct
{
    int height;
    int width;
    int length;
}dimensions;
GetDimensions(list<std::string>, *int); // Function that copies the content of list to array passed as second parameter

int main() 
{
    dimensions cuboid[10];
    int plane[10];

    list<std::string> planeList = GetList();//Function that returns list of elements
    list<std::string> dimensionList = GetList();

    GetDimensions(planeList,&plane);//This is fine, as it is a simple array
    GetDimensions(dimensionList,&cuboid.height);//Trouble in implementation of this usecase, for cuboid.height, cuboid.width and cuboid.height.
    return 0;
}

GetDimensions(list<std::string>dimensionList, int* dimensionParams)
{
    int i=0;
    for(list<std::string>::iterator it = dimensionList.begin(); it != dimensionList.end(); ++it)
    {
        dimensionParams[i] = stoi(*it);
        i++;
    }
}

在这里,我需要GetDimensions() 函数将列表(作为第一个参数传递)复制到数组(第二个参数)。实现的函数适用于简单数组plane。但是如何将结构数组作为参数传递给函数呢?

我将获得std::listcuboid.heightcuboid.widthcuboid.length。所以函数必须将list的内容分别从cuboid[0].height复制到cuboid[i].height。有没有直接复制内容的具体功能?

【问题讨论】:

  • C++ 中不需要typedef struct { ... } abc;。请写struct abc { ... };
  • 关于您的问题,语言中没有简单的方法可以说“dimensions 数组中的所有.height 子对象”。可以构建具有类似行为的东西,但它大多是丑陋且难以理解的。
  • 另外,您的意思是int* dimensionParamsGetDimensions 签名中吗?现在它不适用于planeListdimensionList - 如果dimensionList 是普通的int,则不能使用dimensionList[i]
  • 您不会收到有关为GetDimensions() 声明int 参数然后通过dimensionParams[i] 访问它的错误消息吗?
  • 这显然不是 C,那为什么要那个标签呢?应用前请阅读标签说明,不要盲目推荐推荐的标签!

标签: c++ arrays algorithm struct stdlist


【解决方案1】:

使用 std::array 代替。那么你的问题可以简化为将两种不同类型的数组传递给一个函数。

这个可以解决

以下是带有if-constexpr的模板函数的示例代码(See live online)

#include <iostream>
#include <string>
#include <list>
#include <array>
#include <type_traits>  // std::is_same_v

struct dimensions // no need to typedef here
{
        int height;
        int width;
        int length;
};

template<typename T>
void GetDimensions(const list<std::string>& dimensionList, T& dimensionParams) 
^^^^               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //---> pass list by const-ref as the values are non-modifying
{
    int i{0};
    if constexpr (std::is_same_v<std::array<int, 10>, T>)
    {
        for(const std::string& str: dimensionList)   dimensionParams[i++] = std::stoi(str);
    } 
    else
    {
        for(const std::string& str: dimensionList) dimensionParams[i++].height = std::stoi(str);
    }
}

int main()
 {
    std::array<dimensions, 10> cuboid;  // use std::array instead of VLA
    std::array<int, 10> plane;

    std::list<std::string> planeList{"1", "2"}; // some list
    std::list<std::string> dimensionList{"1", "2"};

    GetDimensions(planeList, plane);
    GetDimensions(dimensionList, cuboid);
    return 0;
}

还要注意:

  • 您没有指定GetDimensions 函数的返回类型。 你可能想在那里返回void
  • 在 C++ 中,您不需要为 struct { ... } 使用 typedef 别名。

  • 最后一点,不要用using namespace std;练习

【讨论】:

    【解决方案2】:

    您可以使用boost::transform_iterator 来做到这一点。

    #include <iostream>
    #include <string>
    #include <algorithm>
    #include <functional>
    #include <boost/iterator/transform_iterator.hpp>
    
    struct dimensions {
        int height;
        int width;
        int length;
    };
    
    template <typename OutputIt>
    void GetDimensions(std::list<std::string> dimensionList, OutputIt dimensionParams)
    {
        // N.b. taking the address of a standard library function is undefined, so wrap in a lambda
        auto stoi = [](std::string s){ return std::stoi(s); };
    
        std::copy(boost::make_transform_iterator(dimensionList.begin(), stoi),
            boost::make_transform_iterator(dimensionList.end(), stoi), 
            dimensionParams);
    }
    
    int main() {
        dimensions cuboid[10];
        int plane[10];
    
        std::list<std::string> planeList = GetList();
        std::list<std::string> heightList = GetList();
        std::list<std::string> widthList = GetList();
        std::list<std::string> lengthList = GetList();
    
        GetDimensions(planeList, plane);
        GetDimensions(heightList, 
            boost::make_transform_iterator(cuboid, std::mem_fn(&dimensions::height)));
        GetDimensions(widthList, 
            boost::make_transform_iterator(cuboid, std::mem_fn(&dimensions::width)));
        GetDimensions(lengthList, 
            boost::make_transform_iterator(cuboid, std::mem_fn(&dimensions::length)));
        return 0;
    }
    

    【讨论】:

    • @JeJo int[10] 不是 VLA。
    猜你喜欢
    • 1970-01-01
    • 2017-03-17
    • 2016-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-19
    • 2015-01-06
    • 2020-10-28
    相关资源
    最近更新 更多