C , почему оператор в итераторе не работает, если его поместить после выражения, *(v.begin() i / 10) ?

#c #iterator

#c #итератор

Вопрос:

Это упражнение взято из учебника для начинающих (C ):

Давайте предположим, что у нас есть набор оценок в диапазоне от 0 до 100. Мы хотели бы подсчитать, сколько оценок попадает в различные кластеры по 10. Между нулем и 100 существует 101 возможная оценка. Эти оценки могут быть представлены 11 кластерами: 10 кластеров по 10 оценок в каждом плюс один кластер для получения идеального результата 100. Первый кластер будет считать оценки от 0 до 9, второй будет считать оценки от 10 до 19 и так далее. Конечный кластер подсчитывает, сколько баллов из 100 было достигнуто.

Кластеризация оценок таким образом, если наши входные данные

42 65 95 100 39 67 95 76 88 76 83 92 76 93

тогда вывод должен быть

0 0 0 1 1 0 2 3 2 4 1

 int main() 
{
    vector<int> v(11, 0);
    int i;
    while (cin >> i)
    {
          *(v.begin()   i / 10); 
    }
    for (autoamp; r : v)
    {
        cout << r << 't';
    }
    cout << endl;
        
    return 0;
}
  

Если строка

*(v.begin() i / 10);

изменяется на

*(v.begin() i / 10) ;

Программа ничего не считывает в вектор. Почему?

Комментарии:

1. Найдите приоритет оператора , чтобы увидеть, какой оператор будет вычислен первым.

2. в сторону: почему нет v[i / 10] / v[i / 10] ?

3. Упростите и исключите арифметику итератора. Просто подумайте о *it vs (*it) vs *(it )

4. Вы только сбиваете себя с толку, написав такой код. Компилятор механически следует правилам для его интерпретации. Можно бесплатно добавлять дополнительные переменные только для удобства чтения, например int scaled_score = i/10 . Компилятору не нужно будет выделять для этого дополнительную память.

5. обе версии нечитабельны, поэтому лучше вам переработать эту строку

Ответ №1:

В выражении *(v.begin() i / 10); begin() итератор сначала увеличивается на i / 10 , затем результирующий итератор разыменовывается, а затем int объект, на который ссылаются, увеличивается.

Но в выражении *(v.begin() i / 10) ; begin() итератор сначала увеличивается на i / 10 , так же, как указано выше. Но из-за приоритета оператора оператор имеет более высокий приоритет, чем * оператор, поэтому результирующий итератор увеличивается, а затем разыменовывается. Объект int , на который ссылаются, остается нетронутым.

Комментарии:

1. в случае с ‘ (v.begin () i / 10) ;’ если ‘i’ равно 55, итератор увеличивается до 5, затем оператор ‘ ‘ делает его 6, а затем » оператор разыменовывает 6-й элемент без каких-либо изменений …… я получил его, покапишу это, спасибо)

Ответ №2:

Я работал над той же проблемой (с примерами из учебника) и смог решить ее с помощью итераторов. Смотрите код ниже.

 // Exercise_3.25.cpp : Rewrite the grade clustering program from 3.3.3 (p. 104) using iterators instead of subscripts.

#include <iostream>
using std::cout;
using std::cin;
using std::endl;

#include <vector>
using std::vector;

int main()
{
    // count the number of grades by clusters of ten: 0--9, 10--19, ... 90--99, 100
    vector<unsigned> scores(11, 0);

    // hold the grades we read from the standard input
    vector<unsigned> grades;

    // 42 65 95 100 39 67 95 76 88 76 83 92 76 93
    unsigned grade;

    while (cin >> grade)    // read the grades
    {
        if (grade <= 100)   // handle only valid grades
        {
            grades.push_back(grade);
        }
    }

    // for each grade in the input
    for (auto iter = grades.begin(); iter != grades.end(); iter  )
    {
        unsigned i = *iter;
        // increment the counter for the current cluster
        (*(scores.begin()   i / 10))  ;
    }

    for (auto iter = scores.cbegin(); iter != scores.cend(); iter  )
    {
        cout << *iter << " ";
    }

    return 0;
}