Содержание данной главы
Модуль 8. Язык программирования Си
8.1. История создания языка.
Первая версия языка Си была разработана в 1972 году сотрудником фирмы Bell Laboratories Денисом Ритчи. В это время он и Кен Томбсон занимались разработкой ОС UNIX. В основу языка был положен язык B. Целью создания было: создание инструмента для программистов-практиков. На основе языка Си в дальнейшем были разработаны Си+, Си++ и Java. В 2000 году международной организацией по стандартизации (ISO) и американским институтом национальных стандартов (ANSI) был принят стандарт под именем Си99.
Языку Си присуща высокая степень переносимости. Это означает, что программы, написанные на Си для одной ОС, могут быть легко адаптированы для другой ОС. В настоящее время Си компилируется примерно для 40 ОС.
Чтобы подчеркнуть достоинства языка Си можно сказать, что многие компиляторы и интерпретаторы других языков программирования (Фортран, APL, Pascal, LISP, Basic) написаны на языке Си.
Программы, написанные на языке Си применяются для решения физических и инженерных задач, а также для создания анимационных спецэффектов в кинофильмах. Например, с этой целью Си применялся в фильмах "Гладиатор" и "Звездные войны".
Если сравнивать язык Си с языком Pascal, то можно сделать вывод, что Си дает большую свободу действиям программиста. С другой стороны Си позволяет совершить ошибки, которые в Pascal совершить невозможно.
8.2. Структура простой программы на языке Си.
Программа, записанная на языке Си состоит из совокупности функций, одна из которых - функция main(). () означают, что main - это функция, но не означает, что у нее нет аргументов. Описание функции состоит из заголовка и тела функции. Заголовок содержит операторы препроцессора, например, директиву #include , которая является стандартной частью всех программных компиляторов языка Си. Этот файл содержит информацию об операторах ввода/вывода.
Тело функции заключается в фигурные скобки и состоит из ряда операторов, каждый из которых заканчивается ";".
Пример:
#include
int main (void) /* простая программа */
{
int num; /* определить переменную с именем num*/
num=1; /* присвоить переменной num значение*/
printf ("Я - простой");
printf (" компьютер ");
printf ("Моим любимым числом будет %d, поскольку оно…", num);
return 0;
}
Результатом исполнения программы будет сообщение на экране:
Я - простой компьютер Моим любимым числом будет 1, поскольку оно…
8.3. Представление данных в языке Си.
В языке Си существует несколько разновидностей целочисленных данных. Они различаются диапазоном возможных значений и тем, что могут ли использоваться отрицательные числа. Основным типом целочисленных данных является тип int. К этому типу относятся целые числа со знаком. Диапазон возможных значений зависит от компьютерной системы для хранения данного типа int. Обычно используется одно машинное слово. При объявлении целочисленной переменной указывается ключевое слово, определяющее тип, затем выбранное имя переменной и ставится ";". Несколько переменных можно объявлять в одном операторе, разделяя их имена запятыми. Значение переменной может быть присвоено способом инициализации, т.е. присвоением первоначального значения при объявлении.
Пример:
int a=21;
int a=21, b= -2;
Обычно в языке Си предполагается, что целочисленное значение записано в десятичной системе счисления, однако в программировании широко используются восьмеричные и шестнадцатеричные числа. Для того, чтобы отметить в какой системе счисления записано данное, перед ним ставится префикс. Для восьмеричного числа префикс 0, для шестнадцатеричного - 0x. При использовании 8-ой и 16-ой систем следует помнить, что в них представляются числа без знака. В языке Си используются три модификации основного целочисленного типа. Для их объявления используются слова short, long и unsigned.
Данные типа short занимают меньший объем памяти и являются данными со знаком. Данные типа long занимают больший объем памяти и являются данными со знаком. Данные типа unsigned используются для представления только положительных чисел. Их диапазон смещен относительно типа int.
В языке Си при достижении максимального значения происходит сброс на минимальное значение и отсчет от него. Разновидностью целочисленных типов в языке Си являются данные символьного типа - char. Объявляется символьный тип также, как и целочисленный. Записи символьных значений заключаются в кавычки. При присвоении символьного значения можно воспользоваться кодом числа. При этом код записывается без вспомогательных знаков.
Пример:
char c="a";
char b=65;
Описанный способ применяется для обозначения непечатаемых символов. В языке Си существуют еще одни "неудобные" символы - управляющие последовательности.
Последовательности |
Действия |
\a |
предупреждение (звукокой сигнал) |
\b |
возврат на одну позицию |
\f |
перевод страницы |
\n |
перевод строки |
\r |
возврат каретки |
\t |
горизонтальная табуляция |
\v |
вертикальная табуляция |
\\ |
вывести на экран \ |
\' |
вывести на экран ' |
\" |
вывести на экран " |
\0 |
для вывода 8-го значения |
\0x |
для вывода 16-го значения |
Когда символьным переменным присваиваются управляющие последовательности, они должны быть заключены в кавычки.
Ключевые слова, начинающиеся с символа _ включены в компиляторы Си, начиная со стандарта Си99. Так, ключевым словом _bool обозначаются данные логического типа. В языке Си логические данные true принято обозначать 1, а данные false - 0. Таким образом, логические данные являются целочисленными. Т.к. в различных компьютерах используются различные форматы представления слов, то как следствие появляется различие в диапазонах целочисленных значений. Для уточнения диапазонов можно воспользоваться обозначениями 16_t или 32_t, указывающими на 16-битовое или 32-битовое представление слова. Перед словом int можно поставить букву u, указывающую на отсутствие знака в формате представления данных. Для распознания программой введенных обозначений, к ней нужно присоединить файл inttypes.h. При работе с обозначенными типами может возникнуть ситуация, когда конкретная система не поддерживает введенный тип. В связи с этим, в языке Си стандарта Си97 определяется второй набор имен, который гарантирует, что рассматриваемый тип данных будет как минимум достаточно велик, чтобы удовлетворять требованиям спецификации и, по сравнению с другими аналогичными типами, имеет наименьшие размеры. Подобные типы данных именуют данными минимальной ширины. Например, int_least8_t означает наименьший доступный тип данных, хранящий 8-битовое целочисленное значение со знаком. При этом тип может быть реализован как 16-битовое значение.
В некоторых программах необходимо обеспечить максимально-возможную скорость исполнения. Для этой цели в стандарте Си99 имеются типы, называемые быстрейшими типами данных минимальной ширины. Для таких типов используется префикс fast. Например, int_fast8_t. В случае, когда необходимо использовать максимально-возможное по величине целочисленное значение, используются int_max_t или uint_max_t.
В языке Си числа с плавающей точкой относятся к типам float, double и longdouble.
В стандарте Си установлено, что данные типа float должны иметь как минимум 6 значащих цифр и диапазон значений от 10-37 до 1037. Для типа double установлен тот же диапазон значений, а минимальное число значащих цифр увеличено до 10.
Для сообщения о переполнении в стандарте Си99 при выводе значения переменной отображается inf или infinity.
В ситуации связанной с потерей точности образуется т.н. субнормальное значение. Чаще всего это значение отображается как ноль.
В стандарте Си99 появилась поддержка комплексных чисел. Для них существует 3 типа данных: float_complex, double_complex и long double_complex. Все эти типы состоят из двух частей, одна из которых является вещественной, а другая - мнимой частью. При работе с этими типами можно использовать константу I для обозначения квадратного корня из -1.
8.4. Форматированный ввод/вывод.
Задачи ввода/вывода в языке Си решают функции printf() и scanf().
Операторы вывода используются для вывода значений переменных и текста.
Тексты в Си записываются в кавычках. В языке Си отсутствует специальный тип для работы со строками. Вместо этого строки представляются как массив типа char. Элементы строки, хранясь в массиве, записываются в смежные ячейки памяти. В конце строки ставится отметка \0. Наличие этой отметки говорит о том, что строка должна иметь размер на единицу больший, чем количество символов. Объявляется строка указанием типа char и записью размера в [].
Пример:
char name[40];
Для работы со строками к программе необходимо подключить файл string.h.
Каждая из функций ввода/вывода использует управляющую строку и список аргументов. Управляющая строка записывается первой и заключается в кавычки. Управляющие строки и аргументы не перемешиваются. Управляющие строки прежде всего содержат указание на вывод значения того или иного типа. Их называют спецификаторами преобразования.
Спецификаторы |
Действия |
%a, %A |
возвращают число с плавающей точкой и 16-е цифры |
%c |
возвращает одиночный символ |
%d, %i |
возвращают целое число в десятичной форме |
%e, %E |
возвращают число с плавающей точкой в экспоненциальной форме |
%f |
возвращает число с плавающей точкой в десятичной форме |
%g |
использует спецификатор %f или %e в зависимости от значения (выбирается автоматически) |
%o |
возвращает восьмеричное целое число без знака |
%p |
вывод указателя в шестнадцатеричном формате |
%s |
возвращает строку символов |
%u |
возвращает десятичное целое число без знака |
%x, %X |
возвращают шестнадцатеричное целое число без знака |
%% |
вывод на печать символа % |
Основную спецификацию можно модифицировать вставляя между % и символом преобразования модификаторы.
Модификаторы |
Действия |
цифра/цифры |
минимальная ширина поля вывода (количество экранных символов) |
.цифра |
точность |
h |
используется при целочисленных преобразованиях для кодирования значений short int и unsigned short int |
hh |
используется при целочисленных преобразованиях для кодирования значений signed char и unsigned char |
j |
используется при целочисленных преобразованиях для получения типов int_max_t и uint_max_t |
l |
используется при целочисленных преобразованиях для получения типа long int и unsigned long int |
ll |
используется при целочисленных преобразованиях для получения типа long long int и unsigned long long int |
t |
используется с целью кодирования значений типа ptroliff_t, который является разностью двух указателей |
z |
используется с целью кодирования значений size_t |
L |
используется при преобразовании чисел с плавающей точкой типа long double |
флаг |
+ |
значения со знаком печатаются со знаком "+" или "-" |
флаг |
- |
элемент выравнивается по левому краю |
флаг |
пробел |
значение со знаком "+" печатается с пробелом, но без знака |
флаг |
# |
для спецификаторов %o, %x, %X выводит не значащие нули. Для форм с плавающей точкой гарантировано печатается точка, даже если десятичных знаков нет |
флаг |
0 |
для числовых форм вместо пробелов на свободные экранные места выводятся нули |
Ввод данных осуществляется с помощью функции scanf(). В языке Си существует несколько функций ввода. scanf() употребляется чаще других, т.к. ей присущ различный формат ввода. Также как и функция printf(), ввод использует управляющую строку, сопровождаемую списком аргументов. Управляющая строка указывает в какие форматы должен быть преобразован вводимый текст. В качестве параметров функция scanf() использует не сами переменные, а указатели на них. Для использования scanf() необходимо выполнять два правила:
1) если функция используется для считывания значений в переменную основного типа, то перед именем переменной ставится знак &.
2) если значение считывается в символьный массив, то символ & не ставится.
Преобразование одного вводимого данного осуществляется указанием спецификатора преобразования. Если данных вводится несколько, то они разделяются знаком пробела.
Спецификаторы |
Действия |
%c |
интерпретирует результат ввода в качестве символа |
%d |
интерпретирует результат ввода как десятичное целое число со знаком |
%e, %f, %g, %a |
интерпретирует результат ввода как число с плавающей точкой |
%E, %F, %G, %A |
интерпретирует результат ввода как число с плавающей точкой. Все вводимые символы преобразуются в заглавные |
%o |
интерпретирует результат ввода как восьмеричное целое число со знаком |
%з |
интерпретирует результат ввода как указатель |
%s |
интерпретирует результат ввода как строку. Ввод начинается с первого символа, не являющегося служебным и включает все символы до следующего служебного |
%u |
интерпретирует результат ввода как целое число без знака |
%x, %X |
интерпретирует результат ввода как шестнадцатеричное целое число со знаком |
Между знаком % и символом преобразования могут использоваться модификаторы. Если их более одного, то они должны записываться в порядке, указанном в таблице ниже:
Модификаторы |
Действия |
* |
подавить присваивание |
цифра/цифры |
максимальная ширина поля ввода. Ввод прекращается когда указанная ширина достигнута или при обнаружении служебного символа |
hh |
определяет считывание целого числа в виде signed char или unsigned char |
ll |
определяет считывание целого числа в виде long long или unsigned long long |
L, l, h |
определяет считывание числа в виде short int, unsigned short int, unsigned long, long, double или long double |
назад содержание вперед на
главную
|