ТОП 10:

Присваивание значений указателям



Указатель может содержать адреса значений только соответствующего ему типа. Например, p_age может указывать только на целочисленные переменные. С не инициализирует указатели при их объявлении. Если age объявина как показано выше, и нужно, чтобы p_age содержала адрес age, нужно присвоить его переменной p_age:

p_age=&age;

Вместо занесения адреса переменной age в переменную p_age при помощи оператора присваивания можно одновременно объявлять и инициализировать указатели.

int age=20;

int *p_age=&age;

Можно присваивать различные значения переменной age следующим оператором:

age=35;

Либо можно сделать то же самое другим путем:

*p_age=35;

Эта строка подразумевает "взять ячейку памяти, на которую указывает p_age и занести туда значение 35".

Объявление массивов указателей

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

int *iptr[10];

Можно присвоить адрес любому элементу из iptr таким же образом, как и любому другому указателю, не входящему в массив:

iptr[4]=&age;

В следующей строке резервируется массив из 20 указателей на переменные символьного типа:

char *cpoint[20];

Задание:

Написать программу, демонстрирующую отличие между значением указателя и значением, на которое ссылается указатель. Для этого объявить переменную-указатель, зарезервировать под значение динамическую память, присвоить по адресу, содержащемуся в указателе, какое-либо значение. Напечатать значение указателя, размер памяти, занимаемой указателем, значение указателя со снятой ссылкой и размер памяти, занимаемой этим значением. Программу выполнить с использованием моделей памяти small и large.

 

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

1. Какие типы переменных резервируются в каждом следующем случае?

int *a;

char *c;

float b;

2. Что означает запись:

*p_age=35;?

 


Лабораторная работа №17

 

Строковые константы и символьные массивы

Цель работы: исследовать особенности применения символьных массивов и констант и научиться использовать их при написании программ.

 

Теоретические сведения

Любая строка символов или одиночный символ, заключенный в двойные кавычки, интерпретируется как строковая константа. Двойные кавычки не являются частью строковой константы. Они выделяют строку и сообщают компилятору, что она является константой. Строку можно вывести на экран следующим образом:

puts(“Это строка”);

Все строковые константы заканчиваются двоичным нулем или нулевым символом ‘\0’, который компилятор добавляет в конец строки автоматически при задании строковой константы. Этот символ очень важен для компилятора, так как без него было бы неизвестно, где в памяти заканчивается строка.

В С не существует переменной строкового типа, но можно хранить строки в массивах символов. Например, можно создать массив для хранения имени:

char name[10];

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

char name[10]=”Michael”;

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

name[3]=’k’;

Содержимое массива можно вывести на экран при помощи оператора:

puts(name);

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

Часто строки задаются при помощи указателей, например:

char *name;

Если в этом случае строка не инициализируется сразу же при объявлении, то требуется выделить память для ее хранения и инициализировать указатель следующим образом:

name=(char*)malloc(sizeof(char)*10);

После этого имя name можно использовать как обычный указатель, а также использовать его в многочисленных функциях манипуляции со строками, которые находятся в системной библиотеке string.h. При помощи этих функций можно копировать строки, сравнивать, присоединять одну строку к другой и выполнять множество других полезных действий.

 

Задание:

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

1. Подсчет числа символов в строке (без учета нулевого символа).

2. Сравнение двух строк, введенных пользователем.

3. Присоединение одной строки к другой (строки ввести с клавиатуры).

4. Удаление из строки лишних пробелов между словами.

5. Подсчет количества слов в строке.

6. Проверку, является ли строка палиндромом (палиндром – фраза, которая слева направо и справа налево читается одинаково без учета пробелов – «А роза упала на лапу Азора»).

 

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

1. Каковы отличительные признаки строковой константы?

2. Как включить символ двойной кавычки в состав строковой константы?

3. Как можно задать массив символов?

4. Как можно инициализировать символьный массив?

5. В каком случае имя массива можно использовать в функциях манипуляции со строками?

 


Лабораторная работа №18

Программирование с помощью функций.
Вызов функций и возврат из них

Цель работы: Научиться программировать на С с использованием функций. На практике освоить методику вызова функций и возврата из них.

 

Теоретические сведения

Когда необходимо запрограммировать прикладную задачу, то лучше не начинать сразу писать программу. Вместо этого следует подумать о самой программе и ее назначении. Сначала следует сформулировать ее главную цель, а затем разбить на несколько более мелких задач. Необходимо все время помнить о главной цели всей программы. В то же время следует подумать, как отдельные объекты взаимодействуют друг с другом для выполнения этой задачи. Не следует делать программу в виде одного огромного модуля. Лучше разрабатывать отдельные объекты – функции.

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

Main ( )

{

//

//Код на C для ввода символов

// Код на C для сортировки символов в

// алфавитном порядке

// Код на C для вывода отсортированных

// символов на экран

//

return 0;

}

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

Main ()

{

Getletters(); // Вызов функции ввода букв

Alphabetize(); // Вызов функции сортировки

// букв по алфавиту

Printletters(); // Вызов функции вывода

// букв на экран

Return 0; // Возврат в DOS

}

Getletters ( )

{ // Код на C для ввода символов

return; // Возврат в функцию main() }

Alphabetize ( )

{ // Код на C для сортировки символов в алфавитном

// порядке

return; // Возврат в функцию main() }

Printietters ()

{ // Код на C для вывода отсортированных символов

// на экран

return; // Возврат в функцию main() }

Такая программа имеет больший размер, чем предыдущая. Однако она намного лучше структурирована. Единственной задачей функции main() в этом случае является вызов в определенном порядке других функций. Каждая из функций выполняет определенную задачу, после чего управление передается в main( ). Затем функция main( ) вызывает следующую, и так происходит до тех пор, пока не будут вызваны все функции. В конце main передает управление в DOS. Назначение функции main( ) состоит, главным образом, в управлении более мелкими функциями, которые и выполняют всю основную работу.

Функция, написанная на C, обычно имеет следующие свойства:

- Каждая функция должна иметь имя.

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

- За именем каждой функции должна стоять пара круглых скобок. Это помогает компилятору C отличать функции от переменнных. Круглые скобки могут ничего в себе не содержать.

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

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

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

Полная программа с функциями, написанная на Cи, это прояснит. Следующая программа, выводит на экран несколько сообщений. Выводимые сообщения определяются порядком вызова функций. В программе определены три функции: main(), next_fun() и third_fun(). Тело каждой из них заключено в фигурные скобки. В конце каждой функции стоит оператор return.

// Эта программа демонстрирует вызовы функций

#include <stdio.h>

void next fun (void)

// Вторая функция

{

puts( "Inside next fun()");







Последнее изменение этой страницы: 2016-04-08; Нарушение авторского права страницы

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.207.102.38 (0.008 с.)