Язык Си - Уэйт, Прата, Мартин. M. уэит с. Прата д. Мартин
Скачать 4.69 Mb.
|
ВЫ ДОЛЖНЫ БЫЛИ УЗНАТЬ В ЭТОЙ ГЛАВЕ Далее Содержание Что делает функция getchar() вводит в программу символ, поступающий с клавиатуры терминала. Что делает функция putchar(ch) отображает символ, содержащийся в переменной ch, на экран. Что символы != означают: не равно. Что такое EOF: специальный символ, указывающий на конец файла. Как переключить стандартный ввод на ввод из файла: program < file Как переключить стандартный вывод на вывод в файл: program > file Что такое порты: средства доступа к подсоединенным устройствам. Как использовать порты: путем вызова функций inp( ) и outp( ). ВОПРОСЫ И ОТВЕТЫ Далее Содержание Вопросы 1. Выражение putchar(getchar( )) является правильным. Будет ли правильным вы ражение getchar(putchar( ))? 2. Что произойдет в результате выполнения каждого из следующих операторов? a. putchar('H' ); б. putchar(' \007'); в. putchar('\n'); г. putchar(' \b') 3. Допустим, у вас есть программа count, подсчитывающая число символов в файле. Напишите команду, в результате выполнения которой будет пpoизвeдeн подсчет числа символов в файле essay, а результат будет помещен в файл essayct. 4. Даны программа и файлы, описанные в вопросе 3. Какие из приведенных ниже команд правильны? a. essayct <essay б. count essay в. count < essayct г. essay > count 5. Что делает оператор outp(212, 23)? 117 Ответы 1. Нет. У функции getchar( ) аргумент должен отсутствовать, а у функции putchar( ) аргумент обязательно должен быть. 2. а. печать буквы Н б. вывод символа '\007', в результате чего сработает громкоговоритель в. переход на новую строку на устройстве вывода г. шаг назад на одну позицию. 3. count < essay > essayct или иначе count > essayct < essay 4. а. неправильно, поскольку essayct не является выполняемой программой б. неправильно, поскольку опушен знак операции переключения. (Позже вы научитесь писать программы, для которых не нужно будет использовать операцию переключения) в. правильно, при выполнении этой команды число символов, полученное в результате работы программы count из вопроса 3, появится в виде сообщения на экране. г. неправильно, имя выполняемой программы должно стоять первым 5. Он посылает число 23 через порт 212. УПРАЖНЕНИЯ 1. Напишите программу, описанную в п. 3, т. е. программу, подсчитывающую число символов в файле. 2. Модифицируйте программу count так, чтобы при учете каждого символа раздается звуковой сигнал. Введите в программу короткий цикл, реализующий временную задержку, для того чтобы отделить один сигнал от другого. 3. Модифицируйте программу сигнал2 так, чтобы во время ее выполнения можно было вводить величину, определяющую число повторении тела цикла. 1) Используется отрывок из произведения Д. Байрона "Еврейские мелодии" перевод С.Я. Маршака - Прим. перев. 2) Приводится отрывок из произведения В. Блейка "Прорицания невинности Перевод С.Я. Маршака. - Прим. перев. 3) Перевод: знание орфографии - залог четкости письма - Прим. перев. 4) Перевод: что случилось? - Прим перев. if, else, switch, break, case, default > >= <= < == != && || / :? 118 Хотите научиться создавать мощные, "интеллектуальные", универсальные и полезные программы? Тогда вам потребуется язык, обеспечивающий три основные формы управления процессом выполнения программ. Согласно теории вычислительных систем (которая является наукой о вычислительных машинах, а не наукой, создаваемой такими машинами), хороший язык должен обеспечивать реализацию следующих трех форм управления процессом выполнения программ: 1. Выполнение последовательности операторов. 2. Выполнение определенной последовательности операторов до тех пор, пока некоторое условие истинно. 3. Использование проверки истинности условия для выбора между различными возможными способами действия. Первая форма хорошо известна; все наши предыдущие программы представляли собой некоторую последовательность операторов. Цикл while служит одним из примеров использования второй формы; другие способы будут рассмотрены в гл. 8. Последняя форма - выбор между различными возможными способами действия - делает программы гораздо более "интеллектуальными" и чрез вычайно увеличивает эффективность работы компьютера. В данной главе мы и займемся этим вопросом. ОПЕРАТОР if Далее Содержание Начнем с очень простого примера. Мы уже видели, как нужно написать программу, подсчитывающую число символов в файле. Предположим, вместо символов мы хотим подсчитать строки. Это можно сделать путем счета числа символов "новая строка" в файле. Ниже приводится соответствующая программа: /* подсчет строк */ #include < stdio.h> main( ) { int ch; int linecount = 0; while((ch = getchar( )) != EOF) if(ch =='\n') linecount ++; printf(" Я насчитала %d строк \n", linecount); } Сердцевиной" программы является оператор if(ch == '\n') linecount ++; Этот "оператор if" служит указанием компьютеру увеличить значение переменной linecount на 1, если только что прочитанный символ (содержимое переменной ch) представляет собой символ "новая строка". Знак == не является опечаткой; его смысл выражается словами "равняется". Не путайте эту операцию с операцией присваивания (=). Что происходит в случае, когда значение переменной ch не является символом "новая строка"? Тогда в цикле while производится чтение следующего символа. Оператор if, который мы только что применили в программе, считается одиночным оператором, начинающимся от ключевого слова if и завершающимся символом "точка с запятой". Вот почему мы не использовали фигурные скобки, чтобы отметить начало и конец тела цикла while. Совсем несложно усовершенствовать программу так, чтобы она подсчитывала символы и строки одновременно; давайте попробуем это сделать. 119 /* 1cс - подсчет числа строк и символов */ #include main( ) { int ch; int linecount = 0; int charcount = 0; while((ch = getchar( )) != EOF) { charcount ++ ; if(ch == '\n' ) linecount++ ; } printf(" Я насчитала %d символов и %d строк.\n", charcount, linecount); } Теперь в цикл while входят два оператора; поэтому мы использовали фигурные скобки, чтобы отметить начало и конец тела цикла. Мы вызываем скомпилированную программу Icc и используем операцию переключения, чтобы подсчитать число символов и строк в файле с именем chow. Ice Следующий шаг в "развитии" этой программы - придание ей способности подсчитывать число слов. Это лишь немного труднее того, что мы делали до сих пор, но сначала нам нужно изучить ряд дополнительных вопросов, связанных с использованием операторов if. РАСШИРЕНИЕ ОПЕРАТОРА if С ПОМОЩЬЮ else Далее Содержание Простейшей формой оператора if является та, которой мы только что воспользовались: if(выражение) оператор Обычно под выражением здесь понимают условное выражение, с его помощью сравниваются значения двух величин (например x > y или c == 6). Если такое выражение истинно (x больше у или c равно 6), то оператор выполняется. В противном случае он пропускается. Вообще говоря, в качестве условия может быть использовано любое выражение, и если его значение равно 0, то оно считается ложным - дальнейшие детали мы обсудим чуть позже. Оператор может быть простым, как в нашем примере 1) , или составным (блоком), начало и конец которого отмечены фигурными скобками: if (score > big) printf(" Полная победа!\n"); /* простой оператор */ if (jое > rоn) /* составной оператор */ { joecash + + ; printf(" Ты проиграл, Рон.\n"); } Простая форма оператора if позволяет выбрать оператор (возможно, составной) или пропустить его. Язык Си предоставляет также возможность выбрать любой из двух операторов путем использования конструкции if-else. Выбор: конструкция if-else Далее Содержание 120 В предыдущей главе мы привели очень простую программу шифровки сообщений, которая заменяла каждый символ следующим по порядку в таблице ASCII. К сожалению, она заменила даже символ "новая строка", что привело к объединению нескольких строк в одну. Можно исключить эту проблему, написав программу, реализующую простой выбор: если символ - "новая строка", то оставить его без изменений, в противном случае преобразовать его. Вот как это можно запрограммировать на языке Си: /* код1 */ #include main( ) { char ch; while((ch = getchar( )) != EOF) { if(ch =='\n' ) /* оставить символ */ putchar(ch); /* "новая строка" неизменным */ else putchar(ch + 1); /* заменить остальные символы */ } } В прошлый раз был использован файл, содержащий следующий текст 2) : Good spelling is an aid to clear writing. Его использование в качестве теста для нашей новой программы приводит к результату: Ура! Она работает! Между прочим, совсем несложно написать и программу дешифровки. Скопируйте для этого программу код1, но только замените выражение (ch + 1) на (ch - 1). Вы обратили внимание на общий вид оператора if-else. Он выглядит следующим образом: if (выражение) оператор else оператор Если выражение истинно, то выполняется первый оператор, а если ложно, то выполняется оператор, следующий за ключевым словом else. Операторы могут быть простыми или составными. Правила языка Си не требуют отступа в строке, но это стало обычной практикой. Отступ позволяет с первого взгляда заметить те операторы, выполнение которых зависит от проверяемого условия. Простая конструкция if позволяет нам выбирать: выполнить или нет некоторое действие; конструкция же if-else дает возможность выбрать одно из двух действий. Что делать, если нам требуется осуществить выбор из большого числа вариантов? Множественный выбор: конструкция else-if Далее Содержание Часто нам приходится осуществлять выбор более, чем из двух вариантов. Чтобы учесть это, мы можем расширить структуру if-else конструкцией else-if. Рассмотрим конкретный пример. Расценки, назначаемые за коммунальные услуги некоторыми компаниями зависят от количества потребляемой энергии. Приведем расценки, установленные за пользование электроэнергией: Первые 240 кВт/ч: 0.05418 долл. за кВт/ч Следующие 300 кВт/ч: 0.07047 долл. за кВт/ч Свыше 540 кВт/ч: 0.09164 долл. за кВт/ч Если вас занимает этот вопрос, мы могли бы подготовить программу, вычисляющую стоимость потребляемой энергии. Приведем пример программы, являющейся первым шагом, сделанным в 121 этом направлении: РИС. 7.1. Операторы if и if else /* счет за электроэнергию */ /* вычисляет плату за электроэнергию */ #definе RATE1 0.05418 /* тариф за первые 240 кВт/ч */ #define RATE2 0.07047 /* тариф за следующие 300 кВт/ч */ #define RATE3 0.09164 /* тариф за потребление свыше 540 кВт/ч */ #define BASE1 13.00 /* плата за первые 240 кВт/ч */ #define BASE2 34.14 /* плата за первые 540 кВт/ч */ #define BREAK1 240.0 /* величина, определяющая первое условие ветвления */ #define BREAK2 540.0 /* величина, определяющая второе условие ветвления */ main( ) { float kwh; /* количество использованных кВт/ч */ float bill; /* плата */ printf(" Укажите, пожалуйста, количество использованных кВт/ч.\n"); scanf(" %f, &kwh); if (kwh < BREAK1) bill = RATEl * kwh; else if(kwh < BREAK2) /* количество кВт/ч между 240 и 540 */ bill = BASE1 + RATE2*kwh; else /* количество кВт/ч свыше 540 */ bill = BASE2 + RATE3*kwh; printf(" Плата за %.1f кВт/ч составляет $%1.2f. \n", kwh, bill); } 122 Для обозначения тарифов были использованы символические константы, которые поэтому оказались собранными в одном месте. Если электрическая компания изменит свои расценки (а это может случиться), то такое расположение констант не позволит нам забыть скорректировать какую- нибудь из них. Мы задали в символическом виде и константы, соответствующие граничным значениям потребляемой мощности Они также подвержены изменениям. Управляющая логика программы реализуется путем npoстого выбора одной из трех расчетных формул в зависимости oт значения переменной kwh, что иллюстрируется на рис. 7.2. Мы хотим подчеркнуть, что программа в процессе выполнения может достичь первого употребления else только в том случае, если величина переменной kwh больше или равна 240. Поэтому строка else if(kwh < BREAK2) эквивалентна требованию, чтобы значение kwh было заключено между 240 и 540, это мы и указали в коментарии к программе. Совершенно аналогично последнее употребление else может быть достигнуто, только если значение kwh больше или равно 540. И наконец, отметим, что константы BASE1 и BASE2 представляют собой величину платы за первые 240 или 540 кВт/ч электроэнергии соответственно. Поэтому требуется только прибавить дополнительную плату за количество потребляемой электроэнергии, превышающее эти величины. РИС. 7.2. Блок схема программы расчета платы за электроэнергию Фактически конструкция else-if является видоизмененным способом задания условного оператора, с которым мы познакомились раньше. Ядро нашей программы представляет собой другую форму записи следующей последовательности операторов. if(kwh < BREAK1) bill = RATEl*kwh; else if(kwh < BREAK2) bill = BASE1 + RATE2*kwh; else bill = BASE2 + RATE3*kwh; Отсюда видно, что программа состоит из оператора if-else, для которого часть else представляет собой другой оператор if-else. Про второй оператор if-else говорят, что он "вложен" в первым. (Между прочим, вся структура 123 if-else считается одним оператором. Вот почему мы не должны заключать вложенную конструкцию if-else в фигурные скобки). Эти две формы записи являются абсолютно эквивалентными. Единственное отличие - дополнительные пробелы и символы "новая строка", но они игнорируются компилятором. Тем не менее первая форма записи предпочтительнее, поскольку она более четко показывает, что мы осуществляем выбор из трех возможностей. Кроме того, она облегчает просмотр программы и понимание семантики каждого варианта. Применяйте форму записи, использующую вложение операторов там, где это необходимо - например когда требуется проверить значения двух разных величин или (в на шем случае) если бы была установлена 10%-ная дополнительная плата за потребление энергии свыше 540 кВт/ч только в летние месяцы. В одном операторе можно использовать столько конструкций else if, сколько нужно, что иллюстрируется приведенным ниже фрагментом: if (score < 1000) bonus = 0; else if (score < 1500) bonus = 1; else if (score < 2000) bonus = 2; else if (score < 2500) bonus = 4; else bonus = 6; (Этот фрагмент мог быть взят из игровой программы, где пере менная bonus представляет собой количество дополнительных "фотонных бомб" или "питательных гранул", получаемых игроком для следующей партии ). Объединение операторов if и else Далее Содержание Когда у вас в программе имеется несколько конструкции if и else, каким образом компилятор решает, какому оператору if соответствует какой оператор else? Рассмотрим, например, фрагмент программы: if(number > 6) if(number < 12) printf ("Вы закончили!\n"); else printf("Простите, вы потеряли ход.\n"); В каком случае фраза "Простите, вы потеряли ход!" будет напечатана? Когда значение переменной number меньше или равно 6, или когда оно больше 12? Другими словами, чему соответствует else: первому if или второму? Ответ выглядит так: else соответствует второму if, т.е. при выполнении программы результаты будут такими: Число: Результат: 5 Нет 10 Вы закончили! 15 Простите, вы потеряли ход! Существует правило, которое гласит, что else соответствует ближайшему if, кроме тех случаев, когда имеются фигурные скобки. Мы сознательно записали этот фрагмент так, как будто else соответствует первому if, но вспомните, что компилятор не обратит внимания на отступы в строках. Если мы действительно хотим чтобы else соответствовал первому if, необходимо данный фрагмент оформить следующим образом: if(number > 6) { if(number < 12) printf (" Вы закончили '\n"); 124 } else printf(" Простите, вы потеряли ход!\n"); Теперь результат может выглядеть так Число: Результат: 5 Простите, вы потеряли ход! 10 Вы закончили! 15 Нет РИС. 7.3. Структура соответствия if и else. Резюме: использование операторов if для организации выбора из нескольких вариантов КЛЮЧЕВЫЕ CЛOBA: if, else ОБЩИЕ ЗАМЕЧАНИЯ: В каждой из последующих форм оператором может быть либо простои оператор, либо составной. Выражение "истинно" в обобщенном смысле, если его значение - ненулевая величина. ФОРМА ЗАПИСИ 1: if(выражение) оператор Оператор выполняется, если выражение истинно. ФОРМА ЗАПИСИ 2: if(выражение) оператор1 else оператор2 Если выражение истинно, выполняется оператор1, в противном случае - оператор2. 125 ФОРМА ЗАПИСИ 3: if(выражение1) оператор1 else if(выражение2) оператор2 else оператор3 Если выражение1 истинно, выполняется оператор1. Если выражение1 ложно, но выражение2 истинно, выполняется оператор2. В случае когда оба выражения ложны, выполняется оператор3. ПРИМЕР: 3) if(legs == 4) printf("Это, возможно, лошадь. \n"); else if (legs > 4) printf(" Это не лошадь. \n"); else /* случай, когда legs < 4 */ { legs++; printf(" Теперь животное имеет еще одну ногу.\n"); } |