Стиль программирования 1.1.
Если изменить условие, то часто удается избавиться от оператора продолжения. Иногда получившаяся программа становится существенно проще. В этой задаче достаточно изменить условие в условном операторе.
while(A) if (!B) C;
Стиль программирования 1.2.
Оператор do...while - это такая конструкция языка С, от которой лучше избавляться. Если можно использовать либо оператор do...while, либо оператор while, то следует всегда предпочитать второй, так как в нем условие проверяется перед каждым выполнением тела цикла. Тот факт, что условие продолжение цикла не проверяется перед первым выполнением тела цикла, служит источником многих ошибок.
В этой задаче операторы do...while и условный - лишние; их можно заменить оператором while.
do { if (A) { B; C: } } while (A) | Вначале избавимся от оператора продолжения. |
while (A) { B; C; } | Затем заменяем операторы do...while и условный на оператор while. |
Стиль программирования 1.3.
Насколько трудно разобраться в конструкциях со многими вложенными условными операторами, хорошо известно программистам: когда доходишь до самого внутреннего условия, внешние условия забываешь или упускаешь из виду. Можно, конечно, полностью пояснить условия, но тогда они становятся слишком длинными и непонятными с самого начала. Во всяком случае, лучше всегда придерживаться меры.
Здесь предлагается два способа решения этой проблемы:
if ( a && B && C ) D; else if (!A && B && C ) E; else if (!A && B && !C ) F;
или if (B) if ( A && C ) D; else if (!A && C ) E; else if (!A && !C ) F;
Стиль программирования 1.4
По идее, эта задача строго иерархична:
Это легко записать на языке С:
while ( (c=getchar())!='\n') { if ( c>='a' && c<='z' ) return (ALPHA); else if ( c>='0' && c<='9' ) return (DIGIT); else if ( c!=' ' && c!='\t' ) return (OTHER); } return (EOL);
Стиль программирования 2.1
done=i=0; while(i<MAXI&&!done) { if((x/2)>1) i++; else done++; } | Первое наблюдение - конструкция if...continue действует как if...else. Так и используйте if...else. |
i=0; while(i<MAXI&&(x/2)>1))i++; | Далее становится ясно что:
Укажите это явно. |
for (i=0; i<MAXI&&(x/2)>1; i++); | Оператор while, которому предшествует инициация и который содержит изменение управляющей переменной, есть в точности оператор for. |
Стиль программирования 2.2
Обычно некоторую некоторую идею в С можно реализовать многими способами. Полезно объединять эти идеи в некоторые группы (нечто целое). В языке есть несколько уровней представления таких групп:
В этой задаче существуют два уровня иерархии. На низшем уровне находятся выражения B, D, F и G. Вместе они существуют как взаимоисключающие варианты одного переключателя. Более органичным представлением переключателя будет конструкция if...else if.
if (A) B; else if(C) D; else if(E) F; else G; return;
Стиль программирования 2.3
Самое главное, что надо обнаружить в этой задаче, - это то, что используемая конструкция эквивалентна переключателю с тремя взаимоисключающими вариантами.
plusflg=zeroflg=negflg=0; (if( a>0 ) ++plusflg; (if( a==0 ) ++zeroflg; else ++negflg;
Стиль программирования 2.4
i=0; while((c=getchar())!=EOF&&c!='\n') { if(c!='\n'&&c!='\t') { s[i++]=c; continue; } if(c=='\t') c=' '; s[i++]=c; } | Первое, что надо сделать, - это переписать выражения, выделив вложенность операторов. Затем обратить внимание на операторы разрыва и продолжения, действительно ли они нужны. От оператора разрыва легко избавиться, если добавить отрицание его условия к условию в операторе while. |
i=0; while((c=getchar())!=EOF&&c!='\n') { if(c!='\t') { s[i++]=c; continue; } if(c=='\t') c=' '; } | Теперь можно убрать первое условие в условном операторе. (c!='\n' находится теперь в условии цикла, значит, в теле цикла оно всегда будет истинно.) |
i=0; while((c=getchar())!=EOF&&c!='\n') { if(c!='\t') s[i++]=c; else s[i++]=' '; } | Оператор продолжения действует как конструкция if...else. |
for(i=0; (c=getchar())!=EOF&&c!='\n'; i++) { if(c!='\t') s[i]=c; else s[i]=' '; } | Наконец, очевидно, что s[i] - следующий символ, если это не табуляция; иначе же это пробел. |
for(i=0; (c=getchar())!=EOF&&c!='\n'; i++) s[i] = c!='\t' ? c : ' '; | Другими словами, здесь происходит замена табуляции на пробелы. Последние два варианта показывают это достаточно ясно. Очевидно также и сходство между условным оператором и условным выражением. В этом примере в условном операторе акцент делается на проверке на табуляцию, а в условном выражении - на присваивании s[i]. |
Стиль программирования 2.5
if (j>k) y=j/(x!=0 ? x : NEARZERO); else y=k/(x!=0 ? x : NEARZERO); | В этой задаче очевидно, что x!=0 не основное соображение; проверка просто предохраняет от деления на 0. Условное выражение естественно реализует эту проверку. |
y=MAX(j,k)/(x!=0 ? x : NEARZERO); | Далее можно прийти к выводу, что основное здесь - присваивание переменной y, которое включает обе проверки (MAX - функция, выдающая наибольший их ее двух параметров). |