Задачи по языку С

       

Пояснения:


Стиль программирования 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

По идее, эта задача строго иерархична:

  • пока есть символы в строке;
  • в зависимости от вида символа используется один из нескольких вариантов:

  • выдается ALPHA;
  • выдается DIGIT;
  • выдается OTHER.

Это легко записать на языке С:

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++; Далее становится ясно что:

  • условие продолжения цикла требует, чтобы done было ЛОЖЬ;
  • done - ЛОЖЬ, пока условие в условном операторе ИСТИНА;
  • таким образом, одно из условий продолжения цикла (x/2)>1.

Укажите это явно.

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 - функция, выдающая наибольший их ее двух параметров).



Содержание раздела