Если i четно, for(int j = 0; j < m; j++)
В противном случае, если iнечетно, for(int j = m-1; j > 0; j--)
Я хотел бы объединить эти два условия следующим образом.
for( (i%2==0) ? (int j = 0; j < m; j++) : (int j = m-1; j > 0; j--))
Но, похоже, это не удалось.
Есть ли способ объединить два условия, используя ? или другой способ языка C?
Таким образом нельзя использовать (тройной) оператор ?:. Просто сделайте очевидную/простую версию: if ((i % 2) == 0) { for (int j = 0; j < m; ++j) { /* do even */ } } else { for (int j = m - 1; j > 0; --j) { /* do odd */ } }
Если вам просто нужен вопросительный знак, вы можете сделать for(int i=0; i<n ??! i<n; i++).





Нет, их нельзя комбинировать с условным оператором . Операндами условного выражения являются каждое выражение, возвращающее значение, а результатом условного выражения является одно значение.
Цикл for имеет форму for( init expression; condition expression; iteration expression) loop-body и принимает три выражения.
Вы пытаетесь вернуть какой-то трехэлементный кортеж (init, condition, iteration) выражений из тернарной системы, который будет служить в качестве выражений инициализации/условия/итерации цикла for, но вы не можете упаковать эти вещи, а затем распаковать их таким образом. Синтаксис просто в корне неверен.
Используйте if/else. Если вы хотите поделиться телом цикла, поместите его в функцию и вызывайте функцию из каждого цикла:
if (i % 2 == 0) {
for (int j = 0; j < m; j++) {
do_things(j);
}
} else {
for (int j = m-1; j > 0; j--) {
do_things(j);
}
}
'Было бы жаль, если бы do_things() требовалось множество дискретных переменных, которые присутствовали в вызывающей функции...
@ Fe2O3 Не уверен, в чем твоя точка зрения. Факторируйте свой код так, как вам нравится.
Нет, вы не можете... Меня, вероятно, следует сослать в самые глубокие ямы ада за упоминание об этом, но «выражение утверждения» GCC можно было бы исказить и злоупотребить настолько, чтобы сделать то, что предлагает ФП. Да, теперь я вручную скопирую K&R 20 миллионов раз в качестве наказания. :-)
Вы могли бы сделать что-нибудь хаотичное и запутанное, например следующее, но я бы не рекомендовал это делать. При этом ведется обратный отсчет от m-1 до 0, если i нечетное, и от 0 до m-1, если i четное. Обратите внимание, что исходный вопрос ведет обратный отсчет от m-1 до 1, и я предположил, что вы хотите от m-1 до 0, поэтому исправьте при необходимости.
Будьте осторожны с «неожиданными» входными значениями m, например. отрицательные, потому что в этом случае цикл может не завершиться, когда вы захотите.
#include <stdio.h>
int main()
{
int i = 1;
int m = 8;
int start = i%2 ? m-1 : 0;
int end = i%2 ? -1 : m;
int delta = i%2 ? -1 : 1;
for (int j = start; j != end; j += delta)
{
printf("j=%d\n", j);
}
return 0;
}
if iis odd, for(int j = m-1; j > 0; j--) ... Забавно, что ОП выбирает ответ «один на один».
jarmod, длинный цикл, а затем неопределенное поведение с экстремальными входными данными, такими как int i = 0; int m = -1;. j != end не является достаточным условием остановки.
@ Fe2O3 Fe2O3 да, вы правы, но я предполагал, что исходный вопрос по ошибке завершил цикл раньше, когда i нечетно. Это была догадка. Возможно, это была хорошая догадка, я не знаю, но я написал решение, исходя из этого предположения. Я также точно указал, каковы были начальные/конечные значения, чтобы ОП мог решить, правильно ли это, и исправить при необходимости.
@chux-ReinstateMonica да, и спасибо. Я изменил ответ, добавив дополнительное предупреждение.
Не усложняйте цикл, считая в большую или меньшую сторону... Просто переведите счетчик цикла по мере необходимости:
void doit( int m, int i ) {
// peculiar imbalance in OP's ranges :\
// if i is odd, bail out BEFORE reaching 0th value
m -= i%2;
for( int j = 0; j < m; j++ ) {
int k = i%2 ? m - j : j; // ternary, and begin using 'k'
printf( "%d ", k );
}
putchar( '\n' );
}
int main( void ) {
doit( 15, 0 );
doit( 15, 1 );
return 0;
}
Результат:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
14 13 12 11 10 9 8 7 6 5 4 3 2 1
Обновлено:
Обеспокоенный тем, что другие ответы предлагают либо дублировать обработку в двух отдельных циклах, либо дублировать вызов функции, ниже приведена упрощенная версия вышеизложенного. Как и другие данные ответы, эта версия игнорирует несбалансированные диапазоны OP для прямого и обратного счета.
int main( void ) {
for( int i = 0; i <= 1; i++ ) { // demonstrate both even and odd
unsigned m = 10; // # of steps
for( unsigned j = 0; j < m; j++ ) { // traverse range
int k = i%2 ? m - j - 1: j; // descending or ascending
printf( "%d ", k ); // Simulate processing
/* more processing with this value */
}
putchar( '\n' );
}
return 0;
}
Результат:
0 1 2 3 4 5 6 7 8 9
9 8 7 6 5 4 3 2 1 0
(Изменено на unsigned, чтобы обойти проблему, поднятую @Chux)
int main( void ) {
double temp = get_double( "Temperature: " );
int i = get_int( "Is this Celsius(0) or Fahrenheit(1): " );
for( unsigned m = 3, j = 0; j < m; j++ ) {
switch( (i%2) ? m - j - 1: j ) {
case 0:
temp *= (i%2) ? 5 : 1.0/5;
break;
case 1:
temp *= (i%2) ? 1.0/9 : 9;
break;
case 2:
temp += (i%2) ? -32 : 32;
break;
}
}
printf( "%.2lf%s\n", temp, i%2 ? "C" : "F" );
return 0;
}
Спасибо, это очень помогает. Я желаю вам всего наилучшего !!!!
Золотое правило, чтобы стать успешным программистом: не усложняйте вещи просто так. Пишите код максимально простым и читабельным способом.
Например, это очень читабельно, и поэтому его очень трудно улучшить дальше:
if (i % 2) // odd
{
for(int j=m-1; j > 0; j--)
{
do_stuff_with(something[i][j]);
}
}
else // even
{
for(int j = 0; j < m; j++)
{
do_stuff_with(something[i][j]);
}
}
Мы могли бы написать более непонятный цикл, подходящий для обоих случаев, но польза от этого сомнительна, поскольку код становится только труднее читать, а очевидных преимуществ нет:
// not really recommended
int start;
int end;
int mod;
if (i % 2) // odd
{
start = m-1;
end = -1;
mod = -1;
}
else // even
{
start = 0;
end = m;
mod = 1;
}
for(int j=start; j!=end j+=mod)
{
do_stuff_with(something[i][j]);
}
(Возможно, это может быть разумно в некоторых сценариях ручной оптимизации для повышения производительности кэша данных, но только после фактического тестирования и обнаружения узкого места в производительности.)
Спасибо, что напомнили мне золотое правило. Мне действительно не следует усложнять свой код
Вы понимаете, что второй цикл выполняется на один раз меньше, чем первая версия, верно? Я ожидаю, что они оба будут запускаться одинаковое количество раз, но без контекста не могу быть уверен, что правильно.