- •1.1. Алфавит языка Си
- •1.2. Лексемы
- •1.3. Идентификаторы и ключевые слова
- •1.4. Знаки операций
- •1.5. Литералы (константы)
- •1.6. Комментарии
- •1.7. Общая структура программы на языке Си.
- •1.8. Функциональная и модульная декомпозиции
- •1.9. Этапы обработки программы.
- •1.10. Роль препроцессора.
- •1.11. Ошибки
- •2. Переменные и константы. Типы данных
- •2.1. Основные типы данных
- •2.2. Декларация (объявление) объектов
- •2.3. Константы в программах
- •2.4. Целочисленные константы
- •2.5. Константы вещественного типа
- •2.6. Символьные константы
- •2.7. Строковые константы
- •2.8. Логические константы
- •3. Обзор операций
- •3.1. Операции, выражения
- •3.2. Арифметические операции
- •3.3. Операции сравнения
- •3.4. Логические операции
- •3.5. Операция присваивания
- •Примеры недопустимых выражений:
- •3.6. Сокращенная запись операции присваивания
- •3.7. Операция «,» (запятая)
- •4. Обзор операций (продолжение)
- •4.1. Преобразование типов операндов бинарных операций
- •4.2. Преобразование типов при присваивании.
- •4.3. Операция явного приведения типа
- •4.4. Приоритеты операций
- •5. Стандартная библиотека языка Си
- •5.1. Стандартные математические функции
- •5.2. Потоковый ввод-вывод
- •5.3. Консольные функции вывода данных на экран
- •5.4. Консольные функции ввода информации
- •5.5. Ввод-вывод в оконных приложениях.
- •Советы по программированию
- •6. Операторы языка с.
- •7. Составление разветвляющихся алгоритмов
- •7.1. Условные операторы
- •If (выражение) оператор;
- •If (выражение) оператор 1 ;
- •If (выражение 1) оператор 1;
- •If (выражение 2) оператор 2;
- •If (выражение 3) оператор 3;
- •7.2. Оператор выбора альтернатив (переключатель)
- •Void main(void)
- •7.3. Условная операция «? :»
- •8. Составление циклических алгоритмов
- •8.1. Оператор с предусловием while
- •8.2. Оператор цикла с постусловием do – while
- •Void main(void)
- •8.3. Оператор цикла с предусловием и коррекцией for
- •8.4. Вложенные циклы.
- •Пример 1.
- •Void main(){
- •Пример 2.
- •9. Операторы передачи управления.
- •9.1. Оператор безусловного перехода goto
- •9.2. Операторы continue, break и return
- •10. Массивы
- •10.1. Одномерные массивы
- •10.2. Примеры алгоритмов, использующих одномерные массивы.
- •10.3. Многомерные массивы
- •10.4. Примеры алгоритмов, использующих двумерные массивы.
- •10.5. Компонента StringGrid
- •11. Размещение данных и программ в памяти пэвм
- •11.1. Общие понятия.
- •11.2. Кодирование целых чисел.
- •11.3. Кодирование вещественных чисел.
- •11.4. Кодирование символов.
- •Примеры кодов символов:
- •Стандартная часть таблицы символов (ascii)
- •Дополнительная часть таблицы символов (ascii, кириллица)
- •Дополнительная часть таблицы символов (ansi, кириллица)
- •11.5. Операция sizeof
- •11.6. Кодирование программы.
- •11.8. Регистры
- •12.1. Строки как нуль-терминированные массивы char.
- •Void main(){
- •If (!strcmp(a,b))
- •Itoa(I, s, 10);
- •If (! sscanf(s, "%d", &I))
- •If (!strnicmp(s, "song", 4)) {
- •If (!strnicmp(s, "song", 4)) {
- •12.2. Русификация консольных приложений.
- •Void main(void)
- •12.3. Строки как переменные типа AnsiString.
- •12.4. Преобразования строковых типов.
- •12.5. Тип String в консольных приложениях.
- •Void main(){
- •13. Функции пользователя.
- •13.1. Сущность и предназначение функций.
- •13.2. Определение и вызов функции.
- •Void main(){
- •14. Область видимости и классы памяти
- •14.1. Область видимости.
- •Void fun(void);
- •14.2. Классы памяти объектов в языке Cи.
- •Void f1(int);
- •Void main(void)
- •Void f1(int I)
- •Void st(void){
- •14.3. Разбиение программы на модули.
- •15. Генерация псевдослучайных чисел.
- •16. Отладка и пошаговое выполнение программы
- •17. Указатели
- •17.1. Определение указателей
- •17.2. Связь указателей и массивов.
- •17.3. Операции над указателями (косвенная адресация)
- •17.4. Сравнение указателей
- •17.5. Массивы указателей.
- •17.6. Указатели на указатели.
- •17.7 . Указатели как параметры функций.
- •Void zam(int *X, int *y)
- •Void zam(int &X, int &y)
- •Void zam (int&, int&);
- •Void main (void)
- •17.9. Указатели на функции
- •Void FunOut(double (*p_f )(char, double)){
- •18.2. Создание одномерного динамического массива.
- •18.3. Создание двуxмерного динамического массива.
- •19. Операция typedef
Void f1(int);
Void main(void)
{
f1(5);
}
Void f1(int I)
{
int m=0;
puts(" n m p ");
while (i--) {
static int n = 0;
int p = 0;
printf(“ %d %d %d \n”, n++ , m++ , p++);
}
}
В результате выполнения программы получим:
n m p
0 0 0
1 1 0
2 2 0
3 3 0
4 4 0
Статическая переменная n будет создана в сегменте данных ОЗУ и проинициализируется нулем только один раз при первом выполнении оператора, содержащего ее определение, т.е. при первом вызове функции f1. Автоматическая переменная m инициализируется при каждом входе в функцию. Автоматическая переменная р инициализируется при каждом входе в блок цикла.
Задача 3. Условие задачи 2, но в начале каждой строки из звездочек выводить ее порядковый номер.
Функция st() примет вид:
Void st(void){
static int k;
cout<<"\n"<<++k<<
") ********************************\n ";
}
Результат работы программы (подчеркнуто число, введенное человеком):
Vvedite x :
3
1) ********************************
sin=0.14112
2) ********************************
cos=-0.989992
3) ********************************
tg=-0.142547
4) ********************************
ctg=-7.015253
14.3. Разбиение программы на модули.
Разбиение программы на модули (отдельные файлы с текстом программы) позволяет использовать готовые модули в разных программах, а также является важнейшим способом разделения труда при работе в коллективе.
При таком разбиении в одних модулях должны содержаться функции, а в других - их вызовы. Модули должны быть объединены в единый проект, включающий головной файл (например, Project1) и отдельные модули (например, Unit1 и Unit2).
Существуют разные способы взаимосвязи модулей в проекте. Одни из них основаны на директиве #include (см. ниже тему "Препроцессор"). Другие - на описании extern:
Пример 2. Разбиение программы на модули с использованием класса памяти extern:
|
Основной файл проекта |
Дополнительный файл |
|
int x, y; char str[ ] = "Rezult = "; void fun1(void); void fun2(void); void fun3(void); void main(void){ fun1(); fun2(); fun3(); }
void fun1(void) { y = 15; printf("\n %s %d\n", str, y); } |
extern int x, y; extern char str[ ]; int r = 4;
void fun2(void) { x = y / 5 + r; printf(" %s %d\n", str, x); } void fun3(void) { int z= x + y; printf(" %s %d\n", str, z); }
|
15. Генерация псевдослучайных чисел.
В языке Си есть возможность генерации т.н. псевдослучайных чисел, т.е. чисел, выглядящих для человека как случайные, хотя в действительности вычисляемых по некоторому алгоритму.
К числу функций, обеспечивающих генерацию псевдослучайных чисел, относятся random() и randomize(). Для их работы необходимо подключить заголовочный файл stdlib.h (годятся также и некоторые другие).
Собственно генерацию выполняет функция random. При обращении к ней в скобках надо указать число, задающее диапазон генерируемых чисел (обозначим его N). Результат функции - "случайное" целое число, равновероятно выбранное в диапазоне от 0 до N-1 (таким образом, получается N различных вариантов этого числа).
Если нам нужно случайное целое число в другом диапазоне, то достаточно прибавить к значению random() начало требуемого диапазона, "сдвинув" тем самым результат:
int a,b,x;
...
x=random(b-a+1)+a; // x - случайное число в диапазоне [a..b]
Аналогично можно получать и дробные числа.
Работа функции random() основана на использовании специальной статической ячейки памяти. При запуске программы эта ячейка получат некоторое значение (обычно 0), а затем при каждом обращении к функции random() новое очередное значение в этой ячейке вычисляется из предыдущего по достаточно сложному алгоритму. Исходя из текущего значения этой ячейки, вычисляется сам результат функции random(). Поэтому он не имеет никакой видимой связи с предыдущим ее результатом, что и создает "псевдослучайность" полученных чисел. Однако, при повторном запуске программы начальное значение этой ячейки вновь будет восстановлено, поэтому вся последовательность полученных псевдослучайных чисел повторится.
Если же мы хотим, чтобы последовательность генерируемых чисел различалась при каждом запуске программы, можно воспользоваться функцией randomize(). Она записывает в упомянутую ячейку значение текущего системного времени (с учетом сотых долей секунд, а также даты). Поскольку дата и время запуска программы не могут повториться (тем более - с точностью до сотых долей секунды), после вызова randomize() функция random() будет выдавать уже совершенно новую, практически непредсказуемую последовательность.
Поэтому обращение к randomize() достаточно сделать один раз в начале программы. Не стоит делать это в цикле, т.к. значение системного времени обновляется не более 100 раз в секунду, а цикл может выполниться быстрее, и тогда каждый вызов randomize() запишет в ячейку одно и то же значение, а следующие за ними вызовы random() дадут одинаковые результаты.
Пример программы, заполняющей массив случайными числами от 1 до 100:
int a[40], n, i;
...
randomize();
for (i=0; i<n; i++)
a[i]=random(100)+1;
