2

我经常不得不编写将索引返回到数组中的方法,在该数组中可能找不到索引。我使用了三种基本方法:

  1. 将“空索引”值定义为负数(即,如果函数返回 -1,则表示没有有效的索引可返回
  2. 将“空索引”值定义为索引类型的最大值(即,如果索引为 int,则函数返回 INT_MAX)。
  3. 传入一个指向布尔值的指针,该指针指示返回值是否为有效索引(即,如果返回值是数组中的实际索引,则传入一个指向设置为 true 的布尔值的指针,否则返回值为 false)

我已经看到了所有这些方法的使用(尽管第三个选项似乎少了很多)。对于其中哪一个更可取(或者是否有第四个选项)是否有任何共识?

4

7 回答 7

3

如有疑问:复制 STL。例如 std::string::npos、std::vector::end() 等。我想这将是您列表中的选项 2。

像 STL 容器一样工作的容器也可以重用 STL 算法。

于 2013-09-14T00:54:34.137 回答
2

#4。返回最近的较低索引的负数,即插入点。先加1,这样你就不用担心-0了。所以任何否定的结果都是'找不到',如果你在下一个操作中需要它,你可以从中得到一个插入点

于 2013-09-14T00:58:15.027 回答
1

Does nobody remember errno? I'd argue this is a reasonable solution. If the function returns a certain value such as 0 (since we are talking about array indices) and errno == ERANGE, an invalid index is returned:

idx =foo.bar(baz);
if (!idx && errno == ERANGE) {
    // problem
}

Arguably, you don't even need to set a value since you would need to check errno anyway.

This way, you have full use of the array. The other approach is a variation of this, which is already a variation of the Boolean value approach: use a class-local error variable, similar to I/O errors that set badbit, failbit and/or eofbit. If you aren't using a class, then I'd say errno/the Boolean approach is the best.

于 2013-09-14T01:46:22.947 回答
1

In most cases, I would say #4:

  • Return a status code indicating whether the operation succeeded or failed and return the index by reference (either using references or a pointer depending on your version of C).

The advantages of #4 over #3 are:

  1. When you need a function to return more than one value, just add more reference parameters for the values you need to return.

  2. If your C functions always return status codes everywhere in your program, then you always know that the return code is status.

  3. It does not eat into your value space for the return index (or other data types) that your function returns and avoids magic number constants. (For example, if you were returning a temperature value in Celsius, 0 and -1 are both valid as are any positive numbers. You might return -274 as invalid, but that is a little obtuse.)

  4. The return code can give a reason for failure or success more than just a Boolean success or failure in a pretty straightforward way.

OTOH, if you program is pretty small, and you don't mind a few magic constants, then either #1 or #2 are morally equivalent and can make for less typing than #3 or #4. #2 has a few advantages over #1:

  1. As mentioned in other answers, a signed int return value can only represent half of the numbers an unsigned int can represent.

  2. It avoids signed vs. unsigned comparison issues if you are comparing against sizeof(array), std::vector::string, which are size_t. Most often the issue is a compiler warning gets ignored (leading people to generally ignore warnings when they should not) or someone fixes it with a cast, hopefully after analyzing to make sure that the cast is really valid.

I have personally used #1, #2, and #4 and find the #4 scales the best. I tend to default to #4, especially in code where failures are common and need to be handled. Either 1 or 2 usually work out best if the code is smaller and you are calling a lot of routines that return one thing and cannot fail (e.g., image processing routines).

于 2013-09-14T01:47:20.913 回答
1

由于数组中的索引通常是非负整数,因此返回负整数(例如-1)以指示无效索引是一种可接受的方法。

于 2013-09-14T00:47:01.397 回答
1

在某些情况下有用的另一种技术是使用 1 .. N 作为索引,并将 NULL 索引设置为 0,因此您可以从第 0 个元素中提取某种默认值,或者累积到第 0 个元素中。这样,在您的调用者中,您实际上不必检查是否获得了 NULL 索引。

于 2013-09-14T00:59:12.593 回答
0

最好的“空索引”是与空模型匹配的索引。那是一个根本不存在的索引。

要完成它,您通常会抛出异常。

于 2013-09-14T01:06:33.237 回答