- •Списки §1. Общие сведения о списках
- •§2. Создание списка
- •§3. Просмотр и анализ списка
- •3.1. Просмотр и анализ списка целых чисел.
- •3.2. Просмотр и анализ списка одномерных массивов.
- •§6. Сравнительный анализ списков.
- •§1. Порядок работы с файлом
- •1.1. Потоки и файлы
- •1.2. Объявление файла
- •1.3. Открытие файла.
- •1.4. Закрытие файла.
- •§2. Работа с текстовым файлом
- •2.1. Посимвольная работа с текстовым файлом
- •Int fputc(int ch, file *stream)
- •2.2. Построчная работа с текстовым файлом
- •§3. Функции блокового ввода/вывода
- •3.1. Экономические задачи с использованием файлов
- •3.2. Математические задачи с использованием файлов
- •§4. Прямой (произвольный) доступ к файлу
- •4.1. Функция fseek()
- •4.2. Замена записи. Функции ftell, fgetpos, fsetpos, rewind.
- •Пример. В файл записать координаты точек плоскости. Найти две (любые) точки с наибольшим расстоянием между ними. Массив для хранения координат всех точек не использовать.
- •Упражнения, тесты.
- •Функции (дополнительные возможности)
- •§1. Функции с переменным количеством параметров.
- •§2. Указатели на функции.
- •§3. Массив указателей на функции.
- •§4. Введение в рекурсивные функции.
- •Упражнения, тесты.
- •Void Fun1 (float); void Fun2(float); void Fun3(float);
- •Лабораторная работа № 12.
- •Команды препроцессора (директивы компиляции)
- •§1. Директива define (замены в тексте)
- •Простое макроопределение (макрос)
- •Макрос с аргументами.
- •Директива #undef.
- •§2. Директива #include (включение файлов).
- •§3. Директивы условной компиляции.
- •Директива #if.
- •Директивы #ifdef и #ifndef.
- •Упражнения, тесты
- •История развития технологий программирования
- •§1. Программирование в машинных кодах и на языках символического кодирования
- •§2. Языки высокого уровня. Структурное и модульное программирование
- •§3. Интегрированные системы программирования.
- •§4. История и идеи объектно-ориентированного программирования.
- •§5. Программирование для Windows. Визуальное программирование.
- •Литература
- •Оглавление Предисловие………………………………………………………….…………………3
- •Г л а в а 4. Структуры и другие типы, определяемые пользователем.84
- •Г л а в а 6. Файлы ………………………………………………………..154
- •Г л а в а 7. Функции (дополнительные возможности) ………………190
- •Г л а в а 9. История развития технологий программирования ……220
§3. Просмотр и анализ списка
3.1. Просмотр и анализ списка целых чисел.
За один просмотр выведем на экран и найдём количество отрицательных чисел в списке, созданном в 2.1.
В этом случае в начале списка есть фиктивный элемент. Так как он при просмотре не должен участвовать (фиктивный элемент не выводим и не анализируем), то переходим на второй элемент списка, то есть на первый реальный:
Q=P->next;
Напомним, что в переменной P находится адрес начала списка, то есть в нашем случае для первого списка адрес фиктивного элемента. Заметим, что при работе с обычным одномерным числовым массивом (не полем списка), объявленного, например, так:
const n=10; int a[n];
это соответствует заданию начального значения индекса одномерного массива, например: i=0; .
Как и при работе с одномерным массивом, цикл можно организовать разными способами.
Условие выхода из цикла можно записать так:
while ( Q) …;,
или, что то же самое,
while (Q!=NULL)…;.
Цикл будет выполняться, пока в Q не поместим значение адресного поля последнего “правого” элемента списка, равное NULL, то есть пока не достигнем конца списка. При работе с массивом это частично напоминает оператор цикла while (i<n)…;.
Кроме такого цикла, как и при работе с массивом, можно записать цикл со счётчиком
for (int i=1; i<=n; i++)
где n —количество реальных (без фиктивного) элементов списка (в нашем примере целых чисел). Но в таком случае переменная (или константа) n должна быть объявлена как глобальная или передаваться в функцию просмотра как параметр. Кроме этого, при удалении или вставке элементов n должна быть только переменной и её надо не забыть изменить, сооответсвенно уменьшить или увеличить.
Можно использовать так называемый “вечный” цикл типа while (1), внутри которого записываем условие выхода из него и оператор break.
Внутри цикла используем информационную часть, в примере это одно число, которое обозначается Q->num. Если продолжить сравнение с одномерным массивом, то это чем то напоминает элемент списка a[i]. Для вывода на экран записываем
cout<<Q->num<<" ";.
Здесь же в цикле вместо вывода или вместе с ним может быть анализ одного или нескольких полей информационной части. Например, при работе с нашим списком для нахождения количества отрицательных чисел можно записать:
if (Q->num<0) count1++;
Для более сложного анализа одного числа из списка может понадобиться логическая функция, которая возвращает true или false, в зависимости от того, удовлетворяет ли число некоторому условию (например, является ли оно простым). Такую функцию можно составить и для нашей простой задачи:
bool Analis (int elem) {return elem<0;};
Обратим внимание на то, что из описания функции никак не видно, что она используется для работы с полем списка, то есть в ней нигде не используется ни Q->num, ни
Q->next->num . Это учитывается при вызове, который записываем, например, так:
if (Analis ( Q-> num)) count1++;
Для перехода на следующий элемент списка необходимо выполнить оператор присваивания Q=Q->next;. Синтаксически он правильный, так как адрес элемента списка может находиться как в переменной Q, так и в адресном поле элемента списка (см. 1.1). С помощью этого оператора значение адресного поля (а там находится адрес следующего элемента) заносится в переменную-указатель Q. Если сравнивать с массивом, это равносильно увеличению индекса его элемента на единицу, то есть i++;. Заметим, что этот оператор продвижения по списку не зависит от информационной части его элемента.
Таким образом, с учётом сказанного вывод последовательности чисел первого списка при наличии в нём фиктивного элемента и определение количества отрицательных чисел в этом списке будет выглядеть следующим образом.
bool Analis (int elem) {return elem<0;};
void LOOK (int &count)
{
count=0;
Q=P->next; // Переход на первый реальный элемент списка
while ( Q)
{ cout<<Q->num<<" "; // Вывод информационной части
if (Analis (Q->num)) count++; // Анализ информационной части
Q=Q->next; // Переход на следующий элемент
}
}