当C++函数返回类型为vector容器时,是否有方法可以返回Null?

3

问题在于我正在实现一个递归,其中必须使用 NULL 值来指定遍历的递归分支无效。

但是在C++中,当返回类型为容器(例如我的vector容器)时,不能返回 NULL

那么是否有解决该问题的方法,还是我必须使用其他逻辑?

代码:

#include<iostream>
#include<vector>


std::vector<int> howSum(int target,std::vector<int> in){
    if(target < 0 ) return {-1}; 
    if(target == 0) return {};

    for(int num : in){
        int remainder = target - num ;
        std::vector<int> remResult = howSum(remainder,in);
        if(remResult[0] != -1 || remResult.empty()){
            remResult.push_back(num);
            return remResult;
        }
    }

    return {-1};
}

int main(){

    std::vector<int> v = {2,4,3};
    int targetSum = 8;

    std::vector<int> r = howSum(targetSum,v);

    for(int o : r)
        std::cout<<o<<" ";

    return 0;
}

编辑:

非常感谢所有的建议和解决方案,但我想要一个不使用更近的c++编译器(即c++17和c++20)的基本解决方案。 如果可能的话,请查看我自己实现的基本解决方案并提出建议,看看是否可以改进。

我找到了一种替代解决方案(基本方法)

我写这篇文章是为了给来参考这个问题的人。

解决方案:

#include<iostream>
#include<vector>
#include<string>

std::string howSum(int target,std::vector<int> v){

    if(target == 0)    return "";
    if(target < 0)     return "null";
    
    for(int num : v){
        int rem = target - num;
        std::string remRes = howSum(rem,v);
        if(remRes != "null"){
            remRes += std::to_string(num);
            remRes += " ";
            return remRes;
        }
        
    }
    return "null";
}

int main()
{
    std::vector<int> v = {2,3,4};
    int targetSum = 8;
    
    std::cout<<howSum(targetSum,v);
    return 0;
} 

我的动态问题解决方案

#include<iostream>
#include<vector>
#include<string>
#include<unordered_map>

std::unordered_map<int,std::string> mem;

std::string howSum(int target, std::vector<int> v){
    if(mem.find(target) != mem.end())
        return mem[target];
    if(target == 0)    return "";
    if(target < 0)     return "null";
    
    for(int num : v){
        int rem = target - num;
        std::string remRes = howSum(rem,v);
        if(remRes != "null"){
            remRes += std::to_string(num);
            remRes += " ";
            mem[target] = remRes;
            return mem[target];
        }
        
    }
    mem[target] = "null";
    return mem[target];
}

int main()
{
    std::vector<int> v = {7,14};
    int targetSum = 300;
    
    std::cout<<howSum(targetSum,v);
    return 0;
}

5
std::pair<bool, whatever> 可以作为 C++14 中 optional 的有效替代品。 - IWonderWhatThisAPIDoes
顺便提一下,在检查向量的元素之前,必须先进行“empty”检查。即使只是第一个元素。 - StoryTeller - Unslander Monica
1
“联合体 yourReturnValue {std::vector<int>; void *;}” - TUI lover
2
@TUIlover 看起来像是 std::optional 的基础,但 void* 使其有些不完整。在这个想法的基础上构建一个答案。 - Ted Lyngmo
5
你如何区分一个“空”的联合体和一个非空的联合体?你需要手动调用向量的适当构造函数和析构函数,否则会出现崩溃或内存泄漏。 - HolyBlackCat
显示剩余3条评论
2个回答

6
您有以下选择:

返回结果 + 布尔值

返回 std::pair<std::vector<int>, bool>,或者更好的方法是返回如下结构体:

struct Result {
    std::vector<int> result;
    bool is_valid;
};

Result howSum(int target, const std::vector<int>& in);

bool会指示结果向量是否实际可用。

输出参数

返回一个bool,指示操作是否成功,并使用输出参数(注意,非常量引用用于输出参数,以便可以从函数内部进行修改并在其外部稍后使用):

bool howSum(int target, const std::vector<int>& in, std::vector<int>& result);

optional

在C++17中,可以使用std::optional,或者使用来自boost库的类似boost::optional

std::optional<std::vector<int>> howSum(int target, const std::vector<int>& in);

std::optional 转换为 bool 或使用 has_value 方法检查是否返回了实际结果。
需要注意的是,在每种情况下最好通过 const & 传递输入向量,以避免不必要的拷贝。

2

使用可选参数(C++17),你可以像这样做:

#include<iostream>
#include<vector>
#include<optional>


std::optional<std::vector<int>> howSum(int target,std::vector<int> in){
    if(target <= 0 ) return {}; // returns "empty" optional

    auto num = in.back();
    in.pop_back();
    int remainder = target - num ;
    auto maybe_r = howSum(remainder, in);
    if (!maybe_r.has_value())
        return howSum(target, in);
    else {
        auto r = maybe_r.value();
        r.push_back(num);
        return r;
    }
}

int main(){

    std::vector<int> v = {2,4,3,1};
    int targetSum = 8;

    auto maybe_r = howSum(targetSum,v);

    if (!maybe_r.has_value()) {
        std::cout << "no result\n";
    } else {

        auto r = maybe_r.value();
        for(int o : r)
            std::cout<<o<<" ";

    }
    return 0;
}

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