Программирование на языке Си
Программирование на языке Си
Конспект лекций
Введение
Возможности ЭВМ как технической основы обработки информации связаны с используемым программным обеспечением (программами). Программы предназначены для машинной реализации различного рода задач. При программировании широкое применение имеют термины задача и приложение. Задача (problem, task) – проблема, подлежащая решению. Приложение (application) – программная реализация алгоритма решения задачи.
Написание программы предусматривает выполнение определенного числа действий, которые с большей или меньшей детализацией можно разделить на следующие важнейшие этапы:
- постановка задачи;
- выбор метода (алгоритма) решения задачи;
- написание программы на языке программирования С;
- ввод исходного текста программы с помощью текстового редактора, текст оформляется в виде файла (модуля) с расширением .с или .срр;
- компиляция модуля (или нескольких модулей вместе); на этом этапе получаем объектный файл, т.е. файл с расширением .obj;
- отладка синтаксиса программы;
- объединение откомпилированных модулей в программу (это часто называют компоновкой или линковкой программы); на этом этапе к программе присоединяют необходимые стандартные библиотеки и мы получаем выполняемый файл с расширением .exe;
- запуск программы на выполнение;
- отладка программы (тестирование программы и устранение ошибок);
- окончательное оформление программы.
При постановке задачи решаются (или уточняются) следующие проблемы:
- цель и назначение задачи, ее место и связи с другими задачами;
- условия и ограничения решения задачи;
- содержание функций обработки входной информации;
- требования к периодичности решения задачи;
- состав, форма и точность представления выходной информации.
Входная информация в задаче определяется как данные, поступающие на вход задачи и используемые для ее решения. Входные данные - это первичные данные документов ручного заполнения, информация, хранимая в файлах, базы данных, выходные результаты решения других задач и т.д.
Выходная информация может быть представлена в виде документов (листинга), файлов данных, сигналов управления выходными устройствами.
Алгоритм – система точно сформулированных правил, определяющая процесс преобразования допустимых исходных данных (входной информации) в желаемый результат (выходную информацию) за конечное число операций.
Алгоритм решения задачи имеет ряд обязательных свойств:
- дискретность – разбиение процесса обработки информации на более простые этапы (операции), выполнение которых ЭВМ или человеком не вызывает затруднений;
- определенность алгоритма – однозначность выполнения каждого определенного этапа преобразования информации;
- выполнимость – конечное число операций решения задачи;
- массовость – пригодность алгоритма для решения определенного класса задач.
В алгоритме отражается логика и способ формирования результатов решения с указанием расчетных формул, логических условий, соотношений для контроля достоверности выходных условий.
Алгоритм решения задачи и его программная реализация тесно взаимосвязаны. Чем детальнее описан алгоритм, тем проще его программная реализация.
Программа – результат интеллектуального труда, для которого характерно творчество. В любой программе присутствует индивидуальность ее разработчика. Вместе с тем программирование предполагает и рутинные работы, которые могут и должны иметь строгий регламент выполнения и соответствовать принятым стандартам.
Ключевые слова и синтаксис языка
Синтаксис языка C
Есть шесть классов лексем: идентификаторы, ключевые слова, константы, строки, операторы и разделители.
Идентификаторы: последовательность букв и цифр произвольной длины. Первый символ-буква, например, NAME1, name 1, Name 1, name_1…
Ключевые слова: Они зарезервированы для языка и не могут использоваться другим образом. Список ключевых слов языка представлен в табл.1.1
Таблица 1.1
Ключевые слова языка
Типы данных | Операторы | |||||
Eng | Рус | Eng | Рус | |||
Сhar | Символ | Asm | ||||
Class | Класс | Break | Прерывание | |||
Double | Двойной | Case | Выбор | |||
Enum | Перечень | Continue | Продолжение | |||
Float | Плавающий | Default | По молчанию | |||
Продолжение табл. 1.1 | ||||||
Int | Целый | Delete | Удалять | |||
Long | Длинное целое | Do | Делать | |||
Short | Короткое целое | Else | Иначе | |||
Struct | Структура | For | Для | |||
Union | Объединение | Go to | Идти (переход) | |||
Unsigned | Беззнаковый | If | Если | |||
Void | Пустой | New | Новый | |||
Return | Возврат | Switch | Прерывать | |||
Extern | Внешняя | Inline | В линию | |||
Register | Регистр | Const | Постоянный | |||
Overload | Переопределение | Typedef | Тип переменной | |||
Auto | Автоматически | While | Пока | |||
Static | Статический | Public | Открытый | |||
Константы: целые, символьные, с плавающей точкой, строки.
Целая – последовательность цифр. Константа - восьмеричная, если начинается с 0, в противном случае – десятичная. Цифры 8 и 9 не являются восьмеричными цифрами. Последовательность цифр 0X или 0x воспринимается как шестнадцатеричное целое число. В шестнадцатеричные цифры входят буквы от A до F(f), имеющие значения 10 – 15.
Примеры: 0x53=83; 0xF=15; 0xA = 10.
Константа, значение которой превышает наибольшее машинное целое со знаком, считается длинной (long), в остальных случаях константы считаются целыми (int).
Длинные константы: десятичная, восьмеричная или шестнадцатеричная константа, за которой непосредственно стоит буква L (l), считается длинной константой.
Примеры: 12l - десятичная,
0123L - восьмеричная,
0xaaaal - шестнадцатеричная.
Перевод чисел из одной системы счисления в другую приведен в табл. 1.2.
Для представления шестнадцатеричного числа в двоичном коде надо заменить двоичной записью каждую цифру этого числа. Например, числа 0xAB01 и 0x53, представленные в двоичном виде, переводятся в десятичные по известной формуле перевода [1].
Таблица 1.2
Таблица перевода чисел
Десятичное число | Шестнадцате-ричное число | Двоичная запись числа | Восьмерич-ная запись числа | Шестнадцате-рич-ная запись числа |
0x0 | ||||
0x1 | ||||
0x2 | ||||
0x3 | ||||
0x4 | ||||
0x5 | ||||
0x6 | ||||
0x7 | ||||
0x8 | ||||
0x9 | ||||
A | 0xA | |||
B | 0xB | |||
C | 0xC | |||
D | 0xD | |||
E | 0xE | |||
F | 0xF |
A B 0 1
1010 1011 0000 0001 –> 1010101100000001=
1 * 215 + 0 * 214 + 1 * 213 + 0 * 212 + 1 * 211 + 0 * 210 + 1 * 29+ 1 * 28 + … 1 * 20 = 43777;
0x53 = 01010011 = 0 * 27 + 1 * 26 + 0 * 25 + 1 * 24 + 0 * 23 + 0 * 22 + 1* 21 + 1 * 20 = 83;
Символьная константа состоит из символа, заключенного в апострофы (например, ‘x’). Значением символьной константы считается численное значение константы в машинном наборе (алфавите). Символьные константы считаются данными типа char. Использование неграфических символов, однозначная кавычка ‘ и обратная косая \ производится в соответствии с табл.1.3
Таблица 1.3
Использование специальных символов
Название | Обозначение |
Символ новой строки | \n |
Горизонтальная табуляция | \t |
Вертикальная табуляция | \v |
Возврат на шаг | \b |
Возврат каретки | \v |
Продолжение табл. 1.3 | |
Название | Обозначение |
Перевод формата | \f |
Обратная кавычка | \\ |
Апостроф | \’ |
Набор битов 0ddd | \ddd |
Набор битов 0xddd | \xddd |
Пустой символ | \0 |
Последовательность \ddd состоит из обратной косой, за которой следуют 1, 2, 3 - восьмеричные цифры, задающие значение требуемого символа. \xddd та же последовательность, где 1, 2, 3 – шестнадцатеричные цифры.
Константы с плавающей точкой (с Е) используются для представления больших чисел в компактной форме.
Примеры: 345. = 345
3.14159
2.1Е5 = 210000
.123Е3 = 123
4037е-5 = .04037
Строки. Строка – это последовательность символов, заключенная в двойные кавычки “…”. Строка имеет тип char, а класс памяти static. Она инициализируется заданными символами. Все строки, даже если они занесены одинаково, различны. Компилятор располагает в конце каждой строки нулевой (пустой) байт \O с тем, чтобы сканирующая строку программа могла найти ее конец. В строке перед символом двойной кавычки должна стоять обязательно \. Кроме того, могут использоваться те же обозначения, что были описаны для символьных констант.
Примеры:
“Это строковая константа”
“A”
“Это одна \*\
строка”
Имена и типы. Имя обозначает объект, функцию, тип, значение или метку. Имя может использоваться только внутри части текста программы, называемой его областью видимости. Имя имеет тип, определяющий его использование.
Объект – это область памяти. Объект имеет класс памяти, определяющий время его жизни.
Область видимости. Существует четыре ее вида: локальная, файл, программа и класс.
Локальная область- имя, описанное в блоке, локально в этом блоке и может использоваться только в нем. Исключения составляют метки, которые могут использоваться в любом месте функции, в которой они описаны.
Файл – имя, описанное вне любого блока. Программа – имя, описанное в файле, может использоваться в любом другом файле.
Класс - имя члена класса, локально для его класса и может использоваться только в функции-члене этого класса.
Сводка операций языка Си
Все операции языка Си разбиты на категории (табл. 1.6). Каждая операция имеет свой приоритет, который убывает с ростом категории. Все операции одной категории имеют одинаковый приоритет. Унарные операции (категория 2), условная (категория 14) и присваивания (категория 15) ассоциируются (выполняются) справа налево. Все остальные операции ассоциируются слева направо.
Таблица 1.6
Сводка операций языка Си
Категория | Операция | Название или действие |
1. Наивысшего приоритета | ( ) [ ] : : | Вызов функции Индексирование Косвенное обращение к члену класса Прямое обращение к члену класса |
2. Унарные | . ! ~ + - + + - - & * size of new delete | Прямое обращение к члену класса Логическое отрицание Дополнение до единицы Унарный плюс Унарный минус Преинкремент или постинкремент Предекремент или постдекремент Адрес Обращение Размер Создание динамического объекта Удаление |
3. Мультипликативные | * / % | Умножение Деление Деление по модулю |
4. Косвенное обращение | . * -> * | Прямое косвенное обращение через указатель Косвенное обращение через указатель |
5. Аддитивные | + - | Бинарный плюс Бинарный минус |
6. Сдвига | << >> | Сдвиг влево Сдвиг вправо |
7. Отношения | < <= > >= | Меньше Меньше или равно Больше Больше или равно |
Продолжение табл. 1.6 | ||
8. Равенства | = = != | Равно Не равно |
9. 10. 11. 12. 13. 14. | & ^ | && || ? : | Побитовое И Побитовое исключающее ИЛИ Побитовое включающее ИЛИ Логическое И Логическое ИЛИ Условия |
Как видно из приведенных таблиц, язык Си богат на операции. Знак операции – это символ или комбинация символов, которые сообщают компилятору о необходимости произвести определенные арифметические, логические или другие действия.
Для каждой операции определено количество операндов и определенный порядок выполнения:
- один операнд – унарная операция, например унарный минус (-х), изменяющая знак;
- два операнда - бинарная операция, например, операция сложения (x + y) или вычитания (x - y);
- три операнда – операция условия ?:, такая операция только одна.
Каждая операция может иметь только определенные типы операндов. Например, операция побитового сдвига определена только для целочисленных операндов. Более подробно об операциях будет дано в следующих разделах.
2. Базовые средства языка Си
2.1. Типы данных
Составление программы на языке Си предполагает выполнение следующих основных этапов (здесь предполагается, что задача поставлена, формализована и выбран алгоритм её решения):
1. Ввод и размещение в памяти ЭВМ исходных данных.
2. Задание последовательности операций над исходными данными в соответствии с выбранным алгоритмом решения задачи.
3. Вывод результатов решения задачи.
Ввод данных осуществляется с клавиатуры, с диска, либо с портов ввода /вывода.
Размещение в памяти ЭВМ требует указания типа переменных. По структуре данные разделяют на простые и составные (сложные).
Простые типы данных. Эти типы (табл.2.1) являются базовыми типами данных языка Си. На их основе формируются более сложные типы.
Таблица 2.1
Типы простых данных
Имя базового типа | Спецификация | Объём занимаемой памяти, байт | |
Целые | signed char signed int signed short int signed long int unsigned char unsigned int unsigned short int unsigned long int | Знаковый символьный Знаковый целый Знаковый короткий целый Знаковый длинный целый Беззнаковый символьный Беззнаковый целый Беззнаковый короткий целый Беззнаковый длинный целый | |
Плаваю-щие | Float Double long float long double | Плавающий Плавающий 2-й точности Длинный плавающий Длинный плавающий 2-й точности | |
Прочие | Void Enum | Пустой Перечислимый |
При задании типов данных, т. е. при описании данных, если спецификация не используется, то компилятор предполагает тип int. Если не используется спецификация signed или unsigned, то предполагается знаковый тип.
Тип переменной определяет максимально - возможное число, которое может быть помещено в памяти ЭВМ. Самое маленькое отрицательное число, которое можно записать в 8 - ми разрядной сетке – (-128), в 16 - разрядной сетке (-32768).
Поэтому, например, если вычислить n! при n=8 мы получили бы число 40320. Оно значительно превосходит максимально возможное положительное число (32767), которое можно записать в 16-м разрядной сетке, что привело бы к переполнению разрядной сетки ЭВМ. Поэтому надо осторожно подходить к выбору типа int или же брать тип float, которое записывается в форме , где m-мантисса, E=10, Р - целочисленный порядок, в пределах от –39 до +38.
В табл. 2.2. приведены значения чисел, которые могут быть записаны в выше перечисленных типах.
Таблица 2.2
Числовые значения типов
Тип переменной | Количество бит | Диапазон чисел |
shortint (знаковый) | 8 бит (левый бит отведён под знак) | -128 a 127 |
int | (знаковый) | -32768 a 32767 |
longint | (знаковый) | -2147483648 a -2147483647 |
Составные (сложные) типы данных. К составным типам данных относятся:
- массивы - данные регулярной структуры;
- структуры – логически связанные данные разных типов.
Данные типы будут рассмотрены позднее подробно.
Особое место занимают данные типа указатель. Значением указателя является адрес расположения в памяти (или адрес памяти) простой переменной, массива, структуры либо функции. В языке Си аппарат указателей используется наиболее интенсивно.
Пример записи данных в программе.
int a,b,c;
float x,y;
char ch;
double e;
unsigned u;
и т.д.
Операции над данными
Операции над данными задаются с помощью операторов:
- присвоения;
- передачи управления по условию;
- организации циклов.
Эти операторы являются средствами организации линейных, разветвляющихся и циклических алгоритмов. Любая программа, кроме самой простой, состоит из вышеперечисленных базовых структур алгоритмов, определяемых соответствующими операторами.
Знаки операций (арифметических, отношения, логических, битовых) используются для объединения констант и переменных в соответствующие выражения.
Операции над данными предполагают наличие объектов некоторого типа и использование знаков операций.
Наиболее распространенной является операция присваивания ``=``. Она предназначена для изменения значений переменных, в том числе и вычислений «по формуле»
Например,
x =362;
k = k + 2;
m = c = 1;
Базовая форма
<имя>=<выражение>
Разновидность операции присваивания
<имя>=<имя> <знак операции> <выражение>
В отличие от других языков программирования, в Си применяется также компактная форма операции присваивания. В компактной форме последнюю запись можно представить так:
Примеры:
A = a + b то же, что a + = b,
A = a*b то же, что a * = b,
A = a*(3*b +10) то же, что а*=3*b+10 ,
i=i+1 тоже, что и i++.
Арифметические операции.
Различают унарные и бинарные операции.
Бинарными операциями являются:
+ сложение;
- вычитание;
* умножение;
/ деление;
% деление по модулю.
Унарные операции:
- унарный минус;
операции единичного приращения:
++ положительного (увеличения на единицу - инкремент),
-- отрицательного (уменьшения на единицу – декремент).
Различают апостериорное приращение, например:
c=a+b++, что при пошаговом выполнении будет означать: c1=a+b; c2=a+(b+1); c3=a+(b+2); и т. д.,
и априорное приращение, например c=a+++b, что при пошаговом выполнении будет означать: c1=a+(b+1); c2=a+(b+2)…
i++ и --i – это полноправные выражения.
Старшинство арифметических операций следующее:
++, --
- (унарный минус)
*, /, %
+, –
Операции, одинаковые по старшинству, выполняются в порядке слева направо.
Чтобы изменить порядок операций используют круглые скобки.
Операции над битами (с двоичными разрядами).
Бинарные:
Сдвиг влево a=b<<c;
Cдвиг вправо a=b>>;
Операция “И” a=b&c;
Операция “ИЛИ” a=b|c;
Операция исключающее “ИЛИ” a=b^c;
Унарная
“НЕ” a=~b.
Помимо перечисленных операций, в языке Си используются операции отношения и логические операции. В языке Си нет данных логического типа. Поэтому принято соглашение, что если в результате логической операции получено значение не равное нулю (!=0), то результат трактуется как ”истина”. В противном случае – как “ложь”.
Примеры операций отношения:
a>b; a>=b; a<=b; a= =b; a != b,
где = = знак «равно»;
!= знак «не равно».
< меньше,
> больше,
>= больше или равно,
<= меньше или равно.
Примеры логических операций:
a&&b - операция логическое “И”,
a | | b - операция логическое “ИЛИ”,
! a - операция логическое “НЕ”.
Операции вывода данных
Ввод и вывод данных в языке Си осуществляется не с помощью встроенных операторов, как в других языках, а с помощью специальных программных модулей, называемых функциями, содержащимися в файлах -прототипах.
Вывод результатов счёта. Вывод результатов счёта осуществляется на стандартный терминал (stdout), на диск, на принтер, либо в порт ввода/вывода.
Следует сказать, что программа на языке Си состоит из функций, или как минимум из одной функции, называемой main(). Эта функция является главной функцией и любая программа начинает выполняться с её главного оператора.
Функции вывода данных. Основные функции вывода данных приведены в табл. 2.3
Таблица 2.3
Функции вывода данных
Имя функции | Описание | Файл, содержащий прототип |
printf() puts() putchar() cprintf() cputs() putch() | Производит форматированный вывод данных в stdout Выводит строку символов в stdout Вводит символ в stdout Осуществляет форматированный вывод на экран Выводит строку на экран Выводит символ на экран | stdio.h stdio.h stdio.h conio.h conio.h conio.h |
Функции из файла-заголовка сonio.h работают только на компьютере IBM PC. Их можно рассматривать, как дополнение к стандартным функциям. Их так же называют консольными.
Отличие стандартных функций от консольных заключается в том, что последние не преобразуют символы перевода строки \n в последовательность символов перевода строки \n и возврата каретки \r. Поэтому программист сам должен позаботиться об этом (см. ниже).
Обобщённая запись функции printf() следующая:
printf(“строка форматов”, обьект, обьект, …);
Пример:
int y; // объявление целочисленной переменной
int x=5; //объявление и инициализация переменной
…
y=x+20; // операция присваивания
printf(“получено число %d \n”, y); //вывод числа
printf(“получено число %d \n”, x+20); //вывод значения выражения
printf(“получено число %d %d \n”, x,y); //вывод двух объектов
Здесь %d – спецификация поля представления целого числа;
x, y – объекты вывода (сами числа);
x + 20 – выражение, значение которого выводится;
// - признак строки- комментария.
В качестве объекта вывода используются константы, переменные, выражения, указатели функций.
В функции printf() используются следующие спецификации полей представления данных (табл. 2.4)
Таблица 2.4
Спецификации полей данных
Формат (Спецификатор) | Типы вводимой информации |
%d | Десятичное целое число |
%i | Десятичное целое число со знаком |
%c | Символ |
%s | Строка символов |
%f | Число с плавающей точкой |
%u | Десятичное целое число без знака |
%ld | Длинное целое |
%p | Целое указателя |
%o | Восьмеричное целое без знака |
%x | Шестнадцатеричное целое без знака |
Первые шесть форматов используются наиболее часто. Размер поля вывода задается либо по умолчанию, либо явно цифрой между знаком % и соответствующей буквой, например:
%-10s; %6d; %8.3f; %ld.
Здесь, так называемые, модификаторы имеют следующий смысл:
- печать с крайней левой позиции поля;
10 - задает максимальное число печатаемых символов строки;
6 – задает максимальное число печатаемых цифр;
8.3 – задает общую ширину поля (8) и число символов (3) после десятичной точки.
Задание окна вывода
Большинство программ связано с окнами (windows), а не со всем экраном. Окно – это прямоугольная область экрана, которую программа использует для выдачи сообщения.
Borland C++ позволяет устанавливать размер и местоположение окон на экране. Окном может быть весь экран или его маленькая область. По умолчанию областью вывода является весь экран. Если требуется установить окно меньшего размера нужно использовать функцию window(), а для очистки окна – функцию clrscr().
Приведем пример простой программы и рассмотрим ее более подробно:
Пример:
#include <conio.h>
int main (void)
{
clrscr( ); /* очистка текстового окна*/
window(10,10,60,20,); /* задание нового окна */
cputs (“Это текст \r\n”); /* вывод текста */
getch( ); /* ждать нажатия клавиши */
retrn 0;
}
Рассмотрим каждую строку:
1. #include <conio.h> - директива препроцессора (текстового процессора), требующая подключить файл conio.h к нашей программе. Любая директива препроцессора начинается с символа # (номер).
2. int main (void) – здесь int - тип значения, возвращаемого функцией main, т.е. целое число;
main – имя функции;
(void) – означает отсутствие параметров у функции.
3. { - открывающая скобка – означает начало описания функции.
4. /* это комментарий */ - игнорируется компилятором.
5. clrscr ( ) - функция, очищающая текущее текстовое окно. Первоначально текстовое окно занимает все поле экрана.
6. window(10,10,60,20),
window(x1,y1,x2,y2) - функция, определяющая координаты текущего текстового окна. Окно задается координатами левого верхнего угла (x1,y1) и правого нижнего угла (x2,y2). В обычном режиме (С80) эти координаты задаются пределами: 1<= x <= 80; 1<= y <= 25.
7. cputs() – выводит строку текста, заключенную в двойные кавычки. \r\n -управляющие последовательности (см. табл.1.3).
8. getch( ) – функция, ожидающая нажатия любой клавиши; используется для временной остановки программы.
9. return 0 - оператор, с помощью которого функция возвращает в точку вызова некоторое значение.
10. } - закрывающая скобка функции main ().
Число открывающих и закрывающих скобок в программе должно быть всегда одинаковым.
Операции над адресами
Любое данное размещается в памяти ЭВМ и, следовательно, имеет некоторый адрес, обращаясь по которому можно извлечь данное из памяти. В языке Си определены две основные операции над адресами:
&- определение адреса операнда;
* - обращение по адресу.
Например, если bip – переменная типа int, то &bip – адрес переменной, по которому она расположена в памяти;
Если char *prt –указатель на данное типа char, то *prt – это само данное типа char (символ).
Пример операции над адресами:
# include <conio.h>
void main (void)
{
int bip;
char *prt;
bip = 2+3;
prt = ‘’Язык Turbo C\n’’
cprintf (‘’bip = %d &bip = %p\n\r’’, bip, &bip);
cprintf (‘’*prt = %c prt = %p\n\r’’, *prt, prt);
}
В результате выполнения этой программы в первой строке будет выведено значение переменной bip, равное 5 и адрес, по которому это значение размещено в памяти. Во второй строке будет выведен символ ''Я'', т.е. первый символ и адрес, по которому этот символ расположен в памяти.
Для того, чтобы более четко уяснить механизм адресации к строке символов, рассмотрим этот вопрос более подробно.
Определение местоположения строки символов и адресация к ней осуществляется с помощью указателя.
Символьные массивы (строки). Вспомним, что в языке Си переменная типа указатель объявляется следующим образом:
int *a; char *b; и т.п.
После таких объявлений а и в трактуются как переменные - указатели на соответствующий тип, a *a и *b – как сами переменные данного типа.
Переменные типа указатель содержат адрес операнда, на который они ссылаются:
Пример:
# include <conio.h>
void main (void)
{
char *st;
st = ”Язык программирования C\n”
cputs (st);
}
В результате обработки строки программы:
st =”Язык программирования C\n”
компилятор создает в тексте объектного кода машинный эквивалент этой строки, а переменной - указателю st присвоит адрес первого символа строки, т.е. адрес символа “Я”. Машинный код строки завершается специальным символом - терминатором или нулевым символом '\О'.
Команда cputs(st) воспроизведет строку символов на экране дисплея, начиная с того, который адресуется переменной st, вплоть до символа - терминатора.
Помимо определения строки символов в форме указателей существует и другая форма задания строки: в форме массива символов.
Пример:
# include <conio.h>
# include <string.h> /* файл заголовка функций, оперирующих со строками*/
void main (void)
{
char mas [24];/* описание массива из 24 символов */
strcpy (mas,’’Язык программирования С ''); /*копирование строки в массив */
cputs (mas);
}
По команде char mas [24] компилятор зарезервирует область памяти для 23 символов строки и еще один байт для размещения символа- терминатора '\О'.
Переменная mas несет информацию об адресе первого символа (нулевого элемента массива, т.к. массивы в Си нумеруются с 0: mas [0], mas[1],.. и т.д.).
Функция cputs() выведет на экран посимвольно все элементы массива. При этом каждый раз будет осуществляться проверка: не является ли очередной символ символом-терминатором.
Вот почему при размещении строки в массиве всегда необходимо отводить как минимум на один элемент больше для '\О', или определяйте необходимый размер в памяти по умолчанию:
char mas[]=’’Строка символов''; /* Размер массива не задан */.
Отметим, что функция cputs() и strcpy() работают с формальными параметрами типа указатель. Их прототипы имеют следующий вид:
int cputs (char* string);
char strcpy (char*dest, char* sours).
Это значит, что при вызове этих функций им должны в качестве фактических параметров передаваться адреса. Но в нашей программе нигде не встречается символ &. В чем же дело?
В том, что при описании массива его имя трактуется как указатель на его первый элемент, т.е.
mas эквивалентно & mas[0] |
Ввод данных в языке СИ
Основные функции, осуществляющие ввод данных представлены в табл.2.5.
Таблица 2.5
Функции ввода
Имя Функции | Описание | Файл, содержащий прототип |
Scanf() Gets() Getchar() Cscanf() Cgets() Getch() | Выполняет форматный ввод из потока stdin Получает строку символов из потока stdin Вводит символ из потока stdin Выполняет форматный ввод с клавиатуры Считывает строку символов с клавиатуры Вводит символ с клавиатуры без эхо-печати | stdio.h stdio.h stdio.h conio.h conio.h conio.h |
Рассмотрим краткое описание этих функций.
Функции scanf() и cscanf() используются для интерактивного ввода. Обобщенная форма записи этих функций следующая:
(с)scanf (“строка форматов'', адрес, алрес,…);
В строке форматов применяются те же спецификаторы, которые были рассмотрены ранее для функции printf(): %d, %f, %c, %s (табл.2.4).
В отличие от функций printf() функция (с)scanf() требует указания в списке ввода не данных, а их адресов.
Пример:
/* ввод двух целых чисел в ячейки памяти ''а'' и ''b''*/
(с)scanf (“%d %d”, &a, &b);
где &a &b- адреса операндов ''a'' и ''b''.
Пример:
/* ввод строки символов, представленных массивом */
#include <conio.h>
void main (void)
{
clrscr ( );
char im [10];
cprintf (“Введите имя:” );
cscanf (”%s”, im) ;
cprintf (”\n\r Ваше имя : %s \n\r”, im);
}
Вспомним, что имя массива указывает на его первый элемент, поэтому перед im не ставится символ &.
Входной поток разбивается на отдельные поля с помощью специальных знаков: пробелов, символов табуляции.
Внимание: Для ввода строки, содержащей пробелы, функцию (с)scanf () не используют. Для этой цели предназначена функция (с)gets().
Функции gets() и cgets() читают строку символов, оканчивающуюся символом перевода строки. Символ перевода строки заменяется на символ -терминатор ’\0’.
Пример:
# include <stdio.h>
#include <conio.h>
void main (void)
{
clrscr ();
char string [40];
printf (”Введите строку : ”);
gets (string);
printf (”Строка = %s \n”, string);
getch ( );
}
Функции getchar() и getch(). Функция getchar() предназначена для ввода одиночного символа. Возвращает считанный символ, преобразованный в целое число. Так как буфер stdin имеет размер в одну строку, то функция ничего не возвращает, пока не нажата клавиша ”Enter”.
Пример:
# include <stdio.h>
int main (void)
{
char c;
while ((c=getchar())!=’\n’)
printf (”%c”, c);
return 0;
}
Else
оператор_2;
Правило выполнения: если выражение в скобках (здесь некоторое условие) не равно нулю, т.е. “истина”, то выполняется оператор_1. В противном случае выполняется оператор_2.
б) в сокращенной форме:
if (выражение)
оператор_1;
Если выражение в скобках (…) не равно нулю, то выполняется оператор_1, в противном случае управление передается следующему оператору программы.
Операторы_1 и _2 могут быть как простыми, так и составными. В последнем случае группа операторов должна заключаться в фигурные скобки:
{
оператор_1;
оператор_2;
…………
оператор_n;
}.
Каждый оператор внутри скобок должен заканчиваться “;”.
Пример 3.1:
# include <conio.h>
void main ( void)
{
clrscr ();
float a, b, rez ;
printf (“Введите значение а и b: “);
scanf (“%f %f “, &a, &b);
if (b= =0)
printf (“Отношение a / b не определено \n “);
Else
{
rez = a / b;
printf (“Отношение a / b равно %6, 3f\n”, rez);
}
getch( );
}
Еще один фрагмент:
. . . . . . . . .
if ( (ch = getch( ) )= =’g’)
puts (“Конец работы \n”);
Else
puts (“Работа продолжается \n”);
Выражение после слова if может состоять из нескольких операций присваивания, разделяемых запятыми. Значение всего выражения будет определяться последним присваиванием. Это справедливо для любого составного выражения. Например:
if (с=сh,ch=getch( ) ).
Операторы организации цикла
Если в программе имеет место периодическое повторение некоторой последовательности действий, то говорят о наличии цикла.
Циклические вычисления в языке Си реализуются операторами for ... , while ... , do ... while... . Операторы цикла for – со счетчиком , while- с предусловием; do...while- с постусловием.
Оператор for имеет следующую конструкцию:
for (выражение_1 ; выражение_2 ; выражение_3)
оператор;
где: выражение_1 устанавливает начальное значение параметра цикла;
выражение_2 определяет условие продолжения цикла;
выражение_3 задает правило модификации параметра цикла.
Каждое из этих трех выражений может быть групповым или может отсутствовать, в том числе и одновременно, но разделители ‘;’ обязательно должны быть. Если отсутствует выражение_2 , то оно считается истинным по умолчанию.
Конструкциии бесконечных циклов:
for (; ; ;) printf(“ Бесконечный цикл\ n”);
for (i =1; 1; i++) printf(“ Бесконечный цикл\ n”);
for (i =10; i >6; i++) printf(“ Бесконечный цикл\ n”);
Тем не мене для таких циклов также может быть организован выход. Для этого используют оператор break, который будет рассмотрен несколько позже.
Пример 3.4: Вычислим сумму первых n целых положительных чисел.
#include <stdio.h>
#include <conio.h>
void main()
{
int n; // количество суммируемых чисел
int sum; // сумма
int i ; // счетчик циклов
printf(“Вычисление суммы положительных чисел \n”);
printf(“введите количество суммируемых чисел \n”);
scanf(“%i”, &n);
sum = 0;
for (i =1; i <= n; i++)
sum + = i;
printf(“ Сумма первых % i целых положительных чисел \n”);
printf(“ равна % i”, sum);
printf(“ \n Для завершения нажмите <Enter>”);
getch();
}
Наиболее универсальным является оператор цикла while (пока). Оператор while имеет следующую форму:
while (выражение)
оператор;
Пока выражение в скобках (. . .) не равно нулю, повторяется выполнение оператора (простого или составного).
Приме