
- •Содержание
- •Введение
- •История развития компьютера
- •Типы и назначение компьютеров
- •Классы программного обеспечения (ПО) ЭВМ
- •Операционная система персонального компьютера (ПК)
- •Основы информатики
- •Информационные процессы
- •Информационная деятельность человека
- •Технические средства хранения информации
- •Кодирование информации
- •Системы счисления
- •Представление информации в компьютере
- •Представление текстовых данных
- •Представление изображений
- •Представление звуковой информации
- •Представление видео
- •Введение в программирование на языке Си
- •Этапы решения задачи на ЭВМ
- •Графический способ описания алгоритмов
- •Структура программы на языке С++
- •Описание переменных
- •Функции ввода-вывода
- •Условный оператор
- •Составной оператор
- •Операция условия
- •Оператор выбора
- •Циклические программы
- •Оператор цикла с постусловием
- •Оператор цикла с предусловием
- •Оператор цикла со счетчиком
- •Обработка массивов
- •Обработка одномерных массивов
- •Обработка двумерных массивов
- •Массивы и указатели
- •Пользовательские функции
- •Решение нелинейных уравнений
- •Нелинейные уравнения
- •Исследование уравнений и отделение корней
- •Методы поиска корней уравнения
- •Модификация табличного способа
- •Метод Ньютона (метод касательных)
- •Метод секущих
- •Файлы
- •Файлы данных и каталоги. Внутренняя организация и типы файлов
- •Текстовые файлы
- •Строки символов
- •Заключение
- •Список источников
printf ( «Введите элементы матрицы \n» ); for ( i = 0; i<n; i++ )
for ( j = 0; j<m; j++ ) scanf ( «%d», &a[i][j] );
printf ( «Исходный массив \n» ); for ( i =0; i<n; i++ )
{
for ( j = 0; j<m; j++ ) printf ( «%5d», a[i][j] ); printf ( «\n» );
}
s = 0;
//Сумма элементов главной диагонали for ( i = 0; i<n; i++ )
s = s+a[i][i];
//Замена элементов побочной диагонали for ( i = 0; i<n; i++ )
{
j = n-i-1;
if ( a[i][j]<0 ) a[i][j] = s;
}
printf ( «Полученный массив \n» ); for ( i = 0; i<n; i++ )
{
for ( j = 0; j<m; j++ ) printf ( «%5d», a[i][j] ); printf ( «\n» );
}
getch ();
}
Массивы и указатели
Известно, что данные хранятся в ячейках памяти компьютера. Все ячейки памяти пронумерованы. Номера ячеек памяти называются адресами. Указатели используются для работы с адресами. Указатель - это некоторое символическое представление адреса. Это означает, что будем работать с переменными, хранящими эти адреса. Описываются такие переменные следующим образом:
<тип> *<идентификатор>; Такое описание синтаксически отличается от описания простой
переменной только наличием знака * перед именем переменной. Как видно
93
из описания, указатель всегда связывается с переменной какого-то определенного типа. Это позволяет определить, сколько байт памяти необходимо выделить по указанному адресу. В переменной типа указатель хранится адрес первого байта, выделенного участка памяти:
int *ptr, *ptr1; float *p, *p1;
Над указателями можно выполнять следующие операции [6]:
-Одному указателю можно присвоить значение другого указателя, если они ссылаются на один и тот же тип:
ptr = ptr1; p1 = p;
-Значение указателя можно увеличить или уменьшить на константную величину:
ptr++;
ptr1 = ptr1-5; p1 = p1+2;
На самом деле ptr увеличивается не на 1, а на столько, сколько байт занимает целое число. Переменная ptr1 уменьшается на 5 умноженное на количество байт, выделяемых под целое число.
-Указателю можно присвоить значение адреса. Для получения адреса используется знакомый значок &:
int a, *ptr; ptr = &a;
-Можно использовать операцию косвенной адресации. Эта операция обозначается значком * и позволяет получить доступ к значению переменной, на которую ссылается указатель:
int n = 12, *ptr, a ; ptr = &n;
а = *ptr;
После выполнения этого фрагмента переменная «а» будет иметь значение 12.
-Можно получить разность двух указателей. Это используется чаще всего для указателей, ссылающихся на один и тот же массив.
Здесь следует обратить внимание на то, что символы * и & имеют разное назначение в зависимости от контекста, в котором они используются.
Очень часто в С++ при работе с массивами вместо индексов используются указатели. Преимущество использования указателей в массивах состоит в том, что арифметические операции над указателями выполняются быстрее, если мы работаем с подряд идущими элементами массива. Если выбор элементов случайный, то быстрее и нагляднее работа
синдексами. Имя массива является указателем на первый элемент массива. Элементы массива располагаются в непрерывной области памяти. Эти два
94
положения позволяют перемещаться по элементам массива, используя указатель. Пусть:
int a[10], *ptr; ptr=a;
тогда к пятому элементу массива можно обратиться: a[4]
*(a+4)
*(ptr+4)
и все эти обращения будут равносильны.
Напишем программу из примера pr17 с использованием указателей. //Пример pr17 с указателями
#include <stdio.h> #include <conio.h> #include <stdlib.h> void main()
{ const int N1 = 100; //Максимальный размер массива int a[N1],
*ptr, //Указатель на элементы массива
n, s; //Количество элементов в массиве и их сумма printf ( «\n Введите число элементов массива:» ); scanf ( «%d», &n );
// Формирование массива с помощью датчика случайных чисел randomize ();//Инициализация датчика случайных чисел
for ( ptr = a; ptr-a < n; ptr++ ) *ptr = random (10);
printf ( «Полученный массив: \n» ); for ( ptr = a; ptr-a < n; ptr++ )
printf ( «%5d», *ptr );
s = 0; // Нахождение суммы for ( ptr = a; ptr-a < n; ptr++ ) s = s+*ptr;
printf ( «\n s= %5d», s ); getch ();
}
Начинающие работать с указателями самую большую сложность испытывают при использовании операции косвенной адресации. Например, в заголовке первого же оператора цикла записано prt = a. Это означает, что переменной типа указатель присваивается адрес нулевого элемента массива а. В теле цикла записано *ptr = random(10). В этом случае переменной, хранящейся по адресу, на который указывает ptr, присваивается значение, полученное с датчика случайных чисел. Имя массива a как указатель на нулевой элемент массива является константой,
95
а указатель prt является переменной. Разность prt - a дает порядковый номер элемента массива.
Составим программу с использованием указателей для примера pr18. Исходные данные читаются из файла из файла in.txt (рис. 27), а результат пишется в файл out.txt (рис. 28).
// Пример pr17 с указателями
#include <stdio.h> #include <conio.h> #include <stdlib.h> void main()
{ FILE *in = fopen ("in.txt», «r"); FILE *out = fopen ("out.txt», «w");
const int n1 = 100; //максимальный размер массива int a[n1], *ptr, //указатель на элементы массива n; //Количество элементов в массиве
int p; //Произведение элементов в массиве
int *ptrmax;//Указатель на максимальный элемент fscanf (in, «%d», &n);
for (ptr = a; ptr-a < n; ptr++) fscanf(in, «%d», ptr);
p = 1;
ptrmax = a;//Пусть пеpвый элемент – максимальный for (ptr = a; ptr-a < n; ptr++)
{
//если элемент положительный, то умножаем на него if ( *ptr > 0 ) p = p* *ptr;
//если текущий элемент массива больше //максимального, то запоминаем указатель на него if ( *ptrmax < *ptr) ptrmax = ptr;
}
fprintf(out, «\n максимальный элемент массива
=%d\n», *ptrmax);
*ptrmax = p; // замена максимального произведением fprintf(out, «p = %d\n», p);
fprintf(out, «\nОбpаботанный массив:\n"); for ( ptr = a; ptr-a < n; ptr++ )
fprintf (out, «%5d», *ptr);
}
96