- •А. Нейбауэр.
- •Глава 1. Основы программирования 11
- •Глава 3. Переменные и константы 39
- •Глава 6. Операторы 103
- •Глава 13. Как собрать все вместе 253
- •Благодарности
- •Введение
- •Что вам даст эта книга
- •Программные средства
- •Глава 1. Основы программирования
- •Компьютерная программа
- •Языки программирования
- •Компиляторы
- •Интерпретатор
- •Скорость
- •Переносимость
- •Структурирование
- •Библиотеки функций
- •Необходимые пояснения
- •Что такое объектно-ориентированное программирование
- •Что Си может и чего не может
- •Этапы программирования
- •План программы
- •Текст программы
- •Компиляция программы
- •Компоновка программы
- •Тестирование программы
- •Изучение основ программирования
- •Что нужно, чтобы писать программы
- •Структура программы
- •Прописные и строчные символы
- •Инструкция return
- •Использование комментариев
- •Понятие параметров
- •Директива #include
- •Проектирование программы
- •Глава 3. Переменные и константы
- •Символьные данные
- •Целочисленные величины
- •Вещественные числа
- •Почему надо использовать целые числа?
- •Константы и переменные
- •Имена констант и переменных
- •Определение констант
- •Почему используют константы?
- •Определение переменных
- •Присваивание значения
- •Определение строковой переменной
- •Типы данных и функции
- •Литералы
- •Проектирование программы
- •Функция puts()
- •Функция putchar()
- •Двойственность символьных переменных
- •Управляющие коды
- •Код «новая строка»
- •Код «табуляция»
- •Код «возврат каретки»
- •Код «возврат на шаг»
- •Код «перевод страницы»
- •Отображение специальных символов на экране монитора
- •Многогранная функция printf()
- •Вывод чисел
- •Перевод строки
- •Преобразование типов данных
- •Форматированный вывод
- •Выбор правильных средств вывода информации
- •Проектирование программы
- •Функция gets()
- •Функция getchar()
- •«Для продолжения нажмите Enter»
- •Оператор получения адреса &
- •Функция scanf()
- •Входной поток
- •Использование функции scanf()
- •Выбор соответствующих средств ввода данных
- •Будьте осторожны при использовании scanf()
- •Неинициализированные переменные
- •Используемые алгоритмы ввода
- •Глава 6. Операторы
- •Арифметические операторы
- •Деление нацело
- •Типыданныхи операторы
- •Выражения
- •Приоритет операторов и порядок вычислений
- •Используемые алгоритмы обработки данных
- •Счетчики
- •Операторы инкремента
- •Аккумуляторы
- •Операторы присваивания
- •Присваивание начального значения
- •Проектирование программы
- •Остерегайтесь логических ошибок
- •Ищите образцы
- •Диагностические проблемы
- •Глава 7. Для чего нужны функции
- •Как использовать функции
- •Переменные в функциях
- •Автоматические (локальные) переменные
- •Внешние (глобальные) переменные
- •Статические переменные
- •Передача параметров
- •Возвращаемые значения
- •Возврат значений типа float
- •Использование return() в функции main()
- •Использование макроопределений
- •Проектирование программы
- •Автоматические или внешние переменные?
- •Неправильный ввод
- •Глава 8. Позвольте компьютеру принимать решения
- •Условия
- •Составные инструкции
- •Конструкция if...Else
- •Дополненный Опросник
- •Логические операторы
- •Вложенные инструкции if
- •Конструкция switch/case/default
- •Проверка чисел с плавающей точкой и строк
- •Проектирование программы
- •Проверка правильности ввода
- •Глава 9. Циклы
- •Использование цикла for
- •Создание паузы в программе
- •Составные инструкции
- •Использование переменных
- •Вложенные циклы
- •Использование цикла do...While
- •Вложенные циклы do
- •Использование цикла while
- •Комбинирование циклов разных типов
- •Проектирование программы
- •Использование флагов
- •Использование инструкции break
- •Глава 10. Массивы и строки
- •Массивы
- •Определение массива
- •Ввод значений в массив
- •Работа с массивами
- •Просмотр массива
- •Поиск в массиве
- •Передача массива функции
- •Использование массивов
- •Сравнение двух строк
- •Определение длины строки
- •Присваивание строк
- •Слияние строк
- •Массивы строк
- •Проектирование программы
- •Глава 11. Структуры и указатели
- •Использование структур
- •Определение структуры
- •Определение структурных переменных
- •Присвоение начального значения
- •Использование структуры
- •Массивы структур
- •Структуры и функции
- •Указатели
- •Указатели и функции
- •Глава 12. Вывод на диск и принтер
- •Что такое файловая структура
- •Указатель на файл
- •Как открыть файл
- •Как избежать ошибок выполнения
- •Как закрыть файл
- •Функции ввода и вывода
- •Работа с символами
- •Посимвольное чтение из файла
- •Работа со строками
- •Чтение строк
- •Форматированный ввод и вывод
- •Чтение форматированных файлов
- •Работа со структурами
- •Чтение структур
- •Чтение в массив
- •Дополнение файла новыми данными
- •Текстовый и двоичный форматы
- •Двоичный формат
- •Печать данных
- •Проектирование программы
- •Глава 13. Как собрать все вместе
- •Прикладная программа
- •Глобальные определения
- •Функция main()
- •Добавление записей: функция addcd()
- •Удаление записи: функция delcd()
- •Редактирование данных: функция chcd()
- •Изменение номера ячейки: функция chloc()
- •Вывод записи на экран: функция locate()
- •Печать записей: функция plist()
- •Сортировка записей: функция sort()
- •Приложение I Ответы и решения Глава 1. Основы программирования.
- •Глава 3. Переменные и константы.
- •Глава 6. Операторы.
- •Глава 7. Для чего нужны функции.
- •Глава 8. Позвольте компьютеру принимать решения.
- •Глава 9. Циклы.
- •Глава 10. Массивы и строки.
- •Глава 11. Струтуры и указатели.
- •Глава 12. Вывод на диск и принтер.
- •Приложение II Прикладная программа
Языки программирования
Третье требование к программе — это язык, который понятен компьютеру.
Глубоко в недрах компьютера находится микропроцессор. Микропроцессор — это интегральная микросхема, которая управляет всем, что происходит в компьютере (рис.1.1).
Когда программа командует компьютеру отобразить сообщение на экране или напечатать его на принтере, микропроцессор посылает соответствующие электрические сигналы, которые говорят компьютеру, в какой области памяти можно отыскать нужное сообщение и куда его следует отправить. По большей части работа микропроцессора остается недоступной для наблюдателя, он загружает программу и полагает, что микропроцессор знает свое дело. Однако чтобы понять, как работает программа, необходимо иметь хотя бы самое элементарное представление о том, как действует микропроцессор.
Физически микропроцессор выполняет всего четыре действия. Он может перемещать данные из одной области памяти в другую, изменять данные в конкретной области, проверять, содержит ли конкретная область памяти определенные данные, и изменять последовательность выполнения инструкций. Все эти действия выполняются путем посылки, приема и отслеживания состояния электрических сигналов.
Электрические сигналы, с которыми имеет дело компьютер, могут иметь только два состояния (в зависимости от уровня напряжения): высокий уровень напряжения — электрический сигнал есть (состояние «включен») либо низкий уровень — электрический сигнал отсутствует (состояние «выключен»). Для того чтобы выполнить любую задачу, мы задаем микропроцессору последовательность сигналов в состоянии «включен» или «выключен». На рис.1.2 для примера приведена последовательность состояний электрических сигналов, необходимая для того, чтобы напечатать символ «А»*.
Для того чтобы задавать инструкции компьютеру на самом низком уровне, используется цифра 0, означающая состояние «выключен», и цифра 1, означающая состояние «включен». Мы называем это двоичными цифрами (битами)** или двоичными кодами, так как они основаны на двоичной системе счисления, в которой, как известно, все числа представлены только при помощи комбинаций нулей и единиц.
На заре компьютерных технологий программа выполнялась путем непосредственной манипуляции сигналами «включен», «выключен». Микропроцессоров тогда не существовало, и техник должен был вручную переводить ряды выключателей из одного состояния в другое, действуя, таким образом, как контроллер. Выполнение какой-нибудь задачи требовало правильной установки тысяч отдельных сигналов и, естественно, создание программы отнимало огромное количество времени и сил.
________________________________
* Здесь и далее на рисунках приведены не конкретные последовательности машинных команд, а лишь дано общее представление о них. (Прим.ред.)
** От английского binary digit, bit. (Прим.перев.)
Рис. 1.2. Ряд последовательных сигналов «включен» или «выключен»говорит микропроцессору, что ему делать, в данном случае —взять символ из памяти и послать на принтер
Рис. 1.3. Транслятор с языка ассемблера преобразует инструкциив двоичные коды
По мере развития электронной техники появилась возможность загружать программу в компьютер сразу, а затем заставлять его выполнять содержащиеся в программе инструкции. Такой способ программирования все еще требовал длительной процедуры задания последовательностей тысяч отдельных цифр 0 и 1, и так продолжалось до тех пор, пока не был разработан язык программирования ассемблер.
Ассемблер представляет задачу, адресованную непосредственно микропроцессору, используя мнемонические коды. Мнемонические коды — это несложные для запоминания слова или аббревиатуры, представляющие завершенное задание для микропроцессора. Например, код MOV указывает компьютеру на то, что некую информацию следует переместить из одной области памяти в другую, а код JMP указывает, что необходимо перейти в другую область памяти. Таким образом, вместо того, чтобы составлять последовательные ряды 0 и 1, программист на ассемблере может использовать мнемонические коды, подобные приведенным выше, каждый из которых представляет собой восемь или более бит.
Как показано на рис. 1.3, транслятор с ассемблера переводит эти коды в информацию о состояниях отдельных электрических сигналов, понятную компьютеру. Так как каждый мнемонический код соотносится непосредственно с внутренними функциями микропроцессора, программа, написанная на ассемблере, выполняется предельно быстро, но само программирование на этом языке отнимает достаточно много времени и требует написания исходных программ большого объема.
В настоящее время большинство программистов работают с языками высокого уровня, где инструкции задают с помощью человеческих слов, а не мнемонических кодов или 0 и 1. Каждое слово представляет практически завершенную операцию, а не одно задание для микропроцессора. Например, функция языка Си puts()* указывает компьютеру, что некая информация должна быть выведена на дисплей. Для выполнения этой же функции может потребоваться использование большого количества мнемонических кодов ассемблера и сотен бит.
Рис. 1.4. Сравнение языка Си, ассемблера и двоичных кодов
Рис. 1.4 демонстрирует простую инструкцию, используемую языком Си и Си++ для вывода какого-нибудь слова на экран, и примерные эквиваленты той же инструкции, написанные на ассемблере и в двоичных кодах. Вы можете сами решить, какой язык программирования кажется более легким для чтения и создания текстов программ.
Разумеется, сам по себе компьютер не понимает, что означает функция puts() и другие инструкции языков высокого уровня, поэтому, прежде чем компьютер реально сможет выполнить задание, оно должно быть переведено на его собственный язык — язык двоичных кодов.
______________________________
* От английского put string. (Прим.перев.)
Операцию по переводу человеческих слов в двоичные коды можно выполнить двумя способами, которые называют компиляцией и интерпретацией.