Связь между указателями и массивами — КиберПедия 

Опора деревянной одностоечной и способы укрепление угловых опор: Опоры ВЛ - конструкции, предназначен­ные для поддерживания проводов на необходимой высоте над землей, водой...

Адаптации растений и животных к жизни в горах: Большое значение для жизни организмов в горах имеют степень расчленения, крутизна и экспозиционные различия склонов...

Связь между указателями и массивами

2020-05-08 291
Связь между указателями и массивами 0.00 из 5.00 0 оценок
Заказать работу

Массивы и указатели в С тесно связаны друг с другом и практически являются взаимозаменяемыми. Имя массива можно рассматривать как указатель-константу. А над указателями можно выполнять различные операции, в том числе использовать с указателем индексные выражения.

Ссылка на элемент массива при помощи индекса преобразуется во время компиляции в выражение с указателем, что сокращает время компиляции программы.

В качестве примера рассмотрим целочисленный массив b[5] и переменную-указатель bPtr на целое. Так как имя массива (если с ним не указан индекс) является указателем на первый элемент массива, можно присвоить указателю bPtr адрес первого элемента массива b при помощи оператора присваивания

bPtr = b;

Этот оператор эквивалентен следующему оператору, в котором используется операция взятия адреса первого элемента массива:

bPtr = &b[0];

Альтернативный способ ссылки на элемент массива b[3], использующий выражение с указателем, представлен в следующем операторе:

* (bPtr + 3)

Константа 3 в приведенном выражении называется смещением. Если указатель ссылается на начало массива, величина смещения указывает, на какой элемент массива производится ссылка; значение смещения равно значению индекса массива. Приведенный способ записи носит название нотации указатель /смещение. В этом выражении использованы круглые скобки, потому что операция * имеет больший приоритет, чем операция +. Без круглых скобок в данном выражении значение 3 было бы прибавлено к значению выражения *bPtr (т.е. число 3 будет прибавлено к элементу b[0], так как bPtr указывает на начало массива). Поскольку на значение элемента массива можно сослаться при помощи выражения с указателем, адрес элемента &b[3] представляется выражением bPtr + 3

Имя массива может рассматриваться как указатель, так что его можно использовать в выражениях арифметики указателей. Например, выражение

*(b + 3)

будет ссылаться на элемент массива b[3]. Все выражения с индексами могут быть преобразованы в выражения с указателем и смещением, в качестве указателя можно использовать имя массива. В этом случае значение указателя не изменяется.

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

bPtr [1]

представляет собой ссылку на элемент массива b[1]. Такой способ записи можно назвать методом указатель/индекс.

Имя массива — это указатель-константа и он всегда указывает на начало массива. Поэтому выражение

b += 3 является недопустимым, так как в нем делается попытка изменить значение начального адреса массива.

В программе на рис. 14 используются четыре метода ссылки на элементы массива — имя массива и индекс, указатель/смещение с именем массива, указатель и индекс и указатель/смещение, — для вывода четырех элементов целочисленного массива b.

В качестве еще одного примера взаимозаменяемости массивов и указателей рассмотрим две функции копирования строк — copy1 и сору2 — в программе на рис. 15. Обе функции копируют строку символов (возможно, символьный массив) в массив символов. Прототипы функций copy1 и сору2 абсолютно идентичны. И действительно, они выполняют одну и ту же задачу, но делают это по-разному.

  /* Использование индексов и указателей при работе с массивами */

#include <stdio.h>

main ()

{

int i, offset, b[] = {10, 20, 30, 40)};

int * bPtr = b; /* указателю bPtr присваивается начальный адрес массива b */

printf("Array b is printed with:\n"

"Array subscript notation\n");

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

printf ("b[%d] = %d\n", i, b[i]);

printf ("\nPointer/of f set notation where \n the pointer is the array name\n");

for (offset = 0; offset <= 3; offset++)

printf ("*(b + %d) = %d\n", offset, *'(b + offset));

printf (" \nPointer subscript notation\n");

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

printf (bPtr[%d] = %d\n, i, bPtr[i]);

printf ("\nPointer/of fset notation\n");

for (offset = 0; offset <= 3; offset++)

printf ("* (bPtr + %d) = %d\n", offset, * (bPtr + offset));

return 0;

}

 

Вывод на экран

Array b is printed with:

Array subscript notation

b[0] = 10

b[l] = 20

b[2] = 30

b[3] = 40

 

Pointer/offset notation where

the pointer is the array name

*(b + 0) =10

*(b + l) = 20

*(b + 2) = 30

*(b + 3) = 40

Pointer subscript notation

bPtr[0] = 10

bPtr[l] = 20

bPtr[2] = 30

bPtr[3] =40

 

Pointer/offset notation

*(bPtr + 0) = 10

*(bPtr +1) =20

*(bPtr + 2) = 30

*(bPtr + 3) = 40

Рис. 14. Использование четырех методов ссылки на элементы массива

 

/* Копирование строки с использованием индексов с именем массива

и арифметики указателей */

# include < stdio. h >

void copy1(char *, const char *);

void copy2(char *, const char *);

main ()

{

char string1[10], *string2 = "Hello", string3[10], string4[] = "Goodbye";

copyl(string1, string2);

printf ("string1 = %s\n", string1);

copy2(string3, string4);

printf ("string3 = %s\n", string3);

return 0; }

/* копирование s 2 в s 1 с помощью индексной нотации */

void copy1(char *s1, const char *s2)

{

int i;

for (i = 0; s1[i] = s2[i]; i++)

/* тело цикла пусто */, }

/* копирование s 2 в s 1 с использованием арифметики указателей */

void copy2 (char *s1, const char *s2), {

for (; *s1 = *s2; s1++, s2++)

;                       /* тело цикла пусто */

 }

 

Вывод на экран

String1 = "Hello", string3 = "Good bye";

Рис. 15. Копирование строки с помощью индексов и указателей

 

Функция copy1 применяет для копирования строки s2 в массив s1 индексы. Переменная-счетчик i, используется как индекс массива. В заголовке цикла for выполняется вся работа по созданию копии, при этом тело цикла пусто. В заголовке цикла i инициализируется нулем и увеличивается на единицу на каждом шаге цикла. Условие цикла for, s1[i] = s2[i], выполняет посимвольное копирование строки s2 в s1. Когда в s2 встречается нуль-символ, он присваивается s1, и цикл завершается, потому что целочисленное значение нуль-символа равно нулю (а значение выражения — false).

Функция сору2 при копировании строки s2 в символьный массив s1 использует указатели и арифметику указателей. Здесь также все операции копирования производятся в заголовке цикла for. В цикле не используется управляющая переменная. Как и в функции copy1, копирование символов строки выполняется в выражении условия цикла (*s1 = *s2). Указатель s2 разыменовывается и полученный символ присваивается разыменованному указателю s1. После выполнения присваивания в выражении условия цикла указатели увеличиваются для перехода соответственно к следующему элементу массива s1 и следующему символу строки s2. Когда в строке s2 встречается нуль-символ, он присваивается разыменованному указателю s1 и цикл завершается.

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

Второй параметр каждой функции объявлен как const char * (строка-константа). В обеих функциях второй аргумент копируется в первый аргумент, при этом символы из второго аргумента читаются по одному и не изменяются. Поэтому, в соответствии с принципом минимума привилегий, второй параметр объявляется указателем на значение-константу.

Ни одной из функций не нужно изменять второй аргумент, поэтому ни одной из них и не предоставляется такое право.

 

Массивы указателей

Массивы могут состоять из указателей. Обычный случай такого массива — это массив строк. Элементами строкового массива являются указатели на начала строк. В качестве примера рассмотрим массив suit, который может пригодится для описания игральных карт.

char *suit[4] = {"Hearts", "Diamonds", "Clubs", "Spades"};

Выражение suit[4] в объявлении означает массив из четырех элементов. При помощи char * этот массив объявляется состоящим из указателей на тип char. В массив помещаются четыре значения «Hearts», «Diamonds», «Clubs» и «Spades» («Червы», «Бубны», «Трефы» и «Пики»). Каждое из этих значений хранится в памяти как строка символов с конечным нулем, длиной на один символ больше, чем количество символов, заключенных в кавычки. Строки эти занимают в памяти соответственно 7, 9, 6 и 7 байт. И хотя кажется, что в массив помещаются сами строки, элементами массива являются указатели (см. рис.16).

Каждый указатель ссылается на первый символ соответствующей строки. Таким образом, хотя массив suit имеет фиксированный размер, он может «хранить» символьные строки произвольной длины.

Рис. 16. Графическое представление массива suit

 

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

 

Указатели на функции

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

Чтобы проиллюстрировать использование указателей на функции, рассмотрим программу пузырьковой сортировки, код которой приведен на рис. 17.

Программа состоит из функций main, bubble, swap, ascending и descending. Функция bubble получает указатель на функцию — это может быть функция ascending или функция descending — в дополнение к двум другим параметрам: целочисленному массиву и размеру массива. Во время исполнения программа запрашивает у пользователя способ сортировки — в порядке возрастания или убывания. Если пользователь вводит число 1, функции bubble передается указатель на функцию ascending и производится сортировка переданного массива по возрастанию. Если пользователь вводит число 2, то в функцию bubble передается указатель на функцию descending и производится сортировка массива по убыванию.

В заголовке функции bubble имеется следующий параметр:

int (* compare) (int, int)

Это значит, что функция bubble получает аргумент, являющийся указателем на функцию, которая имеет два целочисленных параметра и возвращает результат целого типа. Вокруг *compare необходимы круглые скобки, потому что операция * имеет более низкий приоритет, чем скобки, в которые заключены параметры функции. Если убрать скобки, то объявление будет иметь вид

int * compare (int, int)

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

Прототип функции bubble может быть объявлен и в таком виде:

int (*) (int, int)

Функция, переданная функции bubble, вызывается в операторе if следующим образом:

if ((*compare) (work [count], work [count +1]))

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

 

/* Многоцелевая программа сортировки, использующая указатели

на функцию */

# include <stdio.h>

#define SIZE 10

void bubble (int *, const int, int (*) (int, int)); int ascending(const int, const int); int descending(const int, const int);

main () {

int a[SIZE] = {2, 6, 4, 8, 10, 12, 89, 68, 45, 37};

int counter, order;

printf("Enter 1 to sort in ascending order,\n"); printf("Enter 2 to sort in descending order: "); scanf("%d", &order);

printf (" \nData items in original order\n");

for (counter = 0; counter <= SIZE - 1; counter++) printf ("%4d", a [counter]);

if (order == 1) {

bubble (a, SIZE, ascending);

printf (" \nData items in ascending order\n"); } else {

bubble(a, SIZE, descending);

printf(" \nData items in descending order\n"); }

for (counter = 0; counter <= SIZE - 1; counter++) printf ("%4d", a[counter]);

printf ("\n");

return 0; }

void bubble (int *work, const int size, int (*compare) (int, int)) {

int pass, count;

void swap(int *, int *);

for (pass = 1; pass <= size - 1; pass++)

for (count = 0; count <= size - 2; count++)

if ((*compare)(work[count], work[count + 1])) swap(Swork[count], &work[count + 1]);

}

void swap(int *elementlPtr, int *element2Ptr)

{

int temp;

temp = *elementlPtr;

*elementlPtr = *element2Ptr; *element2Ptr = temp;

}

int ascending (const int a, const int b)

{return b < a;}

int descending (const int  a, const int b)

{

return b > a;

}

Рис. 17. Программа пузырьковой сортировки

Функцию можно вызвать и без разыменования указателя, как это сделано в следующей строке:

if (compare(work[count], work[count +1]))

Здесь указатель используется непосредственно, как имя функции. При втором методе вызова функции через указатель может создаться впечатление, что compare — это имя функции. В результате пользователь программы может запутаться, если попытается найти определение функции compare и обнаружит, что она нигде в файле не определена.

Указатели на функции часто используются в системах, управляемых посредством меню. Пользователь выбирает команду меню (например, одну из пяти). Каждая команда обслуживается своей функцией. Указатели на каждую функцию находятся в массиве указателей. Выбор пользователя служит индексом, по которому из массива выбирается указатель на нужную функцию.

Программа на рис. 18 показывает типовой пример объявления и использования массива указателей на функцию. Определяются три функции — function1, function2 и function3, — каждая из которых имеет целочисленный параметр и не возвращает значения. Указатели на эти три функции находятся в массиве f, который объявляется так:

void (*f[3]) (int) = (function1, function2, function3);

Объявление читается, начиная с самой левой скобки и звучит как: «f — массив из трех указателей на функцию, которая имеет параметр целого типа и не возвращает значения». Массив инициализируется именами трех функций. Когда пользователь вводит значение от 0 до 2, это значение используется в качестве индекса массива указателей на функцию. Вызов функции выполняется следующим образом:

(*f[choice]) (choice);

/*Пример использования массива указателей на функцию */

#include <stdio.h>

void functionl(int);

void function2(int);

void function3(int);

main()

 {

void (*f[3]) (int) = (functionl, function2, function3);

int choice;

printf("Enter a number between 0 and 2, 3 to end: ");

scanf("%d", &choice);

while (choice >= 0 && choice < 3) {

(*f [choice]) (choice);

printf ("Enter a number between 0 and 2, 3 to end: ");

scanf("%d", Schoice); }

printf ("You entered 3 to end\n");

return 0;

}

void functionl (int a)

{

printf ("You entered %d so functionl was called\n\n", a);

}

void function2 (int b) {

printf ("You entered %d so function2 was called\n\n", b);

}

void function3 (int c)

{ printf ("You entered %d so function3 was called\n\n", c);

}

Рис. 18. Пример массива указателей на функцию

 

В этом вызове f[choice] выбирает указатель по индексу choice. Для вызова функции указатель разыменовывается, а переменная choice передается функции в качестве аргумента. Каждая функция выводит значение полученного аргумента и свое имя, что позволяет убедиться в правильности вызова функции.

 

 

Порядок выполнения работы

1. Изучите теоретический материал.

2. Напишите программу, согласно заданному в варианте задания условию.

3. Ответьте на контрольные вопросы.

Варианты заданий

Вариант 1

Предположим, что числа с плавающей точкой обычной точности занимают 4 байта, и что начальный адрес массива равен 1002500. Объявите массив numbers типа float из 10 элементов и присвойте элементам значения 0.0, 1.1, 2.2,..., 9.9. Используйте символическую константу SIZE, равную 10. Объявите указатель nPtr, ссылающийся на тип float. Выведите элементы массива numbers, используя нотацию имя массива/индекс. Используйте цикл for и переменную цикла i. Выведите каждый элемент с точностью одного знака после запятой. Присвойте указателю nPtr адрес начала массива numbers двумя способами. Выведите элементы массива numbers при помощи обращения к элементам массива по методу указатель/смещение, где в качестве указателя используется nPtr. Выведите элементы массива numbers при помощи обращения к элементам массива по методу указатель/смещение, где в качестве указателя используется имя массива. Выведите элементы массива numbers, используя индексацию ука­зателя nPtr. Сошлитесь на четвертый элемент массива, используя все четыре способа доступа к элементам массива: имя массива/индекс, имя мас­сива/смещение, указатель/индекс с указателем nPtr и указатель/смещение с указателем nPtr. 

Вариант 2

Выполните каждую из следующих задач при помощи одиночного оператора. Считайте объявленными переменные с плавающей точкой number1 и number2, причем number1 присвоено значение 7.3.

a)Объявите указатель fPtr на тип float.

b) Присвойте адрес переменной numberl указателю fPtr.

c)Выведите значение величины, на которую ссылается fPtr.

d) Присвойте значение величины, на которую указывает fPtr, переменной number2.

e)Выведите значение number2.

f) Выведите адрес numberl. Используйте спецификатор формата %р.

g)Выведите адрес, сохраненный в fPtr. Используйте спецификатор формата %р.

Вариант 3

Выполните следующие задания.

a) Напишите заголовок функции exchange, которая имеет два параметра-указателя на переменные с плавающей точкой х и у и не возвращает значения.

b) Напишите прототип для функции из предыдущего задания.

c) Напишите заголовок функции evaluate, которая возвращает целое число и имеет в качестве параметров целое число х и указатель на функцию poly. Функция poly, в свою очередь, имеет целочислен­ный параметр и возвращает целое число.

d) Напишите прототип для функции из предыдущего задания.

Вариант 4

Выполните каждое из следующих заданий, используя для этой цели только один оператор. Считайте, что переменные value1 и value2 типа long объявлены и переменной value1 присвоено значение 200000.

a) Объявите указатель lPtr на объект данных типа long.

b)Присвойте значение адреса переменной value1 указателю lPtr.

c) Выведите значение объекта, на который ссылается указатель lPtr.

d) Присвойте значение объекта, на который ссылается lPtr, пере­менной value2.

e) Выведите значение value2.

f) Выведите адрес value1.

g) Выведите значение адреса, находящееся в lPtr. Совпадает ли выведенное значение с адресом valuel?

Вариант 5

Выполните следующие задания.

a)Напишите заголовок функции zero, которая имеет параметром це­лочисленный массив biglntegers типа long и не возвращает значе­ние.

b) Напишите прототип для функции из предыдущего задания.

c)Напишите заголовок функции addAndSum, имеющей целочис­ленный массив oneTooSmall в качестве параметра и возвращающей целое число.

d) Напишите прототип функции из предыдущего задания.

Вариант 6

(Быстрая сортировка) Алгоритм для одномерного массива выглядит следующим образом:

1) Этап разбиения: Возьмите первый элемент несортированного массива и определите его расположение в отсортированном массиве. Это положение будет найдено, если все значения слева от данного элемента будут меньше, а все значения направо от элемента — больше значения данного элемента. Мы теперь имеем один элемент, расположенный на своем месте в отсортированном массиве и два несортированных подмассива.

2) Этап рекурсии: Выполните шаг 1 на каждом из несортированных подмассивов.

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

Это описание алгоритма в целом кажется достаточно ясным, но как нам определить окончательную позицию первого элемента каждого подмассива? В качестве примера рассмотрим следующий набор значений (элемент, выделенный жирным — элемент разбиения, — должен быть помещен на свое окончательное место в отсортированном массиве):

37 2 6 4 89 8 10 12 68 45

1) Начиная с правого элемента массива будем сравнивать каждый элемент с числом 37 до тех пор, пока не будет найден элемент меньший чем 37, после чего найденный элемент и 37 должны поменяться своими местами. Первым элементом, который меньше 37, является число 12, поэтому они меняются местами. Теперь массив выглядит так: 12 2 6 4 89 8 10 37 68 45

Элемент 12 выделен курсивом, чтобы указать на то, что он поменял­ся местами с числом 37.

2) Теперь начинаем движение с левой части массива, но начинаем со следующего элемента после 12, и сравниваем каждый элемент с 37, пока не обнаружим элемент больший чем 37, после чего меняем местами 37 и этот найденный элемент. В нашем случае первый элемент больший чем 37 — это 89, так что 37 и 89 меняются местами. Новый массив имеет вид:

12 2.6 4 37 8 10 89 68 45

3) Теперь начинаем справа, но начинаем с элемента, предшествующего 89, и сравниваем каждый элемент с 37 до тех пор, пока не найдем меньший чем 37, и опять поменяем местами 37 и этот элемент. Первый элемент, который меньше 37 — это 10, — меняем местами с 37. Теперь наш массив имеет вид:

12 2 6 4 10 8 37 89 68 45

4) Теперь начинаем движение с левой части массива, но начинаем с элемента, следующего за 10, и сравниваем каждый элемент с 37, пока не обнаружим элемент больший чем 37, после чего меняем местами 37 и этот найденный элемент. В нашем случае элементов, больших 37, не осталось, и когда мы сравним 37 с самим собой, это будет означать, что процесс закончен и элемент 37 нашел свое окончательное место.

После завершения этой операции мы имеем два неупорядоченных подмассива. Подмассив со значениями меньше 37 содержит элементы 12, 2, 6, 4, 10и8. Подмассив со значениями большими 37 содержит 89, 68 и 45. Сортировка продолжается путем применения алгоритма разбиения к полученным подмассивам, как это делалось с первоначальным массивом.

На основе описанного выше алгоритма напишите рекурсивную функцию quicksort, сортирующую одномерный целочисленный массив. Функция должна иметь параметрами целочисленный массив, начальное значение индекса и конечное значение индекса. Функция quicksort должна вызывать функцию partition, выполняющую разбиение массива.

Вариант 7

(Массивы указателей на функции) Напишите программу, управляющуюся при помощи меню. Программа должна предлагать пользователю выбор из 4 команд примерно таким образом:

Выберите:

0 Вывести массив оценок

1 Найти минимальную оценку

2 Найти максимальную оценку

3 Вывести среднюю по всем тестам оценку для каждого студента

4 Выйти из программы

Указатели должны ссылаться на функции, возвращающие значение одного и того же типа, а также имеющие параметры одинаковых типов. По этой причине функции на рис. 6.22 должны быть изменены так, чтобы они возвращали резу­льтат одного типа и имели одинаковый набор параметров. Модифицированные функции minimum и maximum должны выво­дить минимальную и максимальную оценки и ничего не возвра­щать. Измените функцию average для команды меню 3, представ- ленную на рис. 6.22, чтобы она выводила средний балл для каждого студента (а не для одного). Функция average не должна ничего воз­вращать и должна иметь список параметров, одинаковый с функци­ями printArray, minimum и maximum. Сохраните указатели на че­тыре функции в массиве processGrades и используйте выбор, сделанный пользователем, в качестве индекса массива указателей для вызова нужной функции.

 


Форма отчёта: отчет выполняется в текстовом редакторе в электронном виде.

Содержание отчета:

1. Тема работы.

2. Цель работы.

3. Текст отлаженной программы с комментариями

 

Система оценки: пятибальная.

Контрольные вопросы

1. Заполните пропуски в предложениях:

a) Указатель — это переменная, которая в качестве значения содер­жит  другой переменной.

b) Только три величины могут использоваться для инициализации указателя:, ______________  или ______.

c) Единственное целое число, которое может быть присвоено указа­телю, это.

2. Являются ли следующие утверждения верными? Если утверждение неверно, объясните, почему.

a) Операция взятия адреса & может применяться только к констан­там, выражениям и переменным, объявленным с модификатором re­gister.

b) Указатель на void может быть разыменован.

c) Указатели на разные типы данных не могут быть присвоены друг другу без использования операции приведения типов.

3. Найдите ошибку в каждом из следующих фрагментов программ. Учитывайте следующую информацию:

int *zPtr; /* zPtr ссылается на массив z */

int *aPtr = NULL;

void *sPtr = NULL;

int number, I;

int z[5] = {1, 2, 3, 4, 5};

sPtr = z;

a) ++zptr;

b) /* использование указателя для получения первого элемента

массива */ number = zPtr;

c) /* присвоение переменной number значения второго элемента массива (число 3)*/

number = *zPtr[2];

d) /* вывод элементов массива z */ for (i = 0; i <= 5; I++)

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

e) /* присвоение переменной number значения, на которое

ссылается указатель sPtr */ number = *sPtr;

f) + + z;

 

4. Заполните пропуски в предложениях:

a) Операция _______  возвращает адрес своего операнда.

b) Операция_______ возвращает значение объекта, на который

операнд указывает.

c) Для того, чтобы произвести вызов по ссылке при передаче пере- менной (не массива) в качестве аргумента функции, нужно передать  переменной.

5. Являются ли следующие утверждения верными? Если утверждение неверно, объясните, почему.

a) Не имеет смысла сравнивать два указателя, которые указывают на различные массивы.

Поскольку имя массива является указателем на первый элемент массива, имена массивов могут использоваться совершенно анало­гично указателям

6. Что делает эта программа?

#include <stdio.h>

void mystery1(char *, const char *);

main () {

char string1[80], string2[80];

printf("Enter two strings: "); scanf ("%s%s" stringl, string2); mystery1(string1, string2); printf ("%s\n", stringl); return 0; }

void mystery1(char *sl, const char *s2) {

while (*sl!= '\0') + + sl;

for (; *s1 = *s2; s1++, s2++); /* тело цикла пусто */ }

7. Что делает эта программа?

#include <stdio.h>

int mystery2(const char *);

main () {

char string[80];

printf("Введите строку: "); scanf ("%s", string); printf("%d\n", mystery2(string)); return 0; }

int mystery2(const char *s) {

int x = 0;

for (; *s!= '\0'; s++) ++x;

return x; }

8. Найдите ошибку в каждом из следующих фрагментов программы. Если ошибку можно исправить, то объясните как это можно сделать.

a) int *number;

printf ("%d\n", *number);

b)float *realPtr; long *integerPtr; integerPtr = realPtr;

c)int *x, y;

x = y;

d) char s[] = "вот массив символов"; int count;

for (; *s.' = ' \0'; s + +) printf ("%c ", *s);

e)short *numPtr, result; void *genericPtr = numPtr; result = *genericPtr + 7;

f) float x = 19.34; float xPtr = &x; printf("%f\n", xPtr);

g)char *s;

printf ("%s\n", s);

9. Что делает эта программа?

tinclude <stdio.h>

int mystery3(const char *, const char *);

main () {

char string1 [80], string2 [80];

printf("Введите две строки: "); scanf("%s%s", string1, string2); printf("Результат равен %d\n", mystery3(string1,

string2));

return 0; }

int mystery3(const char *s1, const char *s2) {

for (; *s1!= '\0' && *s2!= '\0'; s1++, s2++) if (*s1!= *s2) return 0;

return 1; }

Список использованной литературы

 

1. Х.Дейтел Как программировать на C; Пер. с англ. под ред. В. Тимофеева. - М.: БИНОМ, 2000. - 1005 с.: ил.; 24

2. Язык программирования С / Брайан Керниган, Деннис Ритчи; [пер. с англ. и ред. В. Л. Бродового]. - 2-е изд., перераб. и доп. - Москва [и др.]: Вильямс, 2007. - 289 с.; 23 см.

3. Бьерн Страуструп Язык программирования C++; Пер. с англ. С. Анисимова и М. Кононова под ред. Ф. Андреева, А. Ушакова. - 3. изд. - М.: Binom Pablishers; СПб.: Нев. диалект, 2004. - 990 с.: ил.; 24 см.


Практическое занятие 5


Поделиться с друзьями:

Эмиссия газов от очистных сооружений канализации: В последние годы внимание мирового сообщества сосредоточено на экологических проблемах...

Папиллярные узоры пальцев рук - маркер спортивных способностей: дерматоглифические признаки формируются на 3-5 месяце беременности, не изменяются в течение жизни...

Состав сооружений: решетки и песколовки: Решетки – это первое устройство в схеме очистных сооружений. Они представляют...

Поперечные профили набережных и береговой полосы: На городских территориях берегоукрепление проектируют с учетом технических и экономических требований, но особое значение придают эстетическим...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.232 с.