Для типа индекса цикла при проверке на> = 0 условие завершения - PullRequest
0 голосов
/ 08 ноября 2019

Мне нужно перебрать в обратном направлении по строке.

// std::string str assumed to be defined at this point
for (std::size_t i = str.length() - 1; i >= 0; i--) {
  // perform some check on str[i]
}

Описание проблемы
Теперь, если я использую индекс цикла int i, это работает, потому что я в конечном итоге стану-1 и цикл завершается. При использовании std::size_t i (без знака) для рабочего индекса, он становится чем-то действительно большим при переходе «ниже» нуля, поэтому цикл не прерывается и в конечном итоге приведет к ошибке сегментации. Какой предпочтительный способ решить эту проблему, учитывая, что я хочу использовать std :: size_t в качестве типа индекса цикла, так как std :: string :: length возвращает std :: size_t, а не int.

Возможное решение

for (std::size_t i = str.length(); i > 0; i--) {
  // perform some check on str[i - 1]
}

Я думаю, что это действительно ужасно, так как мы используем i как «смещенный» idx, который не является интуитивным. Какие бы были чистые решения для этого?

Ответы [ 2 ]

2 голосов
/ 08 ноября 2019

Если вам не нужно i внутри цикла, вы можете использовать обратный итератор:

int main()
{
    std::string s = "Hello, World!";
    for (std::string::reverse_iterator i = s.rbegin(); i != s.rend(); ++i)
        std::cout << *i;
}
0 голосов
/ 08 ноября 2019

Предпочтительный цикл с индексом будет выглядеть так:

for ( std::size_t i = str.length(); i != 0; i--) {
  // perform some check on str[i-1]
  //                       ^^^^^^^^
}

Или

for ( std::size_t i = str.length(); i-- != 0; ) {
  // perform some check on str[i]
  //                       ^^^^^^
}

Также вместо объявления

std::size_t i = str.length();

вы можете просто написать

auto i = str.length();
...