Я хочу использовать цикл for с переменным размером шага, в частности, я хочу, чтобы переменная i в цикле for была равна:

  1. Все числа, кроме тех, которые можно разделить на 3 так:

я = 1-2-4-5-7-8-10-11-13-14-16-17 ...

  1. Все числа, кроме тех, которые можно разделить на 3 и 2 так:

я = 1-5-7-11-13-17 ...

Базовый код:

#include <iostream>

int main()
{
    int N = 100;
    for ( int i=0; i<N; i++) { //<-----
        //instructions
    }
    return 0;
}

Возможно ли это с помощью for цикла?

-4
Fra 29 Авг 2017 в 15:09

7 ответов

Лучший ответ

Вы можете попробовать использовать троичные операторы. Это делает читабельность вашего кода более сложной (на мой взгляд, но некоторым это нравится), но вы помещаете все в выражение for.

Для чисел, которые можно разделить на 3, например:

for (int i = 1; i < N; i = (((i+1)%3 == 0) ? i+2 : i+1)) {
    //Instructions
}

И для чисел, которые можно разделить на 3 и 2, вы можете попробовать это:

for (int i = 1; 
 i < N; 
 i = (i+1)%3 == 0 || ((i+1)%2) == 0 ? 
     ((i+2)%3 == 0 || i%2 == 0 ? 
        (i%3 == 0 || (i+1)%2 == 0 ? i+4 : i+3) : i+2 ) : i+1) {
    //Instructions
}

Для получения дополнительной информации о троичных операторах нажмите здесь.

РЕДАКТИРОВАТЬ Добавление предложения @ AMA из комментариев (проще, чем у меня)

for (int i = 1; 
     i < N; 
     i = (i+1)%2 == 0 
         ? (i+2)%3 == 0
             ? i+4
             : i+2
         : (i+1)%3 == 0 
             ? i+2
             : i+1) {
    //Instructions
}
0
AMA 30 Авг 2017 в 15:42

Для более современного стиля c ++ вы также можете использовать lambda для определения функции продвижения. Это не является строго необходимым (advance3 и advance23 ниже могут быть просто обычными функциями), но это помогает показать ваше намерение близко к тому, где вы используете функции advance.

Обратите внимание, что следующее будет включать 0, поскольку 0%n == 0. Если вы хотите исключить 0, просто начните цикл с 1.

#include <iostream>

using namespace std;

int main()
{
    int N = 100;

    auto advance3 = []( int &i ){ i++; while( i % 3 == 0 ) { i++;} };

    for ( int i=0; i<N; advance3( i ) ){ 
        cout << i << ", ";
    }
    cout << '\n';


    auto advance23 = []( int &i ){ i++; while( ( i % 3 == 0 ) || ( i % 2 == 0 ) ) { i++;}  };

    for ( int i=0; i<N; advance23( i ) ){ 
        cout << i << ", ";
    }
    cout << '\n';

    return 0;    
}
0
Steve Rodeen 29 Авг 2017 в 13:53

Задача третьего члена в цикле for состоит в предоставлении следующего значения для переменной управления циклом. Это наиболее распространенная форма - просто приращение: ++i, но оно может быть более сложным. Вы можете написать различные выражения, которые есть в некоторых других ответах, но их трудно прочитать, и, как всегда, трудно читаемый код часто означает, что вам нужно написать функцию:

for (int i = 0; i < N; i = next(i))

Где next(i) был определен, чтобы выглядеть примерно так:

int next(int i) {
    ++i;
    if (i % 3 == 0)
        ++i;
    return i;
}
0
Pete Becker 29 Авг 2017 в 12:25

Просто опустите i++ из оператора for и увеличьте счетчик на основе вашего алгоритма для "не делится на три" внутри цикла. ... или если логика достаточно проста, замените i++ на ваш алгоритм приращения.

0
mkrufky 29 Авг 2017 в 12:11

Используйте условное выражение if и continue .

for (int i = 0; i < N; i ++)
{
    if (i % 3 == 0)
        continue;
    do_stuff();
}

Оператор continue пропускает оставшуюся часть текущего цикла и сразу же переходит к следующему циклу , так что это должно работать для вас. В приведенном выше примере, если переменная i делится на 3, continue пропустит все после нее, и do_stuff не будет выполнен.

Вы можете использовать несколько continue в одном цикле, любой из них пропустит текущий цикл:

for (int i = 0; i < N; i ++)
{
    if (i % 3 == 0)
        continue;
    if (i % 2 == 0)
        continue; // Another continue
    do_stuff();
}

Что ж, давайте сделаем это просто:

for (int i = 0; i < N; i ++)
{
    if (i % 3 == 0 || i % 2 == 0)
        continue;
    do_stuff();
}
1
iBug 29 Авг 2017 в 12:17

ОБНОВЛЕНИЕ : как tobi303 и Michaël Roy предположил в комментариях, что этот метод не является экономичным / эффективным процессором и дорогостоящим. Таким образом, вы можете захотеть посмотреть на другие альтернативы, если читаемость не то, что вы ищете.

Так как, вы специально упомянули, чтобы изменить шаги так ...

Для первой части я бы попробовал что-то вроде этого:

< Сильный > 1 . Пропуск чисел, кратных 3

 for (int i = 1; i < N; i = i + 1 + ((i + 1) % 3 == 0)) {   
    //instructions
 }

< Сильный > 2 . Пропуск чисел, кратных 2 или 3 ( 'или' , потому что это то, что изображено в вашем примере):

for (int i = 1; i < N; i = i + 2 + 2 * ((i + 2) % 3 == 0)) {
    //instructions
}

Рабочий пример. Ideone

Примечание . Позаботьтесь о начальном значении 'i'. Это 1, а не 0.

PS . В первом примере 15 не должно быть.

0
vishal-wadhwa 29 Авг 2017 в 13:18
for(int i = 0; i < N; i++)
{
    if(i % 3 == 0) // if(i % 3 == 0 || i % 2 == 0) // if(is_skippable(i))
        continue;
    //instructions
}
3
AMA 12 Сен 2017 в 12:52