C ++ функция для поиска текущего номера в векторе - PullRequest
0 голосов
/ 23 ноября 2018

Мне нужно объяснение моей домашней работе: / Мне нужно написать функцию на C ++, которая принимает 3 аргумента (начальный и последний итератор векторного среза и int) и возвращает константный итератор первого найденного int (3-го аргумента) в этом векторе,Если этого 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; }

, и это моя попытка решить

#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;
            }
        }
}

1 Ответ

0 голосов
/ 23 ноября 2018

Разбивая это, я вижу одну ошибку компилятора и одно предупреждение (логическая ошибка) и одну логическую ошибку, не обнаруженную компилятором.Сначала давайте разберемся с ошибкой.

В

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

vector<int>::iterator iterator = begin

пытается сделать vector<int>::iterator из vector<int>::const_iterator.Простое исправление:

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

Но begin было передано в функцию по значению .Это означает, что вы можете делать все, что хотите, внутри функции, не затрагивая ее вне функции.Это означает, что создание переменной 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)

занимаетпозаботьтесь об этом.

Это оставляет нам только предупреждение компилятора.Никогда не игнорируйте предупреждения.Программисты, как правило, ленивы и одержимы скоростью.Они не пойдут на это и не понизят производительность печати сообщения, если это не означает что-то важное.Ошибка компилятора означает, что синтаксис неправильный и код не может быть превращен в программу.Предупреждение компилятора означает, что синтаксис правильный, и, при отсутствии других ошибок, код можно превратить в программу, но программа, вероятно, не является логически правильной.Никогда не игнорируйте предупреждения.Устраните их, где это возможно.Если они не могут быть устранены, докажите, что вы получаете поведение, которое вам требуется, и оправдывайте их.Только не игнорируйте их.

Предупреждение должно быть примерно таким: функция find не возвращает значение на всех путях.

Примечание: я настроилкод стиль отступа Allman .Я считаю, что размещение фигурных скобок и чрезвычайно регулярный поток позволяет легко обнаружить неуместные или отсутствующие скобки и ошибки определения объема.Если у вас есть проблемы с синтаксисом, этот стиль устраняет возможные источники путаницы и позволяет сосредоточиться на других проблемах.

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;
}

, который можно улучшить для краткости, но я полагаю, что в результате получается наиболее понятный код.Короткий код - это хороший, но легко читаемый код, который компилятор преобразует в ту же программу, что и более короткий код, на мой взгляд, более ценный.

Sidenote:

Это рискованноприсвойте переменной то же имя, что и ее типу.

vector<int>::iterator iterator

безопасен, потому что имя типа - vector<int>::iterator, а не просто iterator, но обычная ранняя ошибка выглядит примерно так:

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

string, переменная типа string, принимает имя string, делая string тип недоступным, когда string снова используется string name.Плохой компилятор думает, что ему велено сделать переменную типа, который является другой переменной.Это также отличный пример Почему «использование пространства имен std» считается плохой практикой? std::string string; сделает всю проблему невозможной, по крайней мере для типов в пространстве имен std.

...