Локальные и глобальные переменные
· Переменные, которые используются внутри данной функции, называются локальными. Память для них выделяется в стеке, поэтому после окончания работы функции они удаляются из памяти. Нельзя возвращать указатель на локальную переменную, т. к. память, выделенная такой переменной, будет освобождаться.
· Глобальные переменные – это переменные, описанные вне функций. Они видны во всех функциях, где нет локальных переменных с такими именами.
Передача одномерных массивов как параметров функции
При использовании массива как параметра функции, в функцию передается указатель на его первый элемент, т. е. массив всегда передается по адресу. При этом теряется информация о количестве элементов в массиве, поэтому размерность массива следует передавать как отдельный параметр.
void print(int a[100],int n) //вывод массива на печать
{
for(int i=0;i<n;i++)
cout<<a[i]<<" ";
cout<<"\n";
}
Так как в функцию передается указатель на начало массива (передача по адресу), то массив может быть изменен за счет операторов тела функции.
Передача строк в качестве параметров функций
Строка в Си++ - это массив символов, заканчивающийся нуль-символом – ‘\0’ (нуль-терминатором). По положению нуль-терминатора определяется фактическая длина строки. Количество элементов в таком массиве на 1 больше, чем изображение строки.
Для работы со строками существуют специальные библиотечные функции, которые содержатся в заголовочном файле string.h.
Строки при передаче в функции могут передаваться как одномерные массивы типа char или как указатели типа char*. В отличие от обычных массивов в функции не указывается длина строки, т. к. в конце строки есть признак конца строки /0.
//Функция поиска заданного символа в строке
int find(char *s,char c)
{
for (int I=0;I<strlen(s);I++)
if(s[I]==c) return I;
return –1
}
Передача многомерных массивов в функцию
Многомерный массив – это массив, элементами которого служат массивы. Например, массив int a[4][5] – это массив из указателей int*, которые содержат имена одноименных массивов из 5 целых элементов:
Рис. Выделение памяти под массив, элементами которого являются массивы.
При передаче многомерных массивов в функцию все размерности должны передаваться в качестве параметров.
const int N=4;//глобальная переменная
void transp(int a[][N],int n)// транспонирование матрицы
{
int r;
for(int I=0;I<n;I++)
for(int j=0;j<n;j++)
if(I<j)
{
r[a[I][j];
a[I][j]=a[j][I];
a[j][I]=r;
}
}
Строки
Строка в C++ – это массив символов, заканчивающийся нуль-символом – ’\0’ (нуль-терминатором). По положению нуль-терминатора определяется фактическая длина строки. Количество элементов в таком массиве на 1 больше, чем изображение строки.
A | \0 | A | |
”A” строка (2 байта) | ’A’ символ (1 байт) |
Рис. 4. Представление строки и символа
Присвоить значение строке с помощью оператора присваивания нельзя. Поместить строку в массив можно либо при вводе, либо с помощью инициализации.
char s1[10]="string1";//инициализация
char s2[]="string2";//инициализация
char s3[10];
cin>>s3;//ввод
//выделение памяти под динамическую строку
char *s4=new char[strlen(s3)+1];
strcpy(s4,s3);//копирование строки s3 в строку s4
Для работы со строками существуют специальные библиотечные функции, которые содержатся в заголовочном файле string.h.
Прототип функции | Краткое описание | Примечание |
unsigned strlen(const char* s); | Вычисляет длину строки s. | |
int strcmp(const char* s1, const char* s2); | Сравнивает строки s1 и s2. | Если s1<s2, то результат отрицательный, если s1==s2, то результат равен 0, если s2>s1 – результат положительный. |
int strcnmp(const char* s1, const char* s2); | Сравнивает первые n символов строк s1 и s2. | Если s1<s2, то результат отрицательный, если s1==s2, то результат равен 0, если s2>s1 – результат положительный. |
char* strcpy(char* s1, const char* s2); | Копирует символы строки s1 в строку s2. | |
char* strncpy(char* s1, const char* s2, int n); | Копирует n символов строки s1 в строку s2. | Конец строки отбрасывается или дополняется пробелами. |
char* strcat(char* s1, const char* s2); | Приписывает строку s2 к строке s1 | |
char* strncat(char* s1, const char* s2); | Приписывает первые n символов строки s2 к строке s1 | |
char* strdup(const char* s); | Выделяет память и переносит в нее копию строки s | При выделении памяти используются функции |
Строки при передаче в функции могут передаваться как одномерные массивы типа char или как указатели типа char*. В отличие от обычных массивов в функции не указывается длина строки, т. к. в конце строки есть признак конца строки \0.
Постановка задачи
1. Используя функции сформировать с помощью ДСЧ одномерный массив и вывести его на печать.
2. Выполнить обработку одномерного массива в соответствии с вариантом, используя функции, результат вывести на печать.
3. Используя функции сформировать с помощью ДСЧ двумерный массив и вывести его на печать.
4. Выполнить обработку двумерного массива в соответствии с вариантом, используя функции, результат вывести на печать.
5. Ввести с клавиатуры строку символов и обработать ее в соответствии со своим вариантом, используя функции.
Варианты
Вариант | Одномерный массив | Двумерный массив | Строки |
Отсортировать по возрастанию только четные элементы массива. | Перевернуть все четные строки матрицы. | Удалить все гласные буквы из строки. | |
Удалить из массива все четные элементы. | Перевернуть все четные столбцы матрицы. | Подсчитать количество слов в строке. | |
Найти количество простых чисел в массиве. | Перевернуть все нечетные строки матрицы. | Перевернуть каждое четное слово в строке. | |
Найти количество чисел Фибоначчи в массиве. | Перевернуть все нечетные столбцы матрицы. | Удалить каждое четное слово из строки. | |
Удалить все простые числа из массива. | Отсортировать по убыванию все строки матрицы. | Отсортировать слова в строке в лексикографическом порядке (по алфавиту). | |
Удалить из массива все числа Фибоначчи. | Отсортировать по убыванию столбцы матрицы. | Удалить из строки все слова, начинающиеся на гласную букву. | |
Отсортировать по возрастанию только положительные элементы массива. | Меняя местами строки матрицы, отсортировать по возрастанию ее первый столбец. | Удалить из строки все слова, заканчивающиеся на гласную букву. | |
Удалить из массива все элементы с четными номерами. | Меняя местами столбцы матрицы, отсортировать по возрастанию ее первую строку. | Удалить все гласные буквы из строки. | |
Отсортировать по возрастанию только те элементы массива, которые являются простыми числами. | Все четные строки матрицы сдвинуть циклически на К элементов вправо. | Подсчитать количество слов в строке. | |
Удалить из массива все элементы равные min(a[1],a[3],…a[2n-1]). | Все нечетные строки матрицы сдвинуть циклически на К элементов влево. | Перевернуть каждое четное слово в строке. | |
Создать новый массив из номеров элементов, значения которых равны 0. | Перевернуть все четные строки матрицы. | Удалить каждое четное слово из строки. | |
Сформировать массив, в котором будут только элементы исходного массива, заканчивающиеся на цифру К. | Перевернуть все четные столбцы матрицы. | Отсортировать слова в строке в лексикографическом порядке (по алфавиту). | |
Отсортировать по возрастанию только четные элементы массива. | Перевернуть все нечетные строки матрицы. | Удалить из строки все слова, начинающиеся на гласную букву. | |
Удалить из массива все четные элементы. | Перевернуть все нечетные столбцы матрицы. | Удалить из строки все слова, заканчивающиеся на гласную букву. | |
Найти количество простых чисел в массиве. | Отсортировать по убыванию все строки матрицы. | Удалить все гласные буквы из строки. | |
Найти количество чисел Фибоначчи в массиве. | Отсортировать по убыванию все столбцы матрицы. | Подсчитать количество слов в строке. | |
Удалить все простые числа из массива. | Меняя местами строки матрицы, отсортировать по возрастанию ее первый столбец. | Перевернуть каждое четное слово в строке. | |
Удалить из массива все числа Фибоначчи. | Меняя местами столбцы матрицы, отсортировать по возрастанию ее первую строку. | Удалить каждое четное слово из строки. | |
Отсортировать по возрастанию только положительные элементы массива. | Все четные строки матрицы сдвинуть циклически на К элементов вправо. | Отсортировать слова в строке в лексикографическом порядке (по алфавиту). | |
Удалить из массива все элементы с четными номерами. | Все нечетные строки матрицы сдвинуть циклически на К элементов влево. | Удалить из строки все слова, начинающиеся на гласную букву. | |
Отсортировать по возрастанию только те элементы массива, которые являются простыми числами. | Перевернуть все четные строки матрицы. | Удалить из строки все слова, заканчивающиеся на гласную букву. | |
Удалить из массива все элементы равные min(a[1],a[3],…a[2n-1]). | Перевернуть все четные столбцы матрицы. | Удалить все гласные буквы из строки. | |
Создать новый массив из номеров элементов, значения которых равны 0. | Перевернуть все нечетные строки матрицы. | Подсчитать количество слов в строке. | |
Сформировать массив, в котором будут только элементы исходного массива, заканчивающиеся на цифру К. | Перевернуть все нечетные столбцы матрицы. | Перевернуть каждое четное слово в строке. | |
Сформировать два массива. В первый массив включить элементы из исходного массива с четными номерами, а во второй с нечетными. | Отсортировать по убыванию все строки матрицы. | Удалить каждое четное слово из строки. |
Методические указания
1. Формирование, печать и обработку массивов и строк оформить в виде функции. Массивы передавать как параметры функций.
2. Реализовать массивы как псевдодинамические, их размерности передавать как параметры функций.
3. Формирование массивов выполнить с использованием ДСЧ. В массивы записывать и положительные, и отрицательные числа.
4. Ввод/вывод строк организовать с помощью функций:
· char* gets(char*s)
· int puts(char *s)
5. Для обработки строк использовать стандартные функции из библиотечного файла <string.h>
6. Сортировку массивов организовать с помощью одного из простых методов сортировки, рассмотренных в лабораторной работе №3.
7. Функция main() должна содержать только описание массивов/строк и вызовы функций для формирования, печати и обработки массивов/строк.
Содержание отчета
1. Постановка задачи (общая и для конкретного варианта).
2. Определения функций, используемых для формирования, печати и обработки массивов/строк (для каждой задачи).
3. Определение функции main().
4. Результаты тестов.
Лабораторная работа №5
Динамические массивы
1. Цель работы:
1. Получить практические навыки выделения, перераспределения и освобождение памяти при работе с динамическими массивами
Теоретические сведения
Для работы с динамической памятью используют указатели. С их помощью осуществляется доступ к участкам динамической памяти, которые называются динамическими переменными. Динамические переменные создаются с помощью специальных функций и операций. Они существуют либо до конца работы программ, либо до тех пор, пока не будут уничтожены с помощью специальных функций или операций.
Для создания динамических переменных используют операцию new, определенную в C++:
указатель = new имя_типа[инициализатор];
где инициализатор – выражение в круглых скобках.
Операция new позволяет выделить и сделать доступным участок динамической памяти, который соответствует заданному типу данных. Если задан инициализатор, то в этот участок будет занесено значение, указанное в инициализаторе.
int* x=new int(5);
Для удаления динамических переменных используется операция delete, определенная в C++:
delete указатель;
где указатель содержит адрес участка памяти, ранее выделенный с помощью операции new.
delete x;
Операция new при использовании с массивами имеет следующий формат:
new тип_массива
Такая операция выделяет для размещения массива участок динамической памяти соответствующего размера, но не позволяет инициализировать элементы массива. Операция new возвращает указатель, значением которого служит адрес первого элемента массива. При выделении динамической памяти размеры массива должны быть полностью определены.
//выделение динамической памяти 100*sizeof(int) байт
int* a = new int[100];
При формирование матрицы сначала выделяется память для массива указателей на одномерные массивы, а затем в цикле с параметром выделяется память под n одномерных массивов.
/*выделение динамической памяти под двумерный динамический массив*/
int** form_matr(int n,int m)
{
int **matr=new int*[n];//выделение памяти по массив указателей
for(int i=0;i<n;i++)
//выделение памяти 100*sizeof(int) байт для массива значений
matr[i]=new int [m];
return matr;//возвращаем указатель на массив указателей
}
*matr[0] | *matr[1] | *matr[2] | ….. | *matr[n] |
Рис. Выделение памяти под двумерный массив
Изменять значение указателя на динамический массив надо аккуратно, т. к. этот указатель затем используется при освобождении памяти с помощью операции delete.
/*освобождает память, выделенную под массив, если а адресует его начало*/
delete[] a;
Удаление из динамической памяти двумерного массива осуществляется в порядке обратном его созданию, т. е. сначала освобождается память, выделенная под одномерные массивы с данными, а затем память, выделенная под одномерный массив указателей.
int find(int **matr,int m,int I)
{
for(int i=0;i<m;i++)
if(matr[I][i]<0) return 1;
return 0;
}
При удалении из динамической матрицы строк или столбцов создается новая матрица нужного размера, в которую переписываются данные из старой матрицы. Затем старая матрица удаляется.
int **del(int **matr,int &n,int m)
{//удаление четных строк
int k=0,t=0;
for(int i=0;i<n;i++)
if(i % 2!=0)k++;//количество нечетных строк
//выделяем память под новую матрицу
int **matr2=form_matr(k,m);
for(i=0;i<n;i++)
if(i % 2!=0)
{
//если строка нечетная, то переписываем ее в новую матрицу
for(int j=0;j<m;j++)
matr2[t][j]=matr[i][j];
t++;
}
n=t;//изменяем количество строк
//возвращаем указатель на новую матрицу как результат функции
return matr2;
}
Постановка задачи
1. Сформировать динамический одномерный массив, заполнить его случайными числами и вывести на печать.
2. Выполнить указанное в варианте задание и вывести полученный массив на печать.
3. Сформировать динамический двумерный массив, заполнить его случайными числами и вывести на печать.
4. Выполнить указанное в варианте задание и вывести полученный массив на печать.
Варианты
№ варианта | Одномерный массив | Двумерный массив |
Удалить первый четный элемент | Добавить строку с заданным номером | |
Удалить первый отрицательный элемент | Добавить столбец с заданным номером | |
Удалить элемент с заданным ключом (значением) | Добавить строку в конец матрицы | |
Удалить элемент равный среднему арифметическому элементов массива | Добавить столбец в конец матрицы | |
Удалить элемент с заданным номером | Добавить строку в начало матрицы | |
Удалить N элементов, начиная с номера K | Добавить столбец в начало матрицы | |
Удалить все четные элементы | Добавить К строк в конец матрицы | |
Удалить все элементы с четными индексами | Добавить К столбцов в конец матрицы | |
Удалить все нечетные элементы | Добавить К строк в начало матрицы | |
Удалить все элементы с нечетными индексами | Добавить К столбцов в начало матрицы | |
Добавить элемент в начало массива | Удалить строку с номером К | |
Добавить элемент в конец массива | Удалить столбец с номером К | |
Добавить К элементов в начало массива | Удалить строки, начиная со строки К1 и до строки К2 | |
Добавить К элементов в конец массива | Удалить столбцы, начиная со столбца К1 и до столбца К2 | |
Добавить К элементов, начиная с номера N | Удалить все четные строки | |
Добавить после каждого отрицательного элемента его модуль | Удалить все четные столбцы | |
Добавить после каждого четного элемента элемент со значением 0 | Удалить все строки, в которых есть хотя бы один нулевой элемент | |
Добавить по К элементов в начало и в конец массива | Удалить все столбцы, в которых есть хотя бы один нулевой элемент | |
Добавить элемент с номером К | Удалить строку, в которой находится наибольший элемент матрицы | |
Удалить элемент с заданным номером | Добавить строки после каждой четной строки матрицы | |
Удалить N элементов, начиная с номера K | Добавить столбцы после каждого четного столбца матрицы | |
Удалить все четные элементы | Добавить К строк, начиная со строки с номером N | |
Удалить все элементы с четными индексами | Добавить К столбцов, начиная со столбца с номером N | |
Удалить все нечетные элементы | Добавить строку после строки, содержащей наибольший элемент | |
Удалить все элементы с нечетными индексами | Добавить столбец после столбца, содержащего наибольший элемент |
Методические указания
1. Для выделения памяти под массивы использовать операцию new, для удаления массивов из памяти – операцию delete.
2. Для выделения памяти, заполнения массивов, удаления и добавления элементов (строк, столбцов) написать отдельные функции. В функции main() должны быть размещены только описания переменных и обращения к соответствующим функциям:
int main()
{
int n;
cout<<"N?";cin>>n;
person*mas=form_mas(n);
init_mas(mas,n);
print_mas(mas,n);
return 1;
}
3. Для реализации интерфейса использовать текстовое меню:
….
do
{
cout<<”1. Формирование массива\n”;
cout<<”2. Печать массива\n”;
cout<<”3. Удаление из массива\n”;
cout<<”4. Добавление в массив\n”;
cout<<”5. Выход\n”;
cin>>k;
switch (k)
{
case 1: mas=form_mas(SIZE);input_mas(mas,SIZE); break;//выделение памяти и заполнение
case 2: print_mas(mas,SIZE); break;//печать
case 3: del_mas(mas,SIZE);break;//удаление
case 4: add_mas(mas,SIZE);break;//добавление
}
while (k!=5);//выход
4. При удалении элементов (строк, столбцов) предусмотреть ошибочные ситуации, т. е. ситуации, в которых будет выполняться попытка удаления элемента (строки, столбца) из пустого массива или количество удаляемых элементов будет превышать количество имеющихся элементов (строк, столбцов). В этом случае должно быть выведено сообщение об ошибке.
Содержание отчета
1. Постановка задачи (общая и для конкретного варианта).
2. Определения функций для реализации поставленных задач.
3. Определение функции main().
4. Тесты
Лабораторная работа №6