ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы.



 

Часть 4

          
                  ГЛАВА 4. ПРОГРАММИРОВАНИЕ В ТУРБО-СИ
          
          Есть ли у вас опыт программирования на языке Си? Скорее всего,
     вы  слышали о том, что Си - очень трудный для изучения язык. Это не
     так. Действительно, некоторые программисты  получают  удовольствие,
     составляя  на  Си программы, которые трудно читать и отлаживать, но
     никто не говорит, что и вы должны делать точно так же. Основные по-
     нятия языка Си достаточно просты для понимания и использования.
                       Краткое содержание главы 4
          В  этой главе даются основные сведения о языке Си и приводятся
     примеры написания программ на Си. Более подробно язык описан в сле-
     дующей  главе  "Еще  раз  о программировании в Турбо-Си", а глава 9
     "Программирование в Турбо-Си на продвинутом этапе" знакомит с моде-
     лями памяти, прерываниями, программировании на асссемблере и други-
     ми темами из области "высшей математики" программирования.
          Конечно, эти главы не могут претендовать на исчерпывающее  из-
     ложение  всех сведений о Си, о котором написаны целые книги. В нас-
     тоящее время в продаже имеются две хорошие новые кники, которые  мы
     рекомендуем  программистам, изучающим Си. Это Using Turbo-C/Исполь-
     зование Турбо-Си/ и Advanced Turbo-C /Турбо-Си для опытных програм-
     мистов/,  обе  написаны Гербертом Шильдтом и выпущены издательством
     Осборн-МакГроу Хилл.
          Перед тем, как читать эту главу, прочтите главу 2  "Интегриро-
     ванное окружение системы программирования Турбо-Си" и познакомьтесь
     с использованием меню и текстового редактора Турбо-Си. Кроме  того,
     вы  должны  установить Турбо-Си /сделать рабочие копии ваших дисков
     или скопировать с них файлы на Винчестер/, так, как это  описано  в
     главе  1,  а  также  создать файл TCCONFIG.TC как описано в этой же
     главе, иначе Турбо-Си не найдет директорию  библиотечных  /\LIB/  и
     включаемых /\INCLUDE/ файлов.
          Удостоверившись,   что   все  сделано,  сядьте,  включите  ваш
     компьютер /если вы этого еще не сделали/ и будьте готовы к изучению
     программирования в Турбо-Си.
                  Создание первой программы в Турбо-Си
          По традиции, первой для программиста программой на  Си  должна
     быть  программа Hello, World, описанная в классическом труде Керни-
     гана и Ричи "Язык программирования Си". Начните с  ввода  следующей
     командной строки /из DOS/:
                               tc hello.c
          В  результате  выполнения  этой команды вызывается версия Тур-
     бо-Си с интегрированным окружением, создается файл с именем HELLO.C
     /если  он уже не существует/, и вы попадаете в редактор Турбо-Си, в
     котором вам необходимо набрать следующую программу:
          
          Закончив ввод программы, ее необходимо записать на диск  перед
     тем,  как двигаться дальше - было бы очень жаль, если после зависа-
     ния компьютера весь ваш труд пропал  даром.  Для  записи  программы
     нажмите  F2  или выберите пункт Save из меню работы с файлами File,
     нажав F10 F S.
                               Компиляция
          Теперь, когда программа записана на диск, до ее запуска  необ-
     ходимо сделать две вещи: оттранслировать и скомпоновать ее.
 
          Для трансляции исходного файла нажмите Alt-F9 /нажмите одновре-
     менно клавиши Alt и F9/. Вторым способом трансляции исходного файла
     является  возврат  в  главное меню транслятора Compile, и еще раз С
     для выбора  пункта трансляции в объектный файл /Compile to OBJ/.
           После завершения трансляции, которая займет  не  более  одной
     или  двух секунд, на экране появится мигающее сообщение об успешном
     завершении работы: "Succerss: Press any key" /успех, нажмите  любую
     клавишу/.  После нажатия любой клавиши окно исчезнет и вы окажетесь
     в главном меню.
          Если в процессе работы были какие-либо ошибки, сообщения о них
     и  предупрежления  будут находиться в окне сообщений в нижней части
     экрана. В данном случае никаких сообщений быть не должно,  если  же
     они  есть, проверьте правильно ли вы списали программу и оттрансли-
     руйте ее еще раз.
                                 Запуск
          После успешной трансляции программа готова к запуску. Т.к. ме-
     ню в данный момент активно, можно нажать R /Run/. Если вы вернулись
     в редактор, нажмите Alt-R или выйдите в главное меню нажатием F10 и
     нажмите  R для выполнения команды Run. На экране появится окно ком-
     поновщика, показывающее, что Турбо-Си ищет необходимые библиотечные
     процедуры.
          Если в это время появились ошибки, скорее всего это  произошло
     потому,  что  вы не указали, где находятся библиотечные файлы. Если
     окно компоновщика до сих пор находится на экране, уберите его нажа-
     тием любой клавиши, затем нажмите последовательно F10 и О для выхо-
     да в меню установки параметров Options /или используйте  сокращение
     Alt-O/.
          Нажав Е выберите пункт Environment /окружение/, а затем нажми-
     те L для выбора пункта определения библиотечной директории  Library
     directory.  После  появления на экране окна библиотечной директории
     напечатайте полное имя пути поддиректории, в которой находятся биб-
     лиотечные   файлы  /это,  возможно,  будет  имя  A:\TURBOC\LIB  или
     C:\TURBO\LIB/ и нажмите Enter.
          Для выхода из меню Environment нажмите Esc,  затем  нажмите  S
     для  сохранения установленных параметров /Store Options/. На экране
     появится прямоугольник, в который надо впечатать имя файла конфигу-
     рации,  в  нем  уже  будет  указано имя TCCONFIG.TC. Просто нажмите
     Enter, когда Турбо-Си спросит вас, стирать ли старый файл  конфигу-
     рации, нажмите Y.
           Наконец,  нажмите  Esc для выхода из меню Options и нажмите R
     для запуска программы. Теперь компоновка  программы  должна  завер-
     шиться  успешно.  Это  значит, что для запуска вашей программы Тур-
     бо-Си копирует в нее необходимые для ее работы процедуры из библио-
     теки  исполняющей  системы. По умолчанию используется малая /Small/
     модель памяти /более подробно о моделях памяти  говорится  в  главе
     9/, поэтому Турбо-Си берет процедуры из библиотеки с именем CS.LIB.
          После  компоновки  программы Турбо-Си запускает ее на выполне-
     ние. Экран очищается, в  верхней  его  части  появляется  сообщение
     Hello, world, а в нижней части - сообщение Press any key to Turbo C
     ... Нажмите любую клавишу - на экране появится знакомый экран  Тур-
     бо-Си.  Примите  наши  поздравления  - вы только что запустили свою
     первую программу!
 
                             Что случилось?
          Теперь прекратите работу Турбо-Си и посмотрите, что получилось
     в  результате  вашей работы. Выберите команду Quit из меню работы с
     файлами.
          На подсказку Dos наберите команду dir hello и  нажмите  Enter.
     На экране появится список файлов, который будет выглядеть приблизи-
     тельно так:
          HELLO.C          42   1-01-80   9:25p
          HELLO.OBJ       221   1-01-80   9:26p
          HELLO.EXE      4486   1-01-80   9:26p
          Первый файл HELLO.C содержит исходный текст  вашей  программы.
     Его  можно посмотреть на экране при помощи команды DOS. Напечатайте
     команду type hello.c и вы увидите его. Этот  файл  достаточно  мал,
     всего 42 байта.
          Второй  файл, HELLO.OBJ, содержит машинные инструкции в двоич-
     ном виде /объектный код/, этот файл создан  транслятором  Турбо-Си.
     Если  вы  попытаетесь распечатать его командой type, на экране поя-
     вится бессмысленный набор символов.
          Последний файл, HELLO.EXE, представляет  из  себя  выполняемую
     программу,  созданную  компоновщиком  Турбо-Си. В нем находятся как
     файл HELLO.OBJ, так  и  все  необходимые  процедуры,  как  например
     print,  которые компоновщик скопировал из файла библиотеки. Для за-
     пуска выполняемого файла напечатайте в командной строке DOS его имя
     без расширения .ЕХЕ.
          Из командной строки операционной системы наберите hello и наж-
     мите Enter. В верхней части экрана появится сообщение Hello,  world
     и снова подсказка DOS. Итак, вы написали работающую программу и мо-
     жете раздать ее всем своим знакомым, которые,  конечно,  жаждут  ее
     получить.
                 Модификация первой созданной программы
          Вернитесь в Турбо-Си, напечатав в командной строке tc hello.c.
     Вы оказались в редакторе с загруженой в него программой. Изменим ее
     так,  чтобы ввести в нее простейший диалог. Теперь программа должна
     выглядеть так:
          
          К вашей старой программе добавилиь три строки. Первая  из  них
     /char  name  [30];/ объявляет переменную с именем name, которая мо-
     жет содержать строку длиной до 29 символов /цифр, букв, знаков пре-
     пинания  и  т.д./.  Вторая строка, введенная вами, вызывает функцию
     print для вывода на экран сообщения What's your name? /как вас  зо-
     вут?/. Третья добавленная строка вызывает функцию scanf для присво-
     ения переменной name вашего имени.
          Сохраните отредактированную программу, нажав F2 или F10  F  S.
     Нажмите F10 для вызова главного меню, затем нажмите R /Run/. Обра-
     тите внимание, Турбо-Си понимает, что программа изменена, поэтому
     перед запуском она будет перетранслирована.
          Теперь  после  запуска  программы  произойдет следующее: экран
     очистится и в верхней части экрана появится сообщение  What's  your
     name? /маркер находится после знака вопроса?/. Напечатайте ваше имя
     и нажмите Enter. После этого программа печатает  Hello  <ваше_имя>.
     Обратите внимание, воспринимается только первое введенное вами имя,
     почему это так, мы объясним позднее в данной главе. А пока  нажмите
     любую клавишу для возврата в Турбо-Си.
 
          По мере написания программ вы  будете  получать  сообщения  об
     ошибках  и  предупреждения.  Появление  ошибки означает, что в теле
     программы есть ошибка, не позволяющая создать объектный  код.  Пре-
     дупреждение  означает, что в данном месте может быть что-то не так.
     Ошибки и предупреждения выводятся в окне сообщений.  Все  различные
     сообщения об ошибках и предупреждения подробно описаны в Приложении
     3.
                  Написание второй программы в Турбо-Си
          Отредактируем нашу программу и создадим на  ее  основе  новую.
     Войдите  в окно редактора /нажмите F10 E или Alt-E/ и отредактируй-
     те программу следующим образом
          
          
          Вы внесли в первоначальную программу 5 изменений, а именно:
               -  строка, определяющая переменную name заменена на стро-
                  определяющую переменные a, b, sum /все целые/;
               -  изменено сообщение, выводимое функцией printf;
               -  изменена форматная строка и список  переменных функции
                  scanf;
               -  добавлен оператор присвоения sum = a + b;
               -  изменена  форматная строка и список аргументов в функ-
                  ции printf:
          Не пугайтесь символов процента /%/, амперсанда /&/ и  обратной
     черты /\/. Ниже мы объясним, зачем они нужны.
                             Запись на диск
          Теперь  НЕ нажимайте клавишу F2. Если вы ее нажмете, программа
     будет записана на диск и получит имя HELLO.C, а вы хотите  записать
     ее под другим именем.
          Вместо  этого  нажмите F10 и вернитесь в главное меню. Нажмите
     F, затем W для вызова команды File/Write  to.  На  экране  появится
     подсказка, в ответ на которую надо ввести новое имя программы. Вве-
     дите имя sum.c и нажмите Enter. Теперь ваша вторая программа  будет
     храниться  на  диске под именем SUM.C. Нажмите F10 и вновь вызовите
     главное меню.
                              Запуск SUM.C
          Нажмите  R  для выбора команды Run. Турбо-Си начнет транслиро-
     вать вашу программу. Если вдруг появится ошибка, вернитесь  в  окно
     редактора и убедитесь, что ваш текст в точности соответствует напе-
     чатанному в примере.
          Если ошибок нет, Турбо-Си скомпонует программу с соответствую-
     щими библиотечными процедурами и запустит программу на выполнение[7
     экран очистится и на нем появится сообщение:
                Enter two values: /введите два значения/
          Сейчас программа ждет ввода двух целых чисел, разделенных про-
     белами,  табуляциями  и/или  возвратами каретки. Не забудьте нажать
     Enter после ввода второго значения. Когда второе значение  введено,
     программа  напечатает  их  сумму и, после нажатия любой клавиши, вы
     попадете в Турбо-Си.
          Поздравляем! Вы написали две  абсолютно  различные  программы,
     использовав  несколько  основных  элементов программирования. Каких
     имено? Об этом вы узнаете, прочитав до конца эту главу, прежде  чем
     начать главу 5.
 
                Семь основных элементов программирования
          Целью  большинства программ является решить какую-либо задачу.
     Задачи решаются программами путем различных манипуляций с  информа-
     цией и данными. Необходимо:
          - ввести информацию в программу;
          - иметь место для хранения информации;
          - давать инструкции по обработке информации;
          - выводить информацию из программы пользователю /обычно, вам/
          Вы можете организовать инструкции таким образом, что:
          - некоторые из них выполняются только тогда, когда какое-либо
            условие или набор условий истинны;
          - другие повторяются некоторое число раз;
          - третьи разделяются на группы, которые  могут  выполняться  в
            различных местах програамы
          Итак, мы только что описали семь основных элементов программи-
     рования: ввод, типы данных, операторы, вывод, условное  выполнение,
     циклы  и  подпрограммы.  Этот список не очень полон, но он действи-
     тельно охватывает все то общее, что есть в различных программах.
          Во многих языках программирования все это есть, многие,  вклю-
     чая Си, имеют дополнительные возможности. При изучении любого ново-
     го языка, если вам нужно изучить его быстро, определите, как в  нем
     реализованы  семь основных элементов, дальше все будет просто. Ниже
     приведено их краткое описание.
          Вывод - означает запсиь информации на экран, диск или  в  порт
     ввода-вывода.
          Типы  данных  - это константы, переменные и структуры, которые
     содержат числа /целые и с плавающей точкой/, текст /символы и стро-
     ки/, или адреса /переменных и структур/.
          Операторы  -  присваивают  одно  значение другому, комбинируют
     значения /сложение, деление и т.д./, и сравнивают значения  /равно,
     не равно и т.д./.
          Ввод - означает чтение данных с клавиатуры, диска или их порта
     ввода-вывода.
          Условное выполнение - выполнение определенного набора инструк-
     ций,  если  указанное  условие истонно, или пропуск данного набора,
     если условие ложно.
          Циклы - выполнение набора инструкций  определенное  число  раз
     или пока некоторое условие истинно.
          Процедуры  - отдельно именуемые наборы инструкций, которые мо-
     гут выполняться в любом месте программы, вызываются по имени.
          Теперь мы поговорим, как использовать эти элементы в Турбо-Си.
                                  Вывод
          Может показаться странным, что первым оказался вывод, но прог-
     рамма,  которая  ничего не выводит, не представляет из себя большой
     ценности. Вывод обычно принимает вид информации, распечатываемой на
     экране  /слова  и картинки/. записываемой на диск /гибкий или жест-
     кий/ или же подаваемый в порт ввода-вывода /последовательный  порт,
     порт печатающего устройства/.
                             Функция printf
          Вам  уже приходилось использовать наиболее часто встречающуюся
     в Си функцию вывода print. Она предназначена для вывода  информации
     на экран. Формат ее прост и гибок:
          printf(<форматная строка>,<аргумент>,<аргумент>,...);
 
                            Форматная строка
          Форматная строка - это строка, которая начинается и заканчива-
     ется двойными кавычками /"вот так"/. Целью функции printf  является
     вывод  этой строки на экран. До вывода аргументы, указанные в стро-
     ке, преобразуются в соответствии со спецификаторами  формата,  ука-
     занными  в  самой строке. Например, в вашей последней программе был
     использован следующий оператор:
                     printf("The sum is %d/n",sum);
          Последовательность %d в форматной строке является спецификато-
     ром формата. Все спецификаторы формата начинаются со знака процента
     /%/, за которым обычно следует одна буква, указывающая тип данных и
     способ форматирования этих данных.
          Для  каждого  спецификатора  формата должен быть указан один и
     только один аргумент. Если аргумент принадлежит типу данных,  кото-
     рый  не  соответствует  указанному в спецификаторе формата, то Тур-
     бо-Си попытается проделать соответствующее преобразование. Аргумен-
     тами  могут  быть переменные, константы, выражения, вызовы функций,
     т.к. они могут быть чем угодно, возвращающим  значение,  подходящее
     соответствующей спецификации формата.
          Спецификатор  %d  означает,  что аргумент является целым. Ниже
     приведены наиболее часто используемые спецификаторы форматов:
          %u беззнаковое целое
          %p значение указателя
          %f с плавающей точкой
          %e с плавающей точкой в экспоненциальном формате
          %c символ
          %s строка
          %x или %X целое в шестнадцатеричном формате
          Ширина  поля  может быть может быть указана цифрой, помещенной
     между знаком % и буквой. Например, десятичное поле шириной 4 симво-
     ла  будет  указано  так: %4d. Значение будет напечатано выравненным
     вправо /с ведущими нулями/, так что общая длина поля будет равнв  4
     символам.
          Если вам нужно напечатать знак процента, вставьте %%.
          Последовательность  \n  не является спецификатором формата. По
     традиции это называется escape-последовательностью  и  представляет
     собой  символ перехода на новую строку, поэтому после печати строки
     маркер переходит в начало следующей строки.
          Полный список управляющих символов приведен в главе 8,  наибо-
     лее часто встречаются следующие:
          \f - перевод формата или очистка экрана
          \t - табуляция
          \b - забой
          \xhhh  -  вставить  символ  с шестнадцатеричным кодом hhh, где
     hhh - от 1 до 3 шестнадцатеричных цифр.
          Если нужно напечатать обратную косую черту -  напечатайте  две
     косых  черты  \\.  Более  подробно  работа функции printf описана в
     "Справочном руководстве Турбо-Си".
                  Другие функции вывода puts и putchar
          Для вывода на экран есть еще две функции: puts и putchar. Фун-
     кция puts выводит на экран строку, оканчивающуюся символом перехода
     на новую строку. Например, файл HELLO.C можно отредактировать  сле-
     дующим образом
 
          Обратите  внимание,  что символ \n в конце строки отсутствует,
     т.к. он добавляется самой функцией puts.
          Вторая функция, putchar, выводит на экран один символ и не до-
     бавляет \n. Оператор putchar(ch) эквивалентен printf("%c",ch).
          В  чем  смысл  использования puts и/или putchar взамен функции
     printf? Одной из причин является достаточно большой размер процеду-
     ры printf. Если только она вам действительно не нужна для цифрового
     вывода или специального форматирования, лучше воспользоваться функ-
     циями  puts и putchar, что сделает вашу программу меньше и быстрее.
     Например, файл .ЕХЕ, созданный на основе файла HELLO.C,  использую-
     щего  функцию  puts  намного меньше того же файла, но использующего
     функцию printf.
                               Типы данных
          При написании программы необходимо работать с различной инфор-
     мацией. Вся информация может быть приведена к одному из четырех ос-
     новных типов: целые числа, числа с плавающей точкой, текст,  указа-
     тели.
          Целые числа - это числа, используемые для счета /1,5,-21,752/.
          Числа с плавающей точкой имеют дробную часть /3.14159/ или эк-
     споненту /2.579х10 24/. Их еще называют действительными числами.
          Текст состоит из символов /а, Н, !, 3/ и строк /"This is  only
     atest"/.
          Указатели  не  содержат  информации,  указатель содержит адрес
     ячейки памяти, в которой находится информация.
                                Тип float
           Си поддерживает все 4 основных типа данных в различных видах.
     Два  из  них  вы  уже  использовали  - это целый /int/ и символьный
     /char/. Теперь отредактируем последнюю программу и применим  в  ней
     еще  один тип - с плавающей точкой /float/. Войдите в редактор Тур-
     бо-Си и придайте вашей программе следующий вид:
                                                                       
          Запишите эту программу на диск под именем RATIO.C  при  помощи
     команды  File/Write to. Затем нажмите R и программа начнет компили-
     роваться и выполняться. Введите два числа /например 10 и 3/ и обра-
     тите внимание на результат - в данном случае 3.000000.
          Вы,  возможно,  ожидали иного результата /3.333333/, почему же
     это не так? Потому что переменные а и b - целые, типа int, этим оп-
     ределяется  и  тип  результата от деления a/b - тоже int. Результат
     был преобразован в тип float после того, как его присвоили перемен-
     ной ratio, но это преобразование произошло не до деления, а после.
          Отредактируйте  программу,  определив  переменные  а  и  b как
     float, измените также и форматную строку "%d  %d",  которая  должна
     выглядеть  так: "%f %f". Запишите программу на диск /нажав F2/, за-
     тем оттранслируйте и выполните ее. Результат будет таким, какого вы
     ожидали - 3.333333.
          Имеется одна разновидность типа float, называемая double. Этот
     тип предназначен для хранения переменных,  занимающих  в  два  раза
     больше  места,  чем  тип float. У переменных типа double может быть
     больше значащих цифр и больший диапазон экспонент. Конкретные  зна-
     чения указаны в главе 8.
 
                            Три вида типа int
          Кроме собственно целого типа int Си поддерживает еще short int
     и long int, сокращаемые, обычно, как short и long. Конкретный  раз-
     мер этих типов зависит от реализации транслятора, единственно можно
     быть уверенным в том, что переменная типа  short  не  будет  больше
     /т.е.  не  будет занимать больше байт/, чем переменная типа long. В
     Турбо-Си эти типы занимают 16 бит /short/, 16 бит /int/ и  32  бита
     /long/.
                            Беззнаковые типы
          В языке Си имеется возможность объявлять некоторые типы /char,
     short, int, long/ беззнаковыми при  помощи  модификатора  unsigned.
     Это значит, что такие типы не содержат отрицательных значений, т.е.
     весь их диапазон принимает значения большие или равные нулю.
          Таким образом, переменные беззнаковые могут содержать  большие
     значения, чем переменные знаковых типов. Например, в Турбо-Си пере-
     менная типа int может принимать значения от -32768 до 32767, а  пе-
     ременная  типа unsigned int может принимать значения от 0 до 65535.
     Обе переменные имеют один и тот же размер /в данном случае 16 бит/,
     но они по-разному используют эти 16 бит. Боле подробно об ътом рас-
     сказано в главе 8.
                           Определение строки
          Язык Си не поддерживает отдельный строковый тип данных, но  он
     позволяет определять строки двумя несколько различными способами. В
     первом из них используется массив символов, во втором -  ссылка  на
     символ.
                     Использование массива символов
          Загрузите  при помощи команды Load меню работы с файлами отре-
     дактированную версию программы HELLO.C. Теперь измените ее  следую-
     щим образом:
          
          Число  30 в квадратных скобках после идентификатора msg указы-
     вает компилятору на необходимость зарезервировать место для  макси-
     мум  29  символов,  т.е.  организовать массив из 29 переменных типа
     char /30-м символом будет нулевой символ \0, который в данном руко-
     водстве будет еще называться нулевым оканчивающимся символом/. Сама
     переменная msg не содержит символьного значения,  в  ней  находится
     адрес ячейки памяти, в которой хранится первая из 29 переменных ти-
     па char.
          Когда компилятор находит оператор типа:
                       strepy(msg,"Hello, World");
          он делает следующее:
          - Во-первых, он  создает  в  объектном  файле  строку  "Hello,
     world", за которой следует нулевой символ \0 /код ASCII 0/;
          -   Во-вторых,  компилятор  вызывает  процедуру,  называющуюся
     strepy, которая копирует по одному символы в ячейку памяти, на  ко-
     торую  указывает переменная msg, до тех пор, пока не будет скопиро-
     ван нулевой символ, оканчивающий строку.
          Когда выполняется оператор puts(msg), значение,  хранящееся  в
     переменной  msg  /адрес  первого символа, на который она указывает/
     передается функции puts. Функция puts  проверяет,  не  является  ли
     этот символ нулевым. Если этот символ нулевой, тогда работа функции
     puts заканчивается, если нет - тогда  функция  печатает  символ  на
     терминале, прибавляет к адресу единицу и снова начинает проверку на
     нулевой символ.
 
          Из-за зависимости от нулевого символа строки в языке Си  назы-
     ваются "заканчивающимися нулем", т.е. они представляют из себя пос-
     ледовательность символов, за которой следует нулевой символ.  Такая
     трактовка строк позволяет снять ограничения на длину строки: строка
     может быть любой длины, до тех пор, пока есть место в памяти, в ко-
     торое ее можно поместить.
                     Использование ссылки на символ
          Вторым способом определения строки является использование ука-
     зателя или ссылки на символ. Отредактируйте вашу программу  следую-
     щим образом:
          
          Звездочка перед идентификатором msg говорит компилятору о том,
     что msg является ссылкой на символ; другими словами,  в  переменную
     msg  может  быть записан адрес некоторого символа. Однако, в данном
     случае компилятор не резервирует место для хранения символов  и  не
     инициализирует переменную msg конкретным образом.
          Когда компилятор встречает следующий оператор:
                        msg = "Hello, world\n";
          он производит следующие действия:
          -  Во-первых,  как и в предыдущем случае, компилятор создает в
     каком-либо месте объектного файла строку "Hello, world\n", за кото-
     рой следует нулевой символ;
          -  Во-вторых,  он  присваивает значение начального адреса этой
     строки - адрес символа Н - переменной msg.
          Функция puts(msg) работает так же, как и в предыдущем  случае,
     печатая символы до тех пор, пока ей не встретится нулевой символ.
          Между  этими двумя метолдами определения строк - с использова-
     нием ссылок и с использованием массивов - есть некоторые  различия,
     о которых будет сказано в следующей главе.
                             Идентификаторы
          До  настоящего момента мы раздавали переменным имена направо и
     налево, не заботясь о возможных для них  ограничениях.  Ограничения
     могут быть следущие.
          Имена,  которые  присваиваются константам, типам данных, пере-
     менным и функциям  известны  как  идентификаторы.  Приведем  пример
     идентификаторов, которые мы использовали до настоящего момента:
          char, int, float    предопределенные типы данных
          main                основная функция программы
          name, a, b, sum     переменные, определенные пользователем
          scarf, print, puts  библиотечные функции
          Идентификаторы,  используемые в Турбо-Си, должны удовлетворять
     следующим правилам:
          - Все идентификаторы должны начинаться с  буквы  /а  ...z  или
     A...Z/ или с подчеркивания /_/;
          -  В  идентификаторе могут использоваться буквы, подчеркивания
     и/или цифры /0...9/. Использование остальных символов в идентифика-
     торах не разрешено;
          -  Идентификаторы  зависят  от регистра. Это значит, что буквы
     нижнего регистра  /a...z/  отличаются  от  букв  верхнего  регистра
     /A...Z/.  Например,  следующие три идентификатора: indx, Indx, INDX
     различны;
          - Идентификаторы различаются по первым 32 символам.
 
                                Операции
          Когда вы ввели в программу какие-либо данные и  присвоили  ка-
     кие-либо  значения своим переменным, наступает время манипулировать
     этими данными, используя имеющиеся в языке Си многочисленные опера-
     торы.
                          Операция присваивания
          Присваивание,   как   например   в   выражении  ratio=a/b  или
     ch=getch(), является одной из основных операций. В языке Си присва-
     ивание  обозначается  одним знаком равенства /=/; значение с правой
     стороны присваивается переменой с левой стороны.
          Присвоения можно связывать таким  образом:  sum=a=b.  В  таком
     случае вычисление производится справа налево, т.е. значение b будет
     присвоено переменной а будет затем присвоено  переменной  sum,  при
     этом все три переменные получат одно и то же значение /первоначаль-
     ное значение переменой b/.
                       Унарные и бинарные операции
          Язык Си поддерживает стандартный набор бинарных арифметических
     операций:
          - умножение /*/
          - деление (/)
          - взятие остатка (%)
          - сложение (+)
          - вычитание (-)
          Турбо-Си поддерживает операцию унарного минуса (a+(-b)), кото-
     рая выполняет дополнение до двух, а также, в качестве расширения по
     стандарту ANSI, операцию унарного плюса: (a+(+b)).
               Операторы инкремента /++/ и декремента /--/
          В языке Си имеются также некоторые специфические унарные и би-
     нарные операторы. Наиболее широко известны из них операторы  инкре-
     мента  /++/  и  декремента /--/. При помощи одного такого оператора
     можно добавить единицу к любому значению или вычесть из любого зна-
     чения единицу. Сложение или вычитание могут производиться в середи-
     не выражения, кроме того, можно опеределить, будут  ли  они  выпол-
     няться до или после вычисления всего выражения. Рассмотрим две сле-
     дующие строки программы:
                             sum = a + b ++;
                              sum = a + ++b;
          Первая строка производит следующие действия: складываются зна-
     чения переменных а и b, результат вычисления присваивается перемен-
     ной sum, затем переменная b увеличивается на единицу.
          Вторая строка делает следующее: значение  b  увеличивается  на
     единицу, а складывается с b, результат сложения присваивается пере-
     менной sum.
          Эти операторы значительно расширяют возможности языка, но  пе-
     ред  их использованием необходимо убедиться, что вы полностью пони-
     маете их действие. Отредактируйте программу SUM.C так, как показано
     в  нижеследующем  примере, а затем попытайтесь угадать результат ее
     работы дотого, как вы ее запустите.
 
                           Побитовые операторы
          В языке Си имеются следующие операторы для работы  на  битовом
     уровне:
          - сдвиг влево (<<)
          - сдвиг вправо (>>)
          - И (&)
          - ИЛИ (I)
          - исключающее ИЛИ (^)
          - НЕ (~)
          Эти  операторы позволяют выполнять действия низкого уровня над
     различными значениями. Результаты их выполнения показаны на примере
     следующей программы, которую следует набрать и запустить.
          
          Постарайтесь определить результаты, которые должна вывести эта
     программа, прежде чем вы ее запустите. Обратите внимание на исполь-
     зование  спецификаторов  размера  поля  для  выравнивания выводимой
     информации : спецификатор %04X говорит о том, что мы хотим распеча-
     тать ведущие нули, что поле печати имеет ширину 4 разряда и выводи-
     мый результат распечатывается в шестнадцатеричном  виде  /основание
     16/.
                           Составные операторы
          Язык Си позволяет использовать сокращенную запись выражений со
     многими операторами. Все описанные выше операторы /унарные,  бинар-
     ные,  инкремента и декремента/ могут быть скомбинированы с операто-
     ром присваивания. Практически любое выражение вида:
          <переменная>=<переменная><оператор><выражение>;
          может быть заменено на следующее:
          <переменная><оператор>=<выражение>;
          Приведем несколько примеров подобного сокращения выражений:
          
          1-приводится к виду.
                           Адресные операторы
          Язык Си поддерживает два адресных оператора:  оператор  взятия
     адреса & и косвенный оператор *.
          Оператор & возвращает адрес переменной: если sum есть перемен-
     ная типа int, тогда &sum есть адрес /ячейка памяти/  этой  перемен-
     ной.  Таким  образом, если msg есть ссылка на переменную типа char,
     тогда *msg есть символ, на который указывает msg. Напечатайте  сле-
     дующую программу и изучите полученные результаты:
          
          Первая строка выводит два значения: значение переменой sum /8/
     и адрес этой переменной, присвоенный ей компилятором. Вторая строка
     также  выводит  два значения: символ, на который указывает msg/H/ и
     значение переменной, которое является адресом этого  символа  /этот
     адрес также присвоен компилятором/.
                                  ВВод
          В  языке Си имеется несколько функций, обеспечивающих ввод ин-
     формации, некоторые из них принимают входную информацию  из  файла,
     или  выходного  потока,  другие  - с клавиатуры. Подробное описание
     этих  функций  приведено  в  Справочном  руководстве  /см.  функции
     ...scanf и read/, а также в главе 8.
 
                              Функция scanf
          Основное назначение этой функции - интерактивный ввод информа-
     ции. Вид функции scanf эквивалентен виду функции printf:
             scanf (<форматная строка>,<адрес>,<адрес>,...)
          Функция scanf использует многие из тех спецификаторов  формата
     со знаком %, что и функция printf: %d для целых чисел, %f для чисел
     с плавающей точкой, %s для строк и т.д.
          Однако, у этой функции есть  важная  отличительная  черта:  за
     форматной  строкой следуют не значения, а адреса. В программе SUM.C
     имеется следующая строка:
                          scanf("%d%d",&a,&b);
          Эта строка означает, что программа ожидает ввода двух десятич-
     ных  целых  значений,  разделенных  пробелом; первое значение будет
     присвоено переменной а, второе - переменной b. Обратите внимание на
     то,  что для передачи значений применяется адресный оператор &, при
     помощи которого функции scanf передаются адреса переенных а и b.
                         Распространенный пробел
          Пробел  между двумя спецификаторами формата %d представляет на
     самом деле больше, чем просто пробел. На его месте может быть любое
     количество свободного пространства, а именно: любое количество про-
     белов, табуляций и символов новой строки в любых комбинациях. Обыч-
     но, в большинстве случаев такой распространенный пробел игнорирует-
     ся программами и компиляторами языка Си.
          Но что делать,  например, если вместо пробела вы хотите разде-
     лять свои переменные запятой? Для этого отредактируйте  эту  строку
     так:
                          scanf("%d,%d",&a,&b);
          Такая  строка позволит передавать в программу значения, разде-
     ляя их запятой.
                     Передача адреса в функцию scanf
          Что делать, если вы хотите ввести в программу строку?  Напеча-
     тайте и запустите следующую программу:
          
          Т.к. name - это массив символов, значение переменной name есть
     адрес самого массива. По этой причине перед именем name не  исполь-
     зуется адресный оператор &, и строка ввода выглядит следующим обра-
     зом: scanf("%s",name).
          Обратите внимание, что мы использовали массив  символов  /char
     name  [30];/,  а  не указатель на символ /char *name;/. Объяснением
     этому служит тот факт, что объявление массива на самом деле  резер-
     вирует  память  для хранения его элементов, а при объявлении ссылки
     этого не происходит. Если бы мы использовали объявление char *name,
     тогда нам бы пришлось явным образом резервировать память для хране-
     ния переменной *name.
              Использование для ввода функций gets и getch
          Использование  для  ввода  информации функции scanf приводит к
     появлению  следующей  проблемы. Запустите еще раз эту же программу,
     но введите в нее имя и фамилию. В своем  ответе  программа  покажет
     вам снова одно только имя. Почему? Потому что функция scanf воспри-
     няла пробел, введенный вами после имени, как конец вводимой строки.
     Для  решения  этой  проблемы можно воспользоваться двумя способами.
     Ведите следующую программу:
 
          
          В этом примере подразумевается, что вы должны напечатать фами-
     лию,  имя и отчество; функция scanf будет ждатьвведения трех строк.
     Но что делать, если необходимо ввести, скажем, имя, фамилию  и  от-
     чество как одну строку, включая пробелы? Решение может быть вот та-
     ким:
          
          Функция gets воспринимает любую информацию до тех пор, пока вы
     не  нажмете  клавишу  Enter.  Код,  соответствующий этой клавише, в
     строку не вводится, но в конце строки  добавляется  нулевой  символ
     \0.
          И  последняя функция - это getch. Эта функция считывает с кла-
     виатуры один символ, не отображая его на экране /в отличие от функ-
     ции  scanf и gets/. Эта функция не передает символ в качестве пара-
     метра; она сама имеет тип char, и ее значение может быть непосредс-
     твенно присвоено переменной типа char.
                           Условные операторы
          До  сих  пор мы ничего не говорили об операторах отношения и о
     логических операторах. Кроме того, имеются некоторые непростые  мо-
     менты,  обсуждение которых мы отложили до описания условных выраже-
     ний, которые могут принимать значение true или false,  т.е.  истина
     или ложь.
                           Операторы отношения
          Операторы отношения позволяют сравнивать два значения, резуль-
     тат операции зависит от того, истинно  или  ложно  сравнение.  Если
     сравнение ложно, значение результата равно нулю, если истинно, зна-
     чение равно единице. Список операторов отношения языка Си:
                            >      больше чем
                            >=     больше или равно
                            <      меньше чем
                            <=     меньше или равно
                            =      равно
                            !=     не равно
          Зачем необходимо знать, истинна какая-либо величина или ложна?
     Запустите программу RATIO.C и посмотрите, что получится, если в ка-
     честве второго значения вы введете ноль. Программа напечатает сооб-
     щение об ошибке Divide by zero /Деление на ноль/ и остановится. Те-
     перь проделайте в ней следующие  изменения и запустите ее снова:
          
          Оператор, находящийся на двух  следующих  за  вызовом  функции
     scanf строках называется условным оператором if. Он читается следу-
     ющим образом: "Если значение выражения b==0.0  истинно,  немедленно
     вызвать  функцию printf. Если значение этого выражения ложно, прис-
     воить переменой ratio значение выражения а/b, за тем вызвать  функ-
     цию printf."
          Если  вы  напечатаете ноль в качестве второго значения, вводи-
     мого в программу, она напечатает сообщение: The ratio is  undefined
     /отношение  неопределено/,  дождется, пока вы не нажмете какую-либо
     клавишу и вернется в Турбо-Си. Если же второе значение не равно ну-
     лю,  программа печатает частное от деления двух чисел, ждет нажатия
     клавиши и возвращается в Турбо-Си - и все при помощи условного опе-
     ратора if.
 
                          Логические операторы
          Имеется  три  логических оператора: И /&&/, ИЛИ /\\/ и НЕ /!/.
     Их необходимо  отличать  от  описанных  выше  побитовых  операторов
     /&,I,~/.  Логические  операторы  работают  с логическими значениями
     /true и false/, позволяя составлять выражения отношения.
          Чем они отличаются от соответствующих побитовых операторов?
          - Логические операторы дают результат или  равный  1  /истина/
     или  0 /ложь/, тогда как побитовые операторы производят соответсвт-
     вующие действия над каждым битом;
          - Логические операторы && и ||  являются  "короткозамкнутыми".
     Предположим, имеется выражение: expI&& exp2. Если exp1 ложно, тогда
     ехр2 вычисляться не будет. Точно также имея выражение ехр1 || exp2,
     мы не вычислим exp2, если exp1 истинно.
                  Дополнительные сведения о выражениях
          Прежде  чем  мы перейдем к циклам, скажем еще несколько слов о
     выражениях. Выражения типа (а == 0.0) и (а <= c*p) достаточно проз-
     рачны. Однако, язык Си позволяет писать куда более загадочные вещи.
     Мы не будем изощряться в загадочности, но приведем, все же, некото-
     рые примеры.
                          Оператор присваивания
          Любой  оператор присваивания, заключенный в скобки, есть выра-
     жение, имеющее значение, равное присваиваемому.
          Например, выражение (sum=5+3) имеет значение 8, поэтому  выра-
     жение  ((sum=5+3)  <=10)  всегда  будет  давать значение true, т.к.
     8<=10. Следующий пример более экзотичен:
          
          Вы догадались, что здесь происходит? Когда программа встречает
     выражение  ((ch=getch()) == 'g`), она останавливается, ждет пока вы
     не нажмете любую клавишу, присваивает символ, соответствующий  этой
     клавише,  переменной  ch и затем сравнивает этот символ с буквой g.
     Если они совпадают, тогда на экране появляется сообщение "Quitting,
     huh?"  /Выходим,  а?/, в противном случае распечатывается сообщение
     "Good move ..." /Попробуем еще .../.
                           Оператор "запятая"
          Оператор "запятая" может использоваться для помещения сложного
     выражения  в круглые скобки. Выражения будут вычисляться слева нап-
     раво, все выражение примет значение последнего вычисленного выраже-
     ния.  Например,  если  имеются  две переменные oldch и ch, обе типа
     char, тогда выражение
                         (oldch=ch, ch=gatch())
     производит следующие действия: значение переменной ch присваивается
     переменной oldch, затем принимается символ с клавиатуры, и он прис-
     ваивается переменной ch, затем все выражение принимает значение пе-
     ременной ch. Например:
          
                               Оператор if
         Обратите  внимание  на оператор if в предыдущем примере. Опера-
     тор If имеет следующий формат:
          if(значение)
              выражение1;
          else
              выражение2;
     где значением может быть любое выражение, которое  принимает  целое
     значение  или  может быть преобразовано к целому значению. Если это
     значение не равно нулю /т.е. истинно/, тогда выполняется выражение1,
     в противном случае выполняется  выражение2.
 
          Два замечания по-поводу оператора if-else.
          Во-первых,  вторая  часть оператора /else выражение2/ является
     необязательной; ниже приведен пример такого оператора if:
          if (значение)
              выражение1;
     В данном случае выражение1 выполняется тогда и только тогда,  когда
     значение  не равно нулю. Если значение равно нулю, тогда выражение1
     пропускается и программа продолжает свое выполнение.
          Во-вторых, иногда, если конкретное выражение истинно или  лож-
     но, бывает нужно выполнить не одно действие, а несколько. Для этого
     используется составной оператор. Составной оператор состоит из  ле-
     вой фигурной скобки /{/, несколько выражений, каждое из которых за-
     канчивается точкой с запятой /;/ и правой фигурной скобки /}/.
          В программе RATIO в первой половине оператора if  используется
     одиночное выражение:
          
     а во-второй части else используется составной оператор:
          
          Вы  могли  также  заметить,  что тело вашей программы /функция
     main/ представляет из себя составной оператор.
                                  Циклы
          Кроме выражений, которые необходимо выполнять в соответствии с
     каким-либо условием, т.е. условных выражений, существуют выражения,
     которые необходимо выполнять определенное число раз.  Такие  конст-
     рукции называются циклами.
          Имеется  три  вида  циклов  /на самом деле два из них являются
     всего лишь разновидностями первого/, а именно: цикл while, цикл for
     и цикл do...while. Рассмотрим их по порядку.
          
          


Яндекс цитирования