Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
Переключение и работа с файлами
Понятие ввода-вывода включает в себя функции, данные и устройства. Рассмотрим, например, программу " ввод-вывод_ф". В ней используется функция getchar( ), осуществляющая ввод, причем устройство ввода - клавиатура (в соответствии с нашими предположениями), а выходные данные - отдельные символы. Изменим источник поступления в программу данных. По умолчанию Си-программа рассматривает стандартный ввод как источник поступления данных. Стандартным вводом называется устройство, принятое в качестве обычного средства ввода данных в машину. Это может быть устройство чтения данных с магнитной ленты телетайпа или терминал. Мы можем сами выбирать устройство данных из любого источника. Ну, например, мы можем написать в программе, что источник входных данных - файл, а не клавиатура. Существуют два способа написания программ, работающих с файлами. Первый способ заключается в явном использовании специальных функций, которые открывают и закрывают файлы, организуют чтение и запись данных и т.д. Этот вопрос мы будем обсуждать в 15 лекции. Второй способ состоит в том, чтобы использовать программу, спроектированную первоначально в предположении, что данные в нее вводятся с клавиатуры и выводятся на экран, но переключить ввод и вывод на другие информационные каналы, например, из файла в файл. Этот способ в некоторых отношениях обладает меньшими возможностями, чем первый, но зато гораздо проще в использовании. Операция переключения - это средство OC UNIX, а не самого языка Си. Но она оказалась настолько полезной, что при переносе компилятора с языка Си на другие вычислительные системы часто вместе с ним переносится и эта операция. Многие из вновь созданных операционных систем, таких, как MS-DOS 2, включают в себя данное средство. Сначала мы обсудим возможности этой операции в OC UNIX, а за тем и в других системах.
Переключение вывода. Предположим, мы осуществили компиляцию программы " ввод-вывод_ф" и поместили выполняемый объектный код в файл с именем get_put. Затем, чтобы запустить данную программу, мы вводим с терминала только имя файла get_put и программа выполняется так, как было описано выше, т.е. получает в качестве входных данных символы, вводимые с клавиатуры. Теперь предположим, что мы хотим посмотреть, как наша программа работает с текстовым файлом с именем words. Текстовый файл - это файл, содержащий некоторый текст, т. е. данные в виде символов. Это может быть, например, рассказ или программа на языке Си. Файл, содержащий команды на машинном языке, не является текстовым. Так как наша программа занимается обработкой символов, то она должна использоваться вместе с текстовым файлом. Для этого надо ввести следующую команду: get_put < words Символ < служит обозначением операции переключения, используемой в OC UNIX. Выполнение указанной операции приводит к тому, что содержимое файла words будет направлено в файл с именем get_put. Сама программа " ввод-вывод_ф" не знает, что входные данные поступают из некоторого файла, а не с терминала. На ее вход просто поступает поток символов, она читает их, и последовательно, по одному, выводит на печать до тех пор, пока не встретит признак EOF. Если мы наберем команду get_put < words то в результате на экране может появиться, например, следующий текст: Анализ данных, прогнозы, организация связи, создание программного обеспечения, построение моделей процессов - вот далеко неполный список областей применения знаний для компьютерных специалистов. если этот текст находится в текстовом файле words. Переключение ввода Теперь рассмотрим случай, когда нам нужно ввести текст с клавиатуры в файл с именем my_words. Для этого мы должны ввести команду get_put > my_words и начать ввод символов. Символ > служит обозначением операции переключения, используемой в OC UNIX. Ее выполнение приводит к тому, что создается новый файл с именем my_words, а затем результат работы программы " ввод-вывод_ф", представляющий собой копию вводимых символов, направляется в данный файл. Если файл с именем my_words уже существует, он обычно уничтожается, и вместо него создается новый. На экране появляются вводимые слова. Их копии будут направлены в указанный файл. Чтобы закончить работу, мы вводим EOF, в OC UNIX это обычно [CTRL/d]. Комбинированное переключение Предположим, что мы хотим создать копию файла my_words и назвать его my_words2. Нужно ввести для этого команду get_put < my_words > my_words2 и требуемое задание будет выполнено. Команда get_put > my_words2 < my_words приведет к такому же результату, поскольку порядок указания операций переключения не имеет значения. Нельзя в одной команде использовать один и тот же файл и для ввода, и для вывода. Операционные системы, отличные от OC UNIX Чем отличаются другие операционные системы от OC UNIX? Все отличия можно разделить на две группы: В других операционных системах реализована операция переключения. Компиляторы с языка Си предоставляют возможность использовать операцию переключения. У нас нет возможности рассмотреть все компиляторы с языка Си. Однако в пяти из шести версий компилятора, предназначенных для микрокомпьютеров, для указания операции переключения используются символы < >. Операция переключения отличается от аналогичной операции в двух аспектах: Указанная операция выполняется при работе программ, написанных только на Си, в то время как в OC UNIX она может использоваться при работе любой программы. Между именем файла с откомпилированной программой и знаком операции должен быть один пробел, а между знаком операции и именем файла пробел должен отсутствовать. Например:
get_put < words
7. Лекция: Выбор вариантов.
-Выбор вариантов. -Оператор if. -Расширение оператора if. -Операции отношения. -Логические операции. -Операция условия: ?:. -Множественный выбор.
Выбор вариантов Язык Си обеспечивает три основные формы управления процессом выполнения программ. Согласно теории вычислительных систем, хороший язык должен обеспечивать реализацию следующих трех форм управления процессом выполнения программ: Выполнение последовательности операторов. Выполнение определенной последовательности операторов до тех пор, пока некоторое условие истинно. Использование проверки истинности условия для выбора между различными возможными способами действия. Первая форма нам уже хорошо известна. Все наши предшествующие программы представляли собой некоторую последовательность операторов. Цикл while служит одним из примеров использования второй формы, другие способы будут рассмотрены в следующей лекции. Последняя форма делает программы гораздо более интеллектуальными, и чрезвычайно увеличивает эффективность работы компьютера Оператор if Подсчитаем число строк в файле. Это можно сделать путем счета числа символов " новая строка" в файле. Пример: /*подсчет строк */ #include < stdio.h> main( ) { int ch; int line_count=0; while((ch = getchar( ))! = EOF) if(ch == '\n') line_count++; printf(" Мы насчитали %d строк. \n", line_count); } Оператор if служит указанием компьютеру увеличить значение переменной line_count на 1, если только что прочитанный символ, содержимое переменной ch, представляет собой символ " новая строка". Что происходит в случае, когда значение переменной ch не является символом " новая строка"? Тогда в цикле while производится чтение следующего символа. Оператор if считается одиночным оператором, начинающимся от ключевого слова if и завершающимся символом " точка с запятой". Модифицируем программу. Подсчитаем одновременно число символов и строк в файле: /* подсчет числа строк и символов */ #include < stdio.h> main( ) { int ch = 0; int line_count = 0; int char_count = 0; while((ch = getchar( ))! = EOF) { char_count++; if(ch == '\n') line_count++; } printf(" Мы насчитали %d символов и %d строк.\n", char_count, line_count); } Теперь в цикл while входят два оператора, поэтому мы использовали фигурные скобки, чтобы отметить начало и конец цикла. Расширение оператора if Простейшей формой оператора if является if(выражение) оператор Под выражением здесь понимаем условное выражение. С его помощью сравниваются значения двух величин. Если такое выражение истинно, то оператор выполняется. В противном случае он пропускается. В общем случае в качестве условия может быть использовано любое выражение, и если его значение равно 0, то оно считается ложным. Оператор может быть простым или составным, т. е. блоком. Пример: /* пример одиночного оператора и блока */ #include < stdio.h> main( ) { int i; i=getchar( ); if(i > 5) /* одиночный оператор*/ printf(" Значение больше 5.\n" ); if(i < 5) { /* составной оператор*/ printf(" Значение\n" ); printf(" меньше 5.\n" ); } } Простая форма оператора if позволяет выбрать оператор, возможно, составной, или пропустить его. Язык Си предоставляет также возможность выбрать любой из двух операторов путем использования конструкции if-else. Напишем программу, заменяющую каждый символ из таблицы ASCII на следующий символ, кроме символа " новая строка". Пример: /* код_1*/ #include < stdio.h> main( ) { char ch; while ((ch=getch( ))! = EOF) { /* оставить символ " новая строка неизменным" */ if (ch == '\n') putchar(ch); else /* заменить остальные символы*/ putchar(ch + 1); } } Общий вид оператора if-else выглядит следующим образом: if(выражение) оператор else оператор Если выражение истинно, то выполняется первый оператор, а если ложно, то выполняется оператор, следующий за ключевым словом else. Операторы могут быть простыми или составными.
Простая конструкция if позволяет нам выбрать, выполнить или нет некоторое действие; конструкция же if-else дает возможность выбрать одно из двух действий. Подведем итоги. Оператор if имеет две формы: if(выражение) оператор; и if(выражение) оператор1; else оператор2; Если в результате вычисления значения выражения получено значение " истина" (ненулевое значение), то в обоих формах оператора if выполняется оператор1. Если вычисленное значение выражения равно значению " ложь" (нулевое), тогда выполнение оператора if, представленного в первой форме, заканчивается, а в операторе, имеющем вторую форму, выполняется оператор 2. Совместное использование обеих форм оператора if приводит к неоднозначности, называемой " проблемой висящего else". Например, вложенный оператор if if(e1) if( e2) оператор1; else оператор2; может быть интерпретирован так if (e1) if(e2) оператор1; else оператор2; или как if(e1) if(e2) оператор1; else оператор2; Эта неоднозначность разрешается в языке Си с помощью правила, в соответствии с которым часть else оператора всегда относится к синтаксически самому правому, игнорируя любые отступы, оператору if без части else. Следовательно, первая интерпретация является интерпретацией, принятой в языке Си.
if(e1) if(e2) оператор1; else ; /* точка с запятой здесь обозначает пустой оператор*/ else оператор2; Для явного указания намерений программиста можно использовать и фигурные скобки. Например, обе вышеприведенные интерпретации можно записать явно так: if(e1) { if(e2) оператор1; else оператор2 } и if(e1) { if(e2) оператор1; } else оператор2; Операции отношения Операции отношения используются для сравнений. Мы уже обсуждали их, но здесь мы остановимся на их обсуждении подробнее.
Этот список хорошо соответствует возможным числовым соотношениям.
Операции отношения применяются при формировании условных выражений, используемых в операторе if и while. Указанные операторы проверяют, истинно или ложно данное выражение. Пример: #include < stdio.h> main( ) { int mark; mark = getchar( ); if(mark == 4) printf(" Оценка 4.\n" ); else if (mark > 4) printf(" Оценка больше 4! \n" ); else /* случай, когда оценка меньше 4 */ { mark++; printf(" Теперь оценка на 1 больше.\n" ); } } Что такое истина Мы ответим на этот вопрос, как он решается в языке Си. В Си выражение всегда имеет значение. Это утверждение остается верным даже для условных выражений, как показывает пример, приведенный ниже. В нем определяются значения двух условных выражений, одно из которых оказывается истинным, а второе - ложным: /* истина и ложь*/ main( ) { int true, false; true = (12 > 2); /*отношение истинно*/ false = (12 == 2); /*отношение ложно*/ printf(" true = %d; false = %d\n", true, false); } При выполнении программы получим следующие результаты: true = 1, false = 0. В языке Си значение истина равно 1, а значение ложь равно 0. В языке Си все ненулевые значения являются истинными, и только 0 являются ложью. Например, два оператора if(i! =0 ) можно заменить на if(i) поскольку выражение (i! =0 ) и выражение (i) оба примут значения 0, или ложь, только в том случае, если значение переменной i равно 0. Осложнение с понятием истина Рассмотрим следующую программу: /* занятость */ main( ) { int age =20; while (age++ < = 63) { /* делится ли возраст на 20*/ if((age % 20) == 0) printf(" Вам %d.\n", age); if(age = 63) printf(" Вам уже %d.\n", age); } } Мы хотели написать программу, чтобы результат работы программы выглядел так: Вам 40. Вам 60. Вам уже 63. На самом деле выход будет таким: Вам уже 63. Вам уже 63. Вам уже 63. и т. д. - до бесконечности. Это произошло, потому что мы ошибочно написали if(age = 63) вместо if(age == 63) В операторе if(age = 63) переменной age присваивается значение 63, т. е. результат этого оператора - истина и выполняется оператор printf(" Вам %d.\n", age); В операторе while(age++ < = 63) условие выполняется, и программа зацикливается. Приоритеты операций отношения мы описали в лекции 3. Логические операции Иногда бывает полезным объединить два или более условных выражения. Например, нам нужно подсчитать, сколько символов не является пробелами, символами новая строка и табуляции. Напишем такую программу: /* число символов */ main( ) { int ch; int count=0; while((ch=getchar( ))! = EOF) if(ch! =' ' & & ch! = '\n' & & ch! = '\t') count++; printf(" Всего %d непустых символов. \n", count); } Оператор, использующий логическую операцию и, обозначаемую & &. Смысл действий, осуществляемых оператором if, можно пояснить так:
Если прочитанный символ - не пробел и не символ " новая строка", и не символ табуляции, то происходит увеличение значения переменной count на единицу. Все выражение будет истинным, если указанные три условия - истины. В языке Си имеются три логические операции. Операция условия: ?: В языке Си имеется короткий способ записи одного из видов оператора if-else. Он называется " условным выражением" и использует операцию условия -?:. Эта операция состоит из двух частей и содержит три операнда. Рассмотрим, как можно найти абсолютное значение числа: x = (y < 0)? -y: y; Все, что находится между знаком = и символом " точка с запятой" представляет собой условное выражение. Смысл этого оператора заключается в следующем: если y меньше 0, то x=-y; в противном случае x=y. В терминах оператора if-else данный оператор мог выглядеть так: if (y < 0) x=-y; else x=y; В общем виде условное выражение можно записать следующим образом: выражение1? выражение2: выражение3 Если выражение1 истинно (не равно нулю), то значением всего условного выражения является величина выражение2; если выражение1 ложно (равно 0), то значение всего условного выражения - величина выражение3.
Множественный выбор Когда в программе нужно осуществить выбор одного из нескольких вариантов, мы можем сделать это, используя конструкцию if-else if-else_...else Во многих случаях оказывается более удобным применять оператор switch. Оператор switch (переключатель) используется для разветвления программы по нескольким направлениям. Он имеет следующую форму: switch(e) { сase c1: s1; break; case c2: s2; break; ... case ck: sk; break; default: s(k+1); } где e - целое выражение (или выражение, которое может быть преобразовано в целое выражение); ci - целое выражение с постоянным значением (или выражение, которое может быть преобразовано к такому выражению); si обозначает операторы, число которых может быть больше или равно нулю. Метки ci, обозначающие альтернативы case, должны быть уникальными; двух одинаковых меток быть не может. Только одна альтернатива может получить префикс default. Результатом выполнения оператора switch является выбор альтернативы с меткой ci, которая равна значению выражения переключателя e; в этом случае выполняются операторы si. В случае, если выражение переключателя не равно ни одному из выражений альтернатив case, то выполняются операторы s(k+1); при отсутствии альтернативы default не выполняется ни одна из альтернатив оператора switch. Пример: /* Реализация работы калькулятора. Сначала задается число - сколько раз нужно подсчитать. Вводятся левый операнд, операция, правый операнд. Оператор выбора определяет, какой оператор должен работать. Результат выводится на экран. */ #include < stdio.h> #include < conio.h> #include < process.h> main() { float a, b; char opr; float result=0; int I, i=0; clrscr(); printf(" Сколько раз будете считать?: \n" ); scanf(" %I", & I); printf(" Введите операнд, операцию, операнд: \n" ); while(i< I) { i++; scanf(" %f%c%f", & a, & opr, & b); switch(opr) { case '+': result=a+b; break; case '-': result=a-b; break; case '*': result=a*b; break; case '/': result=a/b; break; default: printf(" Ошибка. Неверен знак операции " ); exit(1); /* функция берется из заголовочного файла process.h*/ } textcolor (15); /* функция берется из заголовочного файла conio.h*/ cprintf(" Результат равен %g\n", result); if (i< I) printf(" Введите операнд, операцию, операнд\n" ); else { textcolor(12); /* функция берется из заголовочного файла conio.h */ cprintf(" Конец работы\n" ); /* текст печатается красным цветом*/ } } getch (); exit(0); /* функция берется из заголовочного файла process.h */ }
|
Последнее изменение этой страницы: 2017-04-13; Просмотров: 382; Нарушение авторского права страницы