下面我附上了一个项目的代码,该项目旨在查找用户输入向量中的最小值,如果向量为空则返回 -1,如果向量只有一个索引则返回 0。我遇到了向量为空的情况的问题,因为单元测试继续未能通过 returns_negative_one_for_empty_vector 测试。
main.cc
#include <iostream>
#include <vector>
#include "minimum.h"
int main() {
int size;
std::cout << "How many elements? ";
std::cin >> size;
std::vector<double> numbers(size);
for (int i = 0; i < size; i++) {
double value;
std::cout << "Element " << i << ": ";
std::cin >> value;
numbers.at(i) = value;
}
double index;
index = IndexOfMinimumElement(numbers);
std::cout << "The minimum value in your vector is at index" << index << std::endl;
}
最低.cc
#include "minimum.h"
#include <vector>
int IndexOfMinimumElement(std::vector<double> input) {
int i, min_index;
double min_ = input.at(0);
for (int i = 0; i < input.size(); i++) {
if (input.at(i) < min_) {
min_index = i;
return min_index;
}
else if (input.size() == 0) {
return -1;
}
else if(input.size() == 1) {
return 0;
}
}
};
最小.h
#include <vector>
int IndexOfMinimumElement(std::vector<double> input);
找到用户输入向量中的最小值,如果满足则返回-1 向量为空,如果向量只有一个索引,则为 0。
无需编写原始
for
循环,通过使用 STL 算法函数可以更轻松地完成。
还有其他问题,其中一个是向量应该通过
const
引用传递,而不是通过值传递。 按值传递向量会产生不必要的副本。
#include <algorithm>
#include <vector>
#include <iostream>
int IndexOfMinimumElement(const std::vector<double>& input)
{
if (input.empty())
return -1;
auto ptrMinElement = std::min_element(input.begin(), input.end());
return std::distance(input.begin(), ptrMinElement);
}
int main()
{
std::cout << IndexOfMinimumElement({ 1.2, 3.4, 0.8, 7.8 }) << std::endl;
std::cout << IndexOfMinimumElement({}) << std::endl; // empty
std::cout << IndexOfMinimumElement({3}) << std::endl; // only 1 element
return 0;
}
输出:
2
-1
0
相关函数是std::min_element和std::distance。
std::min_element
返回一个指向范围内最小元素的迭代器(类似于指针)。
代码的编写清楚地了解了每个函数的作用——它实际上是自我记录的。 要获取最小元素,请调用
std::min_element
。 要获取从第一个到找到的最小元素的距离,您可以调用 std::distance
,并使用一个到起始位置的迭代器和一个到结束位置的迭代器。
底线是:当给定正确的输入参数时,STL 算法很少(如果有的话)运行失败。 正如您所见证的,编写原始
for
循环总会有更大的失败机会。 因此,我们的目标是尽量减少编写此类 for
循环。
在
IndexOfMinimumElement
中,您在第一次迭代时return
,因为 if/else 的所有分支都会导致返回。
如果您的向量包含
{14, 2, 10, 1}
,则它将返回的索引为 1
,因为 2
小于 14
。
相反,您希望在函数顶部进行一些条件检查,这些检查根据向量的长度返回。
如果函数调用超过了这些值,它应该迭代向量中的值,检查它们是否小于运行最小值,并相应地更新最小索引。
int IndexOfMinimumElement(std::vector<double> input) {
if (input.size() == 0) return -1;
if (input.size() == 1) return 0;
int i = 0;
double min = input[0];
int min_idx = 0;
for (auto &v : input) {
if (v < min) {
min = v;
min_idx = i;
}
++i;
}
return min_idx;
}
最小测试:
int main() {
std::vector<double> foo { 1.2, 3.4, 0.8, 7.8 };
std::cout << IndexOfMinimumElement(foo) << std::endl;
return 0;
}
打印,如预期:
2
考虑让你的函数返回一个 可选
std::size_t
值,而不是在未找到的情况下返回带有 int
的 -1
。您也可以将其设为模板函数,这样它就不必只处理 double
值的向量。
template <typename T>
std::optional<std::size_t> IndexOfMinimumElement(std::vector<T> input) {
if (input.size() == 0) return std::nullopt;
if (input.size() == 1) return 0;
std::size_t i = 0;
T min = input[0];
std::size_t min_idx = 0;
for (auto &v : input) {
if (v < min) {
min = v;
min_idx = i;
}
++i;
}
return min_idx;
}
int main() {
std::vector<double> foo { 1.2, 3.4, 0.8, 7.8 };
std::cout << IndexOfMinimumElement(foo).value_or(-1) << std::endl;
return 0;
}