- •Основы алгоритмизации и программирования, язык Си
- •Введение
- •Блок-схема алгоритма Общие требования к блок-схеме алгоритма
- •Линейные и разветвляющиеся процессы
- •Циклические процессы
- •Итерационные процессы
- •Комментарии
- •Типы данных
- •Данные целого типа
- •Данные вещественного типа
- •Модификатор const
- •Переменные перечисляемого типа
- •Константы
- •Операции и выражения
- •Операция присваивания
- •Арифметические операции
- •Операции поразрядной арифметики
- •Логические операции
- •Операции отношения
- •Инкрементные и декрементные операции
- •Операция sizeof
- •Порядок выполнения операций
- •Приоритет операций
- •Преобразование типов
- •Операция приведения
- •Операция запятая
- •Ввод и вывод информации
- •Директивы препроцессора Директива #include
- •Директива #define
- •Понятие пустого и составного операторов
- •Условные операторы
- •Операторы организации цикла
- •Оператор цикла for
- •Оператор цикла while
- •Оператор цикла do … while
- •Вложенные циклы
- •Операторы перехода (break, continue, return, goto)
- •Примеры программ
- •Массивы Одномерные массивы
- •Примеры программ
- •Многомерные массивы (матрицы)
- •Примеры программ
- •Указатели Понятие указателя
- •Описание указателей
- •Операции с указателями
- •Связь между указателями и массивами
- •Массивы указателей
- •Многоуровневые указатели
- •Примеры программ
- •Символьные строки
- •Ввод/вывод строк.
- •Функции работы со строками.
- •Примеры программ
- •Функции
- •Прототип функции.
- •Определение функции.
- •Параметры функции
- •Параметры по умолчанию
- •Передача массива в функцию
- •Inline функции
- •Класс памяти
- •Автоматические переменные
- •Статические переменные
- •Регистровые переменные
- •Блочная структура
- •Примеры программ
- •Указатели на функции
- •Примеры программ
- •Рекурсия
- •Примеры программ
- •Аргументы в командной строке
- •Функции с переменным числом параметров
- •Примеры программ
- •Сортировка
- •Пузырьковая сортировка.
- •Шейкер сортировка
- •Сортировка вставкой
- •Сортировка выбором
- •Метод Шелла
- •Метод Хора
- •Структуры
- •Доступ к элементам структуры
- •Инициализация структур
- •Указатели на структуры.
- •Структуры и функции
- •Примеры программ
- •Поля бит
- •Объединения
- •Переменные с изменяемой структурой
- •Примеры программ
- •Организация списков и их обработка
- •Операции со списками при связном хранении
- •Построение обратной польской записи
- •Односвязный линейный список, очередь
- •Двусвязный линейный список
- •Циклический список, кольцо
- •Двусвязный циклический список
- •Примеры программ
- •Деревья
- •Потоки и файлы
- •Файлы Основные сведения о файловой системе
- •Организация посимвольного ввода и вывода
- •Определение конца файла feof()
- •Организация ввода и вывода строк
- •Удаление файлов
- •Дозапись потока
- •Позиционирование в файле
- •Текстовые и двоичные файлы
- •Функции fread() и fwrite()
- •Примеры программ
- •Хеширование
- •Схемы хеширования
- •Метод открытой адресации с линейным опробыванием
- •Метод цепочек
- •Машинное представление графов
- •Примеры программ
- •Литература
Массивы Одномерные массивы
Массивы - объекты структурированного типа данных. Массив представляет собой совокупность элементов одного типа данных. Чтобы создать массив, необходимо компилятору сообщить тип элементов, образующих массив, и требуемый класс памяти. Кроме того, для отведения памяти "под" массив, должно быть известно количество элементов массива. Объявление массива имеет два формата:
[класс памяти] спецификатор_типа описатель [константное_выражение];
[класс памяти] спецификатор_типа описатель [ ];
Описатель - это идентификатор массива.
Спецификатор_типа задает тип элементов объявляемого массива. Элементами массива не могут быть функции и элементы типа void.
Константное_выражение в квадратных скобках задает количество элементов массива. Константное_выражение при объявлении массива может быть опущено в следующих случаях:
- при объявлении массив инициализируется,
- массив объявлен как формальный параметр функции,
- массив объявлен как ссылка на массив, явно определенный в другом файле.
Рассмотрим пример описания массивов:
int mas1[4]={1,2,3,4}; // инициализация внешнего массива
void main()
{ short mas2[3]; // автоматический массив
static float mas3[2]={0,0}; // инициализация статического массива
extern mas1[]; // внешний массив размер указан ранее
}
В рассмотренном фрагменте функции выполнено декларирование массивов трех классов памяти: внешний, статический и автоматический массивы. Основное отличие этих массивов состоит в следующем. Внешний массив должен быть описан (указан тип и размерность) до начала описания основной функции (main() ), и далее при его объявлении указывается ключевое слово extern, за которым следует имя массива, при этом не указывается размерность массива. Внешний массив доступен к использованию в любой из функций. Описание статического и автоматического массивов осуществляется внутри любой функции. Для описания статического массива используется ключевое слово static. Отличие этих массивов состоит в том, что статический массив доступен в любой из функций нижнего уровня по отношению к функции, в которой он объявлен. Автоматический массив доступен лишь в той функции, в которой он объявлен.
Внешние и статические массивы могут быть инициализированы при объявлении. Автоматические и регистровые массивы инициализировать нельзя.
Доступ к элементу массива осуществляется указанием его номера (индекса) в массиве. Например:
mas[3]=4;
k=5;
for(i=0; i<9; i++) mas[i]=mas[i]+k;
Необходимо помнить следующее: индексация элементов массива начинается с номера 0. Число в квадратных скобках в объявлении массива говорит о количестве элементов в массиве, таким образом, максимальный номер элемента будет на 1 меньше их общего числа.
Примеры программ
Рассмотрим некоторые примеры программ, демонстрирующие работу с одномерными массивами.
Пример . В программе вводятся с клавиатуры десять чисел, а затем выводятся на экран в обратном порядке.
#include <stdio.h>
#define n 15
void main()
{ int i;
int mas[n];
printf("Введите %d целых чисел: ",n);
for(i=0; i<n; i++)
scanf(" %d", &mas[i] );
for(i=n-1; i>=0; i--)
printf("%d ", mas[i] );
printf("\n");
}
Пример . Ввести массив чисел и вычислить сумму элементов массива.
#include<stdio.h>
#include <conio.h>
void main( )
{ int m[10],i,s=0;
for(i=0; i<10; i++)
{ scanf("%d",&m[i]); // ввод i-го элемента массива
s += m[i]; // подсчет суммы элементов
}
printf("\nсумма = %d", s);
}
Пример . Ввести массив чисел. За один просмотр массива определить сколько их в какой десяток попадает. Операторы if и switch не использовать. Количество вводимых чисел <=100.
#include <stdio.h>
void main()
{ int a[15], b[10]; int i, k;
for(i=0; i < 15; i++) b[i]=0; // обнуление массива счетчика
for(i=0; i < 15; i++) scanf("%d", &a[i]);
for(i=0; i < 15; i++) b[ a[i] / 10 ]++; //
for(i=0; i < 10; i++)
printf("\nчисел в %d-м десятке: %d", i+1, b[i]);
}
Результат работы программы:
5 10 20 29 50 17 9 22 32 63 3 6 12 28 99
чисел в 1-м десятке: 4
чисел в 2-м десятке: 3
чисел в 3-м десятке: 4
чисел в 4-м десятке: 1
чисел в 5-м десятке: 0
чисел в 6-м десятке: 1
чисел в 7-м десятке: 1
чисел в 8-м десятке: 0
чисел в 9-м десятке: 0
чисел в 10-м десятке: 1
Пример . Ввести массив чисел. Определить k (число k ввести с клавиатуры) максимальных элементов массива и вывести их на экран.
#include <stdio.h>
#define kl 15 // размерность массива
void main()
{ int m[kl], mx[k],i,j,j1,n,n1=0;
printf ("введите массив");
for (i=0;i<kl;i++)
{ printf("m[%d]= ",i);
scanf ("%d",&m[i]);
}
for(i=0;i<k;i++) mx[i]=-1;
for (i=0;i<k;i++) // поиск очередного max значения в m
{ for (j=0;j<kl;j++) // выбор начального максимального элемента
{ for (n=0; mx[n]!=-1 && mx[n]!=j && n<k; n++); // проверка не
// выбран ли он ранее
if (mx[n]==-1) //
{ mx[n]=j; // стартовый индекс для поиска max
break;
}
}
for (j1=j;j1<kl;j1++) // перебор всех следующих за m[j] элементов
{ if(m[j1]>m[ mx[n] ])
{ for (n1=0; mx[n1]!=j1 && n1<n; n1++); // проверка не выбран
// ли j ранее
if(mx[n1]!=j1) mx[n]=j1;
}
}
}
printf ("\n Массив : ");
for (i=0; i<kl; i++) printf ("%3d",m[i]);
printf ("\n найдено % max чисел : ", k);
for (i=0; i<k; i++) printf ("%3d",m[mx[i]]);
}
Пример . Ввести два массива вещественных чисел. Второй массив упорядочен по возрастанию своих значений. Определить, какие числа первого массива содержатся во втором массиве.
#include <stdio.h>
void main()
{ int i, m, l, h;
float arr1[100], arr2[100]; // массивы чисел
int n1,n2; // размеры массивов
do { printf("\n\nВведите размеры массивов: ");
scanf("%d %d",&n1,&n2);
} while( ( n1<0 ) || ( n2<0 ) || ( n1>100 ) || ( n2>100 ) );
printf("\nВведите первый массив: \n");
for( i = 0; i<n1; i++ ) scanf( "%f", &arr1[i] );
printf("\nВведите второй рассортированный массив: \n");
for( i=0; i<n2; i++) scanf( "%f", &arr2[i] );
for( i=0; i<n1; i++ ) // выбор числа из исходного массива err1
{ l=0; h=n2; // l и h –границы поиска числа в массиве err2
while( l < h-1 )
{ m= ( l+h ) / 2; // индекс срединного элемента в массиве err2
if( arr1[i] == arr2[m] )
{ printf("\nЧисло %g входит в оба массива.", arr1[i]);
break;
} // искомый элемент находится
if(a rr1[i] < arr2[m]) h=m; // слева . Сдвиг h влево
else l=m; // справа . Сдвиг l вправо
}
if( arr1[i] != arr2[m] )
printf("\nЧисло %g не входит в массив arr2.", arr1[i] );
}
}
Пример . Ввести первый массив расположив его элементы по убыванию, второй по возрастанию. Не используя сортировок сформировать третий массив по возрастанию. Все массивы целочисленные
#include <stdio.h>
#define n 3
#define m 5
void main()
{ int m1[n],m2[m],m3[n+m],i1,i2,i3;
puts("\nВведите первый массив по возрастанию");
for(i1=0;i1<n;i1++)
{ printf("\nm1[%d]=",i1);
scanf("%d",&m1[i1]);
}
puts("\nВведите второй массив по убыванию");
for(i2=0;i2<m;i2++)
{ printf("\nm2[%d]=",i2);
scanf("%d",&m2[i2]);
}
i1=0; i2=m-1; i3=0;
while(i1<n && i2>=0)
{ while(m1[i1]<=m2[i2] && i1<n)
m3[i3++]=m1[i1++];
if(i1<0) break;
while(m2[i2]<m1[i1] && i2>=0)
m3[i3++]=m2[i2--];
}
while(i1<n) // возможная дозапись остатка
m3[i3++]=m1[i1++]; // первого массива
while(i2>=0) // аналогично для второго массва
m3[i3++]=m2[i2--];
puts("\nРезультирующий массив");
for(i3=0;i3<(n+m);i3++)
printf("%3d",m3[i3]);
}
Пример . Ввести первый массив расположив его элементы по убыванию, второй по возрастанию. Не используя сортировок сформировать третий массив по убыванию. Все массивы целочисленные
#include <stdio.h>
#define n 3
#define m 5
void main()
{ int m1[n], m2[m], m3[n+m], i1, i2, i3;
puts("\nВведите первый массив по возрастанию");
for(i1=0;i1<n;i1++)
{ printf("\nm1[%d]=",i1);
scanf("%d",&m1[i1]);
}
puts("\nВведите второй массив по убыванию");
for(i2=0;i2<m;i2++)
{ printf("\nm2[%d]=",i2);
scanf("%d",&m2[i2]);
}
i1=n-1; i2=0; i3=0;
while(i1>=0 && i2<m)
{ while(m1[i1]>=m2[i2] && i1>=0)
m3[i3++]=m1[i1--];
if(i1<0) break;
while(m2[i2]>m1[i1] && i2<m)
m3[i3++]=m2[i2++];
}
while(i1>=0)
m3[i3++]=m1[i1--];
while(i2<m)
m3[i3++]=m2[i2++];
puts("\nРезультирующий массив");
for(i3=0;i3<(n+m);i3++)
printf("%3d",m3[i3]);
}