【问题标题】:Replace a loop to implement Contains on an array替换循环以在数组上实现包含
【发布时间】:2017-10-09 06:59:05
【问题描述】:

有没有办法使用标准库来简化与 strncmp 比较的结构数组上的循环?

以下是我失败的尝试,因为 std::count_if 抱怨没有重载函数 std::begin 匹配的实例。

#include "stdafx.h"
#include "afx.h"
#include <string.h>
#include <iostream>
#include <algorithm>
#include <string>

struct nodeobject
{
    CString ObjectType;
    nodeobject() {}
    explicit nodeobject(CString objectType) { ObjectType = objectType; }
};

struct nodeinput
{
    struct nodeobject Object;
};

// Original function I want to rewrite to remove the for loop and the strncmp
static int ContainsObjectType(int collectionSize, struct nodeinput collection[], char* objectType)
{
    auto found = 0;
    for (auto idx = 0; idx < collectionSize; idx++)
    {
        if (strncmp(objectType, 
                    collection[idx].Object.ObjectType, 
                    strlen(collection[idx].Object.ObjectType)) == 0)
        {
            found = 1;
        }
    }
    return found;
}

#if 0
// The implementation below does not compile because there is no instance of 
// overloaded function std::begin matches
static int ContainsObjectType(int collectionSize, struct nodeinput collection[], char* objectType)
{   
    auto numFound = std::count_if(std::begin(collection),
                                  std::end(collection),
                                  [](struct nodeinput oneNode) 
    { 
        return strncmp(objectType, oneNode.Object.ObjectType, oneNode.Object.ObjectType) == 0); 
    });

    return numFound > 0;
}
#endif

int main()
{
    struct nodeobject node1("fokker");
    struct nodeobject node2("airbus");
    struct nodeobject node3("boing777");
    struct nodeinput collection[] = {node1, node2, node3};
    auto nintnode = 3;

    auto found = ContainsObjectType(nintnode, collection, "boing777");

    std::cout << found << std::endl;
    return 0;
}

错误是:

C2784: const _Elem *std::begin(std::initializer_list<_elem>) noexcept': 无法从 'nodeinput []

推导出 'std::initializer_list<_elem>' 的模板参数

【问题讨论】:

  • 请提供准确的错误信息
  • 首先,您要统计满足strncmp(...) == 0的对象的数量,或者如果有这样的对象则返回1,否则返回0? ContainsObjectType 做后者,但新版本尝试做前者。
  • 考虑使用std::string 和它的方法而不是CString 和c 字符串函数。您无需在每次使用 struct 类型时都指定 struct。考虑使用标准容器而不是数组,这样做可以解决您的问题。
  • 如果有一个该类型的对象,我想返回 1。错误是 C2784: 'const _Elem *std::begin(std::initializer_list<_elem>) noexcept': 无法从 'nodeinput []' 推断出 'std::initializer_list<_elem>' 的模板参数

标签: c++ stl


【解决方案1】:

只需将collection 设为一个指针,也可以将const 设为一个:

static int ContainsObjectType(int collectionSize, struct nodeinput *collection, char* objectType)
{   
    auto numFound = std::count_if(
        collection,
        collection + collectionSize,
        ...);
}

std::count_if的前两个参数必须是迭代器,而指针,实际上是原始迭代器。

std::begin(iterable) 只是pointerstd::end(iterable)pointer + &lt;data length&gt;

【讨论】:

  • 值得一提的是,std::beginstd::end 可用于数组,但如果它们衰减为指针则不能。
【解决方案2】:

下面是完整的解决方案,以防有人搜索如何用库标准替换对象数组上的 c 样式循环。

#include "stdafx.h"
#include "afx.h"
#include <string.h>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>

// Legacy code
class NodeObject
{
public:
    CString objectType;  // Keeping CString to minimize the impact for now
    NodeObject() {}
    explicit NodeObject(CString objectType) : objectType(objectType) { }
};

// Legacy code
class NodeInput
{
public:
    NodeObject object;
    explicit NodeInput(NodeObject object) : object(object) { }
};

// Code using vector and count_if
static int Contains(std::vector<NodeInput> collection, std::string objectType)
{
    auto numFound = std::count_if(std::begin(collection),
        std::end(collection),
        [&](const NodeInput oneInput)
    {
        return (std::strncmp(objectType.c_str(),
                             oneInput.object.objectType,
                             strlen(oneInput.object.objectType)) == 0);
    });

    return numFound > 0;
}

// Code using array pointer and count_if
static int Contains(int collectionSize, NodeInput* collection, char* objectType)
{
    auto numFound = std::count_if(collection,
                                  collection + collectionSize,
                                  [&](const NodeInput oneInput)
    {
        return (std::strncmp(objectType,
            oneInput.object.objectType,
            strlen(oneInput.object.objectType)) == 0);
    });

    return numFound > 0;
}

// Legacy code
static int ContainsOriginal(int collectionSize, NodeInput collection[], char* objectType)
{
    auto found = 0;
    for (auto idx = 0; idx < collectionSize; idx++)
    {
        if (strncmp(objectType, 
                    collection[idx].object.objectType, 
                    strlen(collection[idx].object.objectType)) == 0)
        {
            found = 1;
        }
    }
    return found;
}

int main()
{
    // Legacy code
    NodeInput arrayCollection[] { NodeInput(NodeObject("fokker")), 
                                  NodeInput(NodeObject("airbus")), 
                                  NodeInput(NodeObject("boing777")) };
    auto arrayCollectionSize = 3;
    auto found = Contains(arrayCollectionSize, arrayCollection, "boing777");
    std::cout << found << std::endl;

    // Code using Standard Library
    std::vector<NodeInput> collection{ NodeInput(NodeObject("fokker")),
                                       NodeInput(NodeObject("airbus")),
                                       NodeInput(NodeObject("boing777")) };
    found = Contains(collection, "boing777");
    std::cout << found << std::endl;

    return 0;
}

【讨论】:

    猜你喜欢
    • 2021-05-24
    • 1970-01-01
    • 1970-01-01
    • 2019-09-14
    • 1970-01-01
    • 1970-01-01
    • 2020-03-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多