【问题标题】:C++ function to find current number in vectorC ++函数在向量中查找当前数字
【发布时间】:2019-04-26 07:25:44
【问题描述】:

我需要解释我的作业:/ 我需要用 C++ 编写一个函数,它需要 3 个 arg(向量切片和 int 的初始和最终迭代器)并返回此向量中第一个找到的 int(3th arg) 的 const 迭代器.如果这个 int 不在我们的向量中,我们应该返回 const final 向量迭代器。此函数使用迭代器而不是索引,并且仅使用“向量标头”。这是示例程序

int main() {
const std::vector<int> vector {3, -1, 7, 12, -5, 7, 10};
std::cout << find(vector.begin() + 3, vector.end(), 7) - vector.begin() << std::endl; }

这是我试图解决的问题

#include <iostream>
#include <vector>
using namespace std;
vector<int>::const_iterator find(vector<int>::const_iterator, vector<int>::const_iterator, int);

int main() {

    const std::vector<int> vector {3, -1, 7, 12, -5, 7, 10};
    std::cout << find(vector.begin() + 3, vector.end(), 7) - vector.begin() << std::endl;

}


vector<int>::const_iterator find(vector<int>::const_iterator begin, vector<int>::const_iterator end, int num) {

        for(vector<int>::iterator iterator = begin; iterator != end;) {
            if (*iterator == num){
                return iterator;
            } else {
                return end;
            }
        }
}

【问题讨论】:

  • 你忘记问了 :-)
  • 有什么问题?对我来说似乎是一个好的开始。不要忘记实际增加迭代器!
  • ++iterator 丢失。
  • 你为什么[试图]从const_iterator切换到iterator
  • 重新考虑else。代码目前说的是,如果我第一次尝试没有找到数字,我放弃。

标签: c++ c++11 vector iterator


【解决方案1】:

分解后,我看到一个编译器错误和一个警告(逻辑错误)和一个编译器未公开的逻辑错误。首先让我们先处理错误。

for(vector<int>::iterator iterator = begin; iterator != end;)

vector<int>::iterator iterator = begin

尝试从vector&lt;int&gt;::const_iterator 中生成vector&lt;int&gt;::iterator。简单的解决方法是

for(vector<int>::const_iterator iterator = begin; iterator != end;)

但是begin 一直是passed into the function by value。这意味着你可以在函数内部做任何你想做的事情,而不会在函数外部影响它。这意味着根本不需要创建变量iterator

for(/*do nothing here*/; begin != end;)

足以消除错误。这会导致逻辑错误。

for(vector<int>::iterator iterator = begin; iterator != end;)

和改进版

for(/*do nothing here*/; begin != end;)

不做任何事情来推进迭代器以使循环看起来比第一个值更多。

for(/*do nothing here*/; begin != end; ++begin)

会处理的。

这给我们留下了编译器警告。永远不要忽视警告。程序员往往很懒惰并且痴迷于速度。如果它并不意味着重要的事情,他们就不会努力并会因打印出一条消息而遭受性能损失。编译器错误意味着语法错误并且代码无法转换为程序。编译器警告意味着语法正确,并且在没有其他错误的情况下,可以将代码转换为程序,但程序可能在逻辑上不正确。永远不要忽视警告。尽可能消除它们。如果它们不能被消除,证明你得到了你需要的行为并证明它们是合理的。只是不要忽略它们。

警告应该类似于 function find 不会在所有路径上返回值。

注意:我已将代码调整为Allman indentation style。我发现它的大括号放置和非常规则的流程使得错误放置或丢失的括号和范围错误很容易被发现。如果您遇到语法问题,这种风格可以消除可能的混淆来源,让您专注于其他问题。

vector<int>::const_iterator find(vector<int>::const_iterator begin, 
                                 vector<int>::const_iterator end, 
                                 int num) 
{
    for(/*do nothing here*/; begin != end; ++begin)
    {
        if (*begin== num)
        {
            return begin;
        } 
        else 
        {
            return end;
        }
    }
}

两个return 语句都在for 循环内。如果以begin == end 开头,则for 循环将永远不会进入,并且函数将在没有有效return 的情况下退出。退出声明为返回值而不返回值的函数的结果是未定义的。该程序可以做任何事情,包括看起来有效。

这真正指出的是return end; 不是你想要的。它应该在所有值都经过检查并发现不足之后放置。换句话说,在循环之外。这使得else 案例为空且无用。删除它。

离开

vector<int>::const_iterator find(vector<int>::const_iterator begin, 
                                 vector<int>::const_iterator end, 
                                 int num) 
{
    for(/*do nothing here*/; begin != end; ++begin)
    {
        if (*begin == num)
        {
            return begin;
        } 
    }
    return end;
}

为了简洁起见,可以对其进行改进,但我相信会产生最容易理解的代码。短代码很好,但易于阅读的代码,编译器将转换为与较短代码相同的程序,在我看来更有价值。

旁注:

给变量赋予与其类型相同的名称是有风险的。

vector<int>::iterator iterator

是安全的,因为类型的名称是vector&lt;int&gt;::iterator,不仅仅是iterator,而且一个常见的早期错误看起来像

string string; 
string name; // inscrutable error message here.

stringstring 类型的变量,取名为string,使得当string 再次被string name 使用时,string 类型不可访问。可怜的编译器认为它被告知要创建一个类型为另一个变量的变量。这也是Why is "using namespace std" considered bad practice? 的一个很好的例子std::string string; 将使整个问题变得不可能,至少对于std 命名空间中的类型。

【讨论】:

  • .... 好老师太难了,你的回答很好,因为现在我明白了!谢谢你:)
猜你喜欢
  • 1970-01-01
  • 2021-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-07
  • 2021-06-15
  • 2020-08-22
  • 2011-10-12
相关资源
最近更新 更多