- •Т.Э. Шульга основы программирования на языке с
- •Введение
- •1. Структура программы на языке с
- •Void main()
- •Задание 1. Вывод строки на экран с использованием esp-последовательности
- •2. Переменные. Основные типы данных
- •Задание 2. Описание переменных и преобразование типов
- •3. Ввод – вывод значений переменных
- •Void main()
- •Void main()
- •Задание 3. Форматирование вывода
- •4. Основные операции языка с
- •Void main ()
- •Заданиe 4. Простейшие вычисления
- •5. Конструкции выбора
- •Void main()
- •Void main()
- •Void main()
- •Задание 5. Обработка введенного символа
- •Задание 6. Вычисление значения функции
- •Задание 7. Применение разветвляющихся алгоритмов при решении простейших задач
- •Задание 8. Mультиветвление
- •6. Конструкции цикла и передачи управления
- •Int *t; // неинициализированный указатель на объект типа int,
- •Void main()
- •Int a2[3][2]; // массив из 3 массивов, содержащих по 2 целых элемента.
- •Задание 9. Детерминированные циклы. Простейшие задачи
- •Void main()
- •Задание 10. Итерационные циклы. Простейшие задачи
- •Void main()
- •Int last;
- •Задание 11. Одномерные массивы
- •Void main()
- •Задание 12. Вложенные циклы
- •Void main ()
- •Задание 13. Двумерные массивы
- •Void main ()
- •Задание 14. Посимвольная обработка строк
- •Void main ()
- •Задание 15. Сортировка массива
- •Void main ()
- •7.Функции
- •Int max (int n, int m ) // определение функции нахождения максимума
- •Void main()
- •Int strcmp(const char *str1, const char* str2);
- •Void main()
- •Int fclose (file * stream);
- •Int feof(file *stream);
- •Int fseek ( file* stream, long offset, int origin);
- •Void main ()
- •Задание 16. Определение и вызов функций
- •Задание 17. Рекурсивные функции
- •Задание 18. Использование библиотечных функций string.H
- •Задание 19. Использование библиотечных функций stdio.H
Int *t; // неинициализированный указатель на объект типа int,
//то есть в переменной T может храниться адрес объекта типа int;
В качестве инициализирующего выражения указателя может использоваться константное выражение, частными случаями которого являются явно заданный адрес участка памяти, указатель, уже имеющий значение, выражение, позволяющее получить адрес объекта с помощью операции ‘&’. Например,
char c1 = ‘a’;
char* p = &c1;// в p хранится адрес переменной c1
Переменная, на которую указывает p, это c1, а значение, которое хранится в c1, это символ ‘a’. Основная операция над указателем – разыменование, унарная операция ‘*’ (получение значения через указатель). Эта операция также называется косвенным обращением или обращением по адресу. Например, при выполнении оператора printf(“%c”, *p); на экран выведется значение того участка памяти, с которым связан указатель p, то есть символ ‘a’.
Имя массива является указателем–константой на его первый элемент. То есть, если описан массив int a [n], то для обращения к его i–ому элементу наряду с записью a[i], можно использовать запись *(a+i).
Например, пусть описан и инициализирован массив a.
const int n=5;
int a[n]={1,2,3,4,5};
Выведем его элементы на экран столбиком тремя способами:
int *p=a; for (int i=0;i<n;i++ ) printf("%d%s",*p++, "\n");
for (int i=0;i<n;i++ ) printf("%d%s",*(a+i), "\n");
for (int i=0;i<n;i++ ) printf("%d%s", a[i], "\n");
Чтобы связать указатель с новым участком памяти, еще не занятым никаким объектом программы, используют функцию malloc (n) из библиотеки stdlib.h, где n – количество выделяемых байт. Функция malloc возвращает укатель на void, потому при присваивании ее результат необходимо преобразовать в указатель на нужный тип данных. Например,
char *p= (char*)malloc(sizeof(char)); //выделили память для перемененной типа
// char и связали указатель p с эти участком памяти;
Объекты, созданные таким образом (динамические объекты), требуют явного уничтожения с помощью функции free(t) из библиотеки stdlib.h (), где t- имя указателя из-под которого осбождается память, например
free(p);
Функция malloc позволяет определять массив еще одним способом:
int k;
scanf(“%d”,&k);
int *a=(int *)malloc(k*sizeof(int));
Этот способ целесообразно использовать, если размерность массива не может быть описана как константа. Однако в данном случае необходимо удалить описанный динамический массив после использования с помощью функции free(а) , иначе память, выделенная под него останется занятой до перезагрузки операционной системы. Обращаться к элементам динамического массива можно всеми перечисленными выше способами.
Специальным образом в языке С обрабатываются массивы, называемые С–строками. С–строка – это массив символов, последний из которых символ ‘\0’. Дело в том, что в С нет специального типа данных для описания строк, но есть библиотека функций языка С для работы С–строками (описанная в заголовочном файле string.h, см.задание 15),которые обеспечивают различные операции для манипулирования строками. В этой главе мы рассмотрим работу, используя обычный принцип обработки символов как элементов массива.
При инициализации массив символов можетзадаваться как последовательность символов, заключенная в двойные кавычки: “...”. Компилятор располагает в конце каждой строки нулевой (пустой) байт, обозначемыesc-последовательностью ‘\0’, с тем, чтобы сканирующая строку программа могла найти ее конец. Например,
char str1[]= “abcd”; // действительная длина этой строки равна 5
char * str2= “abcd”; // действительная длина этой строки равна 5
Кроме того, инициализация строк может быть выполнена следующим образом:
char str3[]={‘a’, ‘b’, ‘c’, ‘d’, ‘\0’};
При такой инициализации списком, а также при посимвольном заполнении неинициализированного массива в цикле в конце символьного массива следует явным образом задать символ конца строки ‘\0’. Только при этом массив получает свойства С–строки, которые можно использовать, например, в библиотечных функциях для работы со строками или при вводе и выводе строки. Например, С–строку str3 в отличии от любого несимвольного массива можно вывести на экран не в цикле, а с помощью с помощью одного оператораprintf(“%s”,str2). А неинициализированный массивcharstr4[20], в отличии от любого несимвольного можно заполнить одним операторомscanf(“%s”, str3); Однако, как отмечено в главе 2, при применении функцииscanfклавиатуры считаются в массив str3 все символы только до первого пробела. Чтобы считать строку целиком, можно использовать функцию
gets (указатель_на_строку),
описанную в заголовочном файле stdio.h. Например,
char s1[10]; gets(s1);
char * s2 = (char *)malloc(m); scanf(“%s”, str3);
Строка s1 – это массив с константой размерностью 10, элементы которого считываются с клавиатуры с помощью функции gets. Строка s2 – это динамический массив из m элементов, в который считается только m–4 символов (m–3–ий элемент будет равен ‘\0’). Причем второй способ считывания строки предпочтительнее, чем первый, так как функция gets не накладывает ограничения на число считываемых с клавиатуры символов, а это значит, что массив s1 может переполниться.
Пример. Определить длину строки, введенной с клавиатуры, не использую библиотечных функций.
# include <stdio.h>