САОД. Задание 2
Темы
· указатели и ссылки,
· массивы,
· z-строки,
· передача параметров.
Задания
1. Запустить Visual Studio и создать на рабочем столе проект “ pointer ”. Убедиться, что стоит птичка “Создать каталог для проекта”.
a. Подключить в stdafx.h ввод-вывод.
b. В main ввести код:
int x = 3;
int *p = &x;
cout << x << ' ' << *p << ' ' << p << endl;
c. Убедиться, что х и *p равны 3, а p – адрес x, т.е. *p получили значение.
d. Добавить строчки p++; cout << p << endl;
e. Убедиться, что p++ передвинула адрес на 4 байта (размер целого).
f. Добавить cout << p - &x<< endl;
Убедиться, что результат (разность двух указателей) равен 1 (между ними 1 целое число);
2. Следующее упражнение трудно сделать без указателей. Посмотрим, как целое число размещено в памяти по байтам. Преобразуем тип указателя к byte* и выведем байты в цикле:
typedef unsigned char byte; // Нет встроенного byte
byte *pb = (byte *)--p; // вернули указатель на x и преобразовали
for (byte *pt = pb; pt - pb<sizeof(int); pt++)
cout << (int)*pt << ' '; // выводим как int
cout << endl;
Разобрать текст. Задать вопросы, если что-то непонятно.
Обратите внимание, что целое 3 расположено в памяти не как 0 0 0 3, а как 3 0 0 0. Расположение в памяти зависит от платформы.
3. Самостоятельно. Разработать функцию Swap с использованием указателей.
a. Закомментируйте весь код в main.
b. Объявите две целочисленных переменных int a = 3, b=5; и прямо в main напишите код, который приведет к обмену переменных значениями.
c. Убедитесь, что он работает. До обмена a = 3, b =5, после обмена a = 5, b =3.
d. Добавьте функцию типа
void Swap(int a, int b)
перед main и перенесите в нее код обмена значениями.
e. Вызовите ее в main и убедитесь, что она не работает. Подумайте почему.
Очевидно, что если бы в функцию попали адреса фактических параметров, то задачу бы выполнить удалось.
|
f. Самостоятельно доработайте функцию, чтобы оп-на принимала параметры-указатели void Swap(int *pa, int *pb).
g. Убедитесь, что теперь функция работает. Вызывать конечно нужно, передавая в нее адреса переменных (& a, & b).
h. Вспомните (по лекции) про параметры, которые передаются по ссылке.
Изменяем на void Swap(int &pa, int &pb) и внесите необходимые изменения в ее реализацию и вывод (теперь при вызове указываем только имена переменных, а не адреса).
Убедитесь, что так удобнее и более естественно, а функция работает
ИТОГ:
Теперь стало более понятно, как работают указатели.
4. Переносим функцию Swap в отдельный модуль (utils.cpp и utils.h)
a. Добавляем оба файла в проект;
b. В utils.h переносим прототип функции, а в utils.cpp реализацию;
c. В utils.cpp первой строкой добавляем #include “stdafx.h ” (т.к. проект сконфигурирован на использование прекомпилированных файлов).
d. В основном модуле включаем заголовок “ utils.h ”;
e. Проверяем, что все работает, или добиваемся, чтобы работало.
5. Знакомство с массивами.
a. Создать новый проект arrays. Подключить консольный ввод-вывод;
b. В main объявить массив и вывести его на консоль в одну строку
int a[5]{1,2,3,4,5};
for(int i = 0; i<5; i++)
cout<<a[i] << ' ';
cout<<endl;
c. Вывести массив с помощью указателя на целое:
for (int *p = a; p-a<5; p++)
cout << *p << ' ';
cout << endl;
d. Разберитесь как работает цикл!
6. Передача массива как параметр:
a. Создать функцию, которая выполняет циклическую перестановку массива
void rotate (int a[], int n) { int x = a[0];
for (int i = 1; i < n; i++)
|
a[i - 1] = a[i];
a[n - 1] = x;}
b. Проверить, что функция работает или добиться, чтобы работала!
Обратите внимание, что при передаче в функцию размер массива нужно указывать. Имя массива – это просто указатель на блок памяти и размер его не известен!
c. Реализуйте функцию через указатели без использования целочисленного счетчика i.
7. Z -строки.
a. Создать новый проект strings.
b. Необходимо объявить строку вывести ее на консоль.
Встроенного типа string в C++ нет. Используется массив символов.
char str[] = "Hello!";
cout << str << endl;
c. Вывести на консоль размер массива и длину строки:
cout << strlen(str) << ' ' << sizeof(str) << endl;
Обратите внимание, что они отличаются на 1. Почему это произошло?
d. Создайте дополнительный массив символов и скопируйте в него строку:
char t[32];
for (char *pd = t, *ps = str; *pd++ = *ps++;);
e. Убедитесь, что произошло копирование. Разберитесь с текстом как происходит копирование. Перепишите цикл менее компактно, но более понятно.
f. Вынесите текст в функцию void string_copy(char *d, char*s);
8. Вынесите функцию в utils.
9. Реализуйте самостоятельно функции:
a. int len(const char *s); // Функция возвращает количество символов в строке.
b. int compare(const char *s, const char *t);
Функция должна возвращать целое > 0, если s > t, < 0, если s < t и 0, если s == t;
Если не успеваете, то проделайте эти упражнения дома.
10. Завершайте работу, удалите ненужные файлы, архивируйте решение и сохраняйте на сетевом диске или на флэшке.
ИТОГ:
Теперь мы умеем:
· Объявлять и использовать указатели;
· Передавать параметры по ссылке;
· Объявлять и использовать массивы;
· Работать с z-строками. (сами не будем, есть много стандартных функций, но, в принципе, умеем)
|