关于功能设计的问题

时间:2011-02-10 16:43:58

标签: c++

我刚刚接受了一个关于我如何设计一个简单函数的面试问题 - 在Int数组中找到第二大数字。

int findSecondLargest(int * arr, int len){
    int second = 0;
    ...

    return second;
}

然而,我被问及以下有关如何处理这些问题的问题。

  1. 如果len小于2(我想我们可以返回一个特殊值,如0或MinInt。)
  2. 但是,如果第二大是0(因为在这种情况下,我无法区分错误和正常返回值。所以我可能会抛出异常)
  3. 如果数组是{1,1,1}(因为1是最大的数字,不是第二大数字。所以我可能会抛出异常)
  4. 我真的感到困惑。我认为不可能处理所有情况。我们通常必须记录函数的用法,而不是抛出异常。

    希望得到一些建议。感谢

    //函数体由我自己编写。我非常喜欢Donotalo和PigBen所设想的设计

5 个答案:

答案 0 :(得分:11)

遵循标准库模型,在搜索序列时,我们不返回我们要查找的值,我们返回一个迭代器到该值(在这种情况下是一个指针)。如果我们没有找到值,我们将迭代器返回到最后一个元素之后,签名将如下所示:

// end is not the last element, it is one past the last element
int * findSecondLargest(int * begin, int * end);

答案 1 :(得分:2)

面试官是否给出了职能机构?如果没有,我会编写一个函数,返回数组中第二大项的索引。如果找不到第二大项(如错误情况),我的函数将返回len以指示找不到第二大项。

答案 2 :(得分:1)

返回'特殊值'(例如0)的问题是,数组中的第二大数字可能为0.你怎么能分辨出来?

写入的函数无法使用它的返回值来指示何时发生错误。您可以重构它以返回错误代码并使用out参数填充找到的值(非常C风格),或者您可以抛出异常(更多C ++风格)。

编辑:

我刚刚发现,如果返回的值是数组中第二大数字的索引,则可以使用负数作为“特殊值”。

答案 3 :(得分:0)

具体使用该功能并不排除处理角落情况。它只是意味着您在这种情况下明确记录了函数的行为。

您是否抛出异常或返回特定(魔术)值取决于您。您可能还会要求更改返回类型,以便您可以进行更丰富的诊断。

在任何情况下,考虑整个投入领域都是一种好习惯。例如,您在这里也忘记了将arr NULLlen视为否定的情况。

答案 4 :(得分:0)

使用GCC特定的变量数args-to-macro表示法仅用于测试,但无论如何,基本思想是:

  

如果len小于2(我想我们可以返回一个特殊值,如0或MinInt。)

  • 这里,我返回一个NULL指针,而不是一个安全的解除引用指针,所以在数据中有0或MinInt没有问题。
  

但是,如果第二大是0(因为在这种情况下,我无法区分错误和正常返回值。所以我可能会抛出异常)

合理输入的例外非常糟糕!

  

如果数组是{1,1,1}(因为1是最大的数字,不是第二大数。所以我可能会抛出异常)

这是有争议的,但这是我建模的行为,也是通过返回NULL。

所以:

  • 使用指针vs NULL
  • 区分找到的条件和未发现的条件
  • 第二大值可以通过跟踪最大值来维持,因为我们迭代一次

代码有点杂乱,但FWIW:

#include <iostream>

template <typename T, int N>
T* second_largest(T (&arr)[N])
{
    if (N < 2) return NULL;
    T* largest = &arr[0];
    T* second = NULL;
    for (int i = 1; i < N; ++i)
    {
        if (arr[i] > *largest)
        {
            second = largest;
            largest = &arr[i];
        }
        else if (arr[i] != *largest && (!second || arr[i] > *second))
            second = &arr[i];
        std::cout << "i " << i << ", largest " << (largest ? *largest : -1)
            << ", second " << (second ? *second : -1) << '\n';
    }
    return second;
}

#define TEST(ASSERTION, ARRAY...) \
{ \
    int x[] = { ARRAY }; \
    int* p = second_largest(x); \
    assert(ASSERTION); \
    std::cout << #ASSERTION << " passed for " << #ARRAY << '\n'; \
}

int main()
{
    TEST(*p == 4, 1, 3, 2, 5, 4, 0);
    TEST(!p, 1, 1, 1);
    TEST(!p, 1);
    TEST(*p == 1, 1, 2);
    TEST(*p == 1, 2, 1);
    TEST(*p == 1, 1, 2, 0);
    std::cout << "all tests passed\n";
}