Сдам Сам

ПОЛЕЗНОЕ


КАТЕГОРИИ







Передача многомерных массивов как параметров





При передаче многомерных массивов как параметров все размерности, если они не известны на этапе компиляции, должны передаваться в качестве параметров. Внутри функции массив интерпретируется как одномерный. Поэтому при передаче двумерных массивов обязательно нужно указывать количество столбцов в массиве (то есть размер строки), так как в С++ массивы хранятся по строкам. Чтобы можно было правильно определить адреса элементов матрицы по их координатам, используя адрес первого элемента с координатами [0][0], нужно знать количество элементов в строке - т.е. количество столбцов. Число строк указывать необязательно.

В списке формальных параметров для двумерных массивов указывается тип элементов массива, имя массива, квадратные скобки для строк и квадратные скобки с количеством столбцов:

тип_элементов имя_параметра-матрицы[][количество_столбцов];

Пример 1.

С помощью датчика случайных чисел сформировать целочисленные матрицы A[5][8], B[6][9]. Найти минимальные элементы каждой матрицы. Вывести на экран матрицы и минимальные элементы матриц.

#include <stdio.h>

#include <stdlib.h> // Необходимо подключение этой библиотеки для использования

// датчика случайных чисел

void create_matric(int x[][9], int n, int m) // Указываем максимально возможное

// количество столбцов - 9

{ int i,j;

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

for (j=0; j<m; j++)

x[i][j]=random(10)-5;

}

void print_matric(int x[][9], int n, int m)

{ int i,j;

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

{ for (j=0;j<m;j++) printf(“%6d “,x[i][j]); printf(“\n”); }

}

int min(int x[][9], int n, int m)

{ int i,j, min;

min=x[0][0];

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

for (j=0;j<m;j++) if (x[i][j]<min) min=x[i][j];

return min;

}

int main()

{ int A[5][9], B[6][9], minA,minB;

void create_matric(int [][9], int, int);

void print_matric(int [][9], int, int);

int min(int [][9], int, int);

randomize();

create_matric(A,5,8); printf(“Матрица A\n”); print_matric(A,5,8);

minA=min(A,5,8); printf(“minA=%d\n”,minA);

create_matric(B,6,9); printf(“Матрица B\n”); print_matric(B,6,9);

minB=min(B,6,9); printf(“minB=%d\n”,minB);

return 0;

}

Использование указателей при работе с функциями

Указатель на функцию содержит адрес в сегменте кода, по которому располагается исполняемый код функции, то есть адрес, по которому передается управление при вызове функции. Объявление указателя на функцию имеет формат:

тип (*имя_указателя)(тип_параметра, тип_параметра,…)

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

int (*pfunc)(int, float);

Инициализировать указатель на функцию можно с помощью имени функции, которое трактуется как адрес:

int func(int a){ …} // Определение функции func()

int (*pfunc)(int); // Объявление указателя на функцию

pfunc=func; // Присваивание адреса функции

Пример 1. Создать функцию, печатающую приветствие. Вызов ее осуществить через указатель.

#include <stdio.h>

int func(char *msg)

{ return printf(msg);

}

int main()

{

int (*pfunc)(char*); // Объявление указателя на функцию

pfunc=func; // Инициализация указателя

(*pfunc)(“HELLO!\n”); // Вызов функции через указатель

return 0;

}

Пример 2. Задать значения двух целых переменных. Используя соответствующую функцию, поменять значения этих переменных.

#include <stdio.h>

int swap(int *px, int *py) // px и py являются указателями

{ int temp;

temp=*px; // Переменной temp присваивается значение, на которое указывает px

*px=*py; // Теперь по адресу px находится значение y

*py=temp;

return 0;

}

int main()

{

int swap(int *px, int *py); // Прототип функции

int x=3, y=5; // Инициализация переменных x и y

printf(“Вначале значение x=%d, y=%d\n”, x,y);

swap(&x, &y); // Передача адресов переменных x и y функции swap

printf(“Теперь значение x=%d, y=%d\n”, x,y);

return 0;

}

Пояснения.

При передаче функции адресов переменных, а не их значений, функция получает возможность доступа к переменным. Используя указатели и операцию *, функция может извлекать величины, помещенные по соответствующим адресам, и модифицировать их.

Перегрузка функций

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

Пример перегрузки функции.

int myFunction(int,int);

int myFunction(long,long);

int myFunction(long);

Функция myFunction() перегружена с тремя разными списками параметров. Первая и вторая версии отличаются типами параметров, а третья – их количеством. Типы возвращаемых значений перегруженных функций могут быть одинаковыми или разными. При создании двух функций с одинаковым именем и одинаковым списком параметров, но с различными типами возвращаемых значений, будет диагностирована ошибка компиляции. При этом никакой путаницы при вызове функции не будет, поскольку нужная функция определяется по совпадению используемых параметров. Это позволяет создать функцию, которая сможет, например, усреднять целочисленные значения, значения типа double, или значения других типов без необходимости создавать отдельные имена для каждой функции. При вызове перегруженной функции компилятор автоматически определит, какой именно вариант функции следует использовать.


Занятие 7. Коллоквиум.

Готовьтесь к коллоквиуму! Удачи!


Занятие 8. Строки

Указатели и строки

При работе со строками часто используются указатели. Cтрока представляет собой массив символов, заканчивающийся нуль-символом (‘\0’). По положению нуль-символа определяется фактическая длина строки.

Пример, иллюстрирующий применение указателей в работе со строками.

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

#include <stdio.h>

#define PRNT(X) printf(“X=%s; &X=%p\n”, X, &X)

int main()

{

char *text=”Не делай глупостей”, *copy;

copy=text; /* Указатель copy теперь указывает на ту же строку */

printf(“%s\n”, copy);

/* Cтрока – это массив символов, copy – указатель на первый символ массива */

/* Печать первого символа строки (форматная спецификация %с) */

printf(“Первый символ строки: %c \n”, * copy);

/* Печать седьмого символа строки, copy+6 – указатель на седьмой символ */

printf(“Седьмой символ строки: %c \n”, *(copy+6));

PRNT(text);

PRNT(copy);

}

Пояснения.

В программе строка text инициализируется строковой константой ”Не делай глупостей”. Так как любая строка – это массив символов с замыкающим нуль-символом, то можно было бы инициализировать ее и как символьный массив с нуль-символом (‘\0’) в конце:

сhar *text={‘Н’,’е’,’ ‘,’д’,’е’,’л’,’а’,’й’,’,’г’,’л’,’у’,’п’,’о’,’с’,’т’,’е’,’й’,’\0’};

Правда, такой метод инициализации утомителен и чреват ошибками. Без замыкающего нуль-символа мы получаем массив символов, а не строку, и не можем использовать функции работы со строками.

Функции ввода, вывода строк

1. Функции ввода строки gets() и scanf()

Чтобы ввести строку символов, необходимо сначала в программе зарезервировать память под вводимую строку. Это проще всего сделать, явно задав размер символьного массива (например, char array[81]). Функция gets(char *) читает вводимые с клавиатуры символы до тех пор, пока не встретит символ новой строки (‘\n’), который создается при нажатии клавиши [ввод]. Функция берет все символы до (но не включая) символа новой строки, присоединяет к ним нуль-символ (‘\0’) и возвращает указатель на введенную строку вызывающей программе.

Пример использования функции gets() для ввода строки.

Ввести строку символов, вывести ее на экран, вывести пятый символ строки. Для доступа к символам строки использовать указатели.

#include <stdio.h>

int main()

{

char text[81], *ptext;

printf(“Введите строку символов (<=10)”);

ptext=gets(text);

printf(“%s \n %s \n”, text, ptext);

printf(“%c \n %c \n”, text[5],*(ptext+5));

}

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

Пример использования функции scanf() для ввода строки.

Ввести 2 строки символов, вывести их на экран.

#include <stdio.h>

int main()

{

char text1[81], text2[81];

int number;

printf(“Введите 2 строки символов (<=10) через пробел ”);

number=scanf(“%s %s”,text1, text2);

printf(“Функция scanf() считала %d строки: “ %s” и “%s” \n”,

number, text1, text2);

}

2. Функции вывода строк puts() и printf().

Функция puts(char *) очень простая, у нее только один аргумент – указатель на строку. Функция выводит на экран все символы строки, пока ей не встретится нуль-символ. Если с помощью этой функции попытаться вывести на экран массив символов без завершающего нуль-символа, то функция станет перебирать все ячейки памяти, чтобы найти его и остановить свою работу. Хорошо, если найдет. Иначе ей придется работать вечно. Любая строка, выводимая с помощью функции puts(), печатается с новой строки. В вызывающую программу puts() возвращает неотрицательное число.

Пример использования функции puts() для вывода строки.

#include <stdio.h>

int main()

{

char text1[]=”Массив инициализирован этой строкой.”;

char *ptext2=”Указатель инициализирован этой строкой.”;

puts(“Любая строка легко печатается с помощью puts().”);

puts(text1); puts(ptext2);

puts(ptext2+3); // Печать строки начнется не с первого символа, а с четвертого

puts(&text1[4]); // Печать строки начнется с пятого символа

}

Функция printf() менее удобна, чем puts(), но более гибка. Она тоже использует указатель строки в качестве аргумента, но не выводит автоматически каждую строку текста с новой строки. Зато printf() легко объединяет строки для печати в одну строку. В вызывающую программу printf() возвращает число байт выводимой на экран информации.







Что делает отдел по эксплуатации и сопровождению ИС? Отвечает за сохранность данных (расписания копирования, копирование и пр.)...

ЧТО ТАКОЕ УВЕРЕННОЕ ПОВЕДЕНИЕ В МЕЖЛИЧНОСТНЫХ ОТНОШЕНИЯХ? Исторически существует три основных модели различий, существующих между...

ЧТО ПРОИСХОДИТ ВО ВЗРОСЛОЙ ЖИЗНИ? Если вы все еще «неправильно» связаны с матерью, вы избегаете отделения и независимого взрослого существования...

Что делать, если нет взаимности? А теперь спустимся с небес на землю. Приземлились? Продолжаем разговор...





Не нашли то, что искали? Воспользуйтесь поиском гугл на сайте:


©2015- 2024 zdamsam.ru Размещенные материалы защищены законодательством РФ.