Передача массива в функцию

Обработку массивов удобно организовывать с помощью специальных функций. Для обработки массива в качестве аргументов функции необходимо передать

· адрес массива,

· размер массива.

Исключение составляют функции обработки строк, в которые достаточно передать только адрес.

При передаче переменные в качестве аргументов функции данные передаются как копии. Это означает, что если внутри функции произойдет изменение значения параметра, то это никак не повлияет на его значение внутри вызывающей функции.

Если в функцию передается адрес переменной (или адрес массива), то все операции, выполняемые в функции с данными, находящимися в пределах видимости указанного адреса, производятся над оригиналом данных, поэтому исходный массив (или значение переменной) может быть изменено вызываемой функцией.

Пример Дан массив из 10 элементов. Поменять местами наибольший и начальный элементы массива. Для операций поиска максимального элемента и обмена использовать функцию.

#include <stdio.h>

// Функция обмена

void change(int *x, int n) {
// x - указатель на массив (адрес массива)

// n - размер массива

int i;

int max, index;

max = x[0];

index = 0;

// Поиск максимального элемента

for(i=1; i<n; i++)

{

if(x[i]>max)

{

max= x[i];

index = i;

}

}
// Обмен

x[index] = x[0];

x[0] = max;
}
int main() {

int a[10];

int i;

for(i=0; i<10; i++)

{

printf("a[%d] = ", i);

scanf("%d", &a[i]);

}

change(a,10); // вызов функции обмена

// Вывод элементов массива

for(i=0; i<10; i++)

{

printf("%d ", a[i]);

}

getchar();

getchar();

return 0;
}

Результат выполнения

Пример Дан массив размерности n. Вычислить произведение четных элементов

#include <stdio.h>
int func(int *x, int n) { // произведение четных элементов

int p=1; // начальное значение произведения

int i;

for(i=0;i<n; i++) {

if(x[i] % 2==0) // остаток от деления на 2 равен 0?

p = p * x[i];

}

return p;
}
int main() {

int a[5]; // объявлен массив a из 5 элементов

int i;

int pr;

// Ввод элементов массива

for(i=0; i<5; i++) {

printf("a[%d] = ", i);

scanf("%d", &a[i]); // &a[i] - адрес i-го элемента массива

}

pr = func(a, 5); // вычисление произведения

printf("\n pr = %d", pr); // вывод произведения четных элементов

getchar();

getchar();

return 0;
}

Результат выполнения

 

Вопрос 2:Можно ли перегружать конструктор ?Примеры

Перегрузка конструкторов очень схожа с перегрузкой функций. Конструкторов в определяемом классе может быть несколько — по мере необходимости. Они должны иметь одинаковое имя, идентичное имени класса и обязательно должны отличаться сигнатурой. Например: один из конструкторов не принимает параметры, второй принимает два параметра, третий принимает три параметра. Позже, во время создания объекта, параметры передаются в качестве аргументов. Так компилятор сможет определить, какой из объявленных конструкторов применить при создании объекта.

Рассмотрим пример:

Перегруженный конструктор класса в C++

C++

 

#include <iostream> using namespace std;   class _2Data { double data1; double data2; public: _2Data(); _2Data(double initData1, double initData2); void showData(); };   // конструктор класса _2Data с параметрами _2Data::_2Data(double initData1, double initData2) { data1 = initData1; data2 = initData2; cout << "\nСработал конструктор с параметрами.\n"; }   // конструктор класса _2Data без параметров _2Data::_2Data() { data1 = 0; data2 = 0; cout << "\nСработал конструктор без параметров.\n"; }   void _2Data::showData() // метод вывода на экран { cout << "data1 = " << data1 << endl; cout << "data2 = " << data2 << endl << endl; }   int main() { setlocale(LC_ALL, "rus"); // создается объект Obj1 и вызывается конструктор // без параметров. Поля класса инициализируются 0-ми // на экран выводится "Сработал конструктор без параметров." _2Data Obj1; Obj1.showData(); // показываем данные     // создается объект Obj2, вызывается конструктор c параметрами // поля класса инициализируются значениями (переданными аргументами) // на экран выводится "Сработал конструктор с параметрами." _2Data Obj2(222, 333); Obj2.showData(); // смотрим значения }

На этом примере достаточно легко увидеть, чем вызвана необходимость перегрузки конструкторов. Основной смысл в том, чтобы дать возможность программисту выбрать наиболее подходящий способ инициализации объекта.

Тут представлен самый распространенный вариант перегрузки конструкторов. А именно конструктор с параметрами и второй без параметров. Часто, программисту бывают необходимы оба подобных конструктора, так как конструктор с параметрами удобно использовать, работая с одиночными объектами. Но он не может быть использован, например, для инициализации динамического массива объектов класса.

При каждом объявлении объекта класса надо применять соответствующий определённым конструкторам способ объявления.

Конструктор можно перегружать столько раз, сколько посчитаете нужным. Но, как бывает у большинстве случаев, желательно придерживаться золотой середины. Перегружайте его только для наиболее распространенных ситуаций.

Хочется добавить, что деструктор, в отличии от конструктора, перегружен быть не может, так как он никаких параметров не принимает.

 

Билет 9:

Вопрос 1:Как работать со строками в языке C.Пример.

Строка – это последовательность ASCII или UNICODE символов. Строки в си, как и в большинстве языков программирования высокого уровня рассматриваются как отдельный тип, входящий в систему базовых типов языка. Так как язык СИ по своему происхождению является языком системного программирования, то строковый тип данных в нем как таковой отсутствует, а в качестве строк в си используются обычные массивы символов.
Исторически сложилось два представления формата строк:
1. формат ANSI;
2. строки с завершающим нулем (используется в СИ).

Формат ANSI устанавливает, что значением первой позиции в строке является ее длина, а затем следуют сами символы строки. Например, представление строки "Моя строка!" будет следующим:
11 ‘М’ ‘о’ ‘я’ ‘ ’ ‘с’ ‘т’ ‘р’ ‘о’ ‘к’ ‘а’ ‘!’
В строках с завершающим нулем, значащие символы строки указываются с первой позиции, а признаком завершения строки является значение ноль. Представление рассмотренной ранее строки в этом формате имеет вид:
‘М’ ‘о’ ‘я’ ‘ ’ ‘с’ ‘т’ ‘р’ ‘о’ ‘к’ ‘а’ ‘!’ 0

Работа со строками в СИ:

Так как строки на языке СИ являются массивами символов, то к любому символу строки можно обратиться по его индексу. Для этого используется синтаксис обращения к элементу массива, поэтому первый символ в строке имеет индекс ноль. Например, в следующем фрагменте программы в строке str осуществляется замена всех символов ‘a’ на символы ‘A’ и наоборот.
for(int i=0;str[i]!=0;i++)
{
if(str[i] == ‘a’) str[i] = ‘A’;
else if(str[i] == ‘A’) str[i] = ‘a’;
}

Функции для работы со строками в СИ


Все библиотечные функции, предназначенные для работы со строками, можно разделить на три группы:
1. ввод и вывод строк;
2. преобразование строк;
3. обработка строк.

Вопрос 2:Связь между объединёнными и классами в C++.Ограничения

Точно так же, как структуры и классы связаны между собой, связаны и объединения и классы. Объединения представляют по существу структуру, в которой все элементы хранятся в одном и том же месте. Объединения могут содержать конструкторы и деструкторы, а также функции-члены и дружественные функции. Подобно структурам, члены объединения по умолчанию имеют в качестве спецификатора доступа public. Например, следующая программа использует объедине­ние для вывода символов, соответствующих старшему и младшему байтам короткого целого (име­ющего размер в два байта как для 16-битных, так и для 32-битных сред):

#include <iostream.h>
union u_type {
u_type(short int a); // по умолчанию публичные
void showchars ();
short int i;
char ch[2];
};
// конструктор
u_type::u_type(short int a)
{
i = a;
}
// показ символов, которые содержит short int.
void u_type::showchars()
cout << ch [ 0 ] << " ";
cout << ch [ 1 ] << "\n";
int main()
u_type u(1000);
u.showchars ();
return 0;
}

Важно понимать, что подобно структуре, объявление объединения определяет тип класса. Это означает, что принципы инкапсуляции сохраняют свою силу.

Имеется несколько ограничений, которые необходимо иметь в виду при использовании объе­динений в С++. Первое — объединение не может наследовать какие-либо другие классы. Далее объединение не может использоваться в качестве базового класса. Объединение не может иметь виртуальные функции-члены. Никакие статичес­кие переменные не могут быть членами объединения. Объединение не может иметь в качестве члена какой-либо объект, перегружающий оператор =. Наконец, никакой объект не может быть членом объединения, если этот объект имеет конструктор или деструктор.

 

Билет 10:

Вопрос 1:Структура языкат C.Примеры:

Программа на языке Си состоит из одной или более подпрограмм, называемых функциями.

Язык Си является блочно-структурированным. Каждый блок заключается в фигурные скобки {}.

Основным блоком в программе консольного приложения на языке Си является главная функция, имеющая имя main().

Каждое действие в языке Си заканчивается символом "точка с запятой" - ;. В качестве действия может выступать вызов функции или осуществление некоторых операций.

Имя функции — это коллективное имя группы описаний и операторов,
заключенных в блок (фигурные скобки). За именем функции в круглых скобках указываются параметры функции.

Комментарии в языке Си

В языке Си для комментариев используются символы