Для типа индекса цикла при проверке условия завершения ›=0

Мне нужно прокрутить строку назад.

// 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, который не интуитивно понятен. Какие были бы чистые решения для этого?


person Matt    schedule 08.11.2019    source источник
comment
Нужно ли знать индекс? В противном случае вы можете просто использовать обратный итератор.   -  person tkausl    schedule 08.11.2019
comment
Отвечает ли это на ваш вопрос? обратная итерация без знака int с циклами for   -  person Borgleader    schedule 08.11.2019
comment
std::size_t — число без знака. Беззнаковые числа всегда >=0.   -  person Algirdas Preidžius    schedule 08.11.2019
comment
@AlgirdasPreidžius ОП знает, что они буквально заявляют об этом в вопросе.   -  person Borgleader    schedule 08.11.2019
comment
@Borgleader OP заявил, что при опускании ниже нуля он станет чем-то действительно большим, поэтому цикл не прерывается и в конечном итоге приведет к ошибке сегментации. Из чего не ясно, что он понимает, что такое условие (>=0) всегда будет истинным из-за природы unsigned. Он просто написал наблюдения о том, что происходит, когда вы это делаете. Я утверждал, что вообще не нужно проводить тест.   -  person Algirdas Preidžius    schedule 08.11.2019


Ответы (2)


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

int main()
{
    std::string s = "Hello, World!";
    for (std::string::reverse_iterator i = s.rbegin(); i != s.rend(); ++i)
        std::cout << *i;
}
person Blaze    schedule 08.11.2019
comment
Применимо ли это решение, если бы я начал свою обратную итерацию не с самого и (s.rbegin()), а с некоторой позиции (заданной индексом) внутри строки? В остальном очень приятно, спасибо. - person Matt; 08.11.2019
comment
Да, вы можете, например, сделать std::string::reverse_iterator i = s.rbegin()+5, чтобы он не начинался в конце, а 5 символов перед этим. - person Blaze; 08.11.2019

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

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

Or

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();
person Vlad from Moscow    schedule 08.11.2019
comment
@Matt Игнорируйте голосование против. Я показал правильные петли. - person Vlad from Moscow; 08.11.2019
comment
Я удалил свой отрицательный голос, но в свою защиту в вашем исходном ответе был только первый цикл, который присутствовал в op (!= и › в этом случае функционально эквивалентны) и считался уродливым, поэтому исходная версия этого ответа была не ответ, потому что ОП искал что-то еще. - person Borgleader; 08.11.2019
comment
@Borgleader Вы ошибаетесь. Кажется, вы не поняли вопроса. Показанная мной первая петля не эквивалентна петле в вопросе. - person Vlad from Moscow; 08.11.2019
comment
Чем первый цикл отличается от for (std::size_t i = str.length(); i > 0; i--) { (› vs != aside ofc) - person Borgleader; 08.11.2019
comment
@Borgleader Для начала вы показали другой цикл, чем в вопросе. Во-вторых, я показал, как получить доступ к элементу строки, используя индекс внутри цикла. - person Vlad from Moscow; 08.11.2019
comment
Я не прав в разделе «Возможное решение», я вставил его оттуда. - person Borgleader; 08.11.2019