Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Прототипы функций




Возврат указателей

Передача строк

 

Строка представляет собой обычный массив символов с нулем в конце, и когда вы передаете строку в функцию, фактически передается только указатель на начало строки. Этот указатель имеет тип char *. Рассмотрим в качестве примера следующую программу. В ней определена функция strInvertCase(), которая преобразует строчные буквы строки в прописные и наоборот:

 

// Передача в функцию строки.

 

#include <iostream>

#include <cstring> I

#include <cctype>

using namespace std;

 

void strlnvertCase(char *str);

 

int main(){

char str[80];

strcpy(str, "This Is A test");

strlnvertCase(str);

cout << str; // вывод модифицированной строки

 

return 0;

}

// Преобразование регистра букв внутри строки,

void strlnvertCase(char *str)

{

while(*str) {

 

// преобразуем регистр

if(isupper(*str)) *str = tolower(*str);

else if(islower(*str)) *str = toupper(*str);

str++; // сместимся к следующему символу

}

}

 

Вот вывод этой программы:

 

tHIS iS a tEST

 

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

В приводимой ниже программе демонстрируется использование указателя в качестве возвращаемого значения. Функция get_substr() просматривает строку в поисках заданной подстроки. Функция возвращает указатель на первую найденную подстроку. Если заданной подстроки найти не удалось, возвращается нулевой указатель. Например, если анализируется строка "Я люблю С++", а в качестве искомой задана подстрока "люблю", то функция вернет указатель на первую букву л в слове "люблю".

//Возврат указателя.

 

#include <iostream>

using namespace std;

 

char *get_substr(char *sub, char *str);

int main ()

{

char *substr;

substr = get_substr("three", "один два three four");

cout << "подстрока найдена: " << substr;

return 0;

}

 

// Возвращает указатель на подстроку или нулевой указатель, если подстрока не найдена.

char *get_substr(char *sub, char *str)

{

int t;

char *p, *p2, *start;

 

for(t = 0; str[t]; t ++) {

p = &str[t]; // начальная установка указателей

start = p;

p2 = sub;

while(*p2 && *p2==*p) { // проверка на наличие подстроки

p ++;

p2 ++;

}

/* Если р2 указывает на завершающий 0 (т. е. на.

конец подстроки), значит, вся подстрока найдена. */

if(!*p2)

return start; // вернуть указатель на начало подстроки

}

return 0; // подстрока не найдена

}

 

Вот вывод этой программы:

 

подстрока найдена: три четыре

 

 

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

§ Тип возвращаемого значения.

§ Типы параметров функции.

§ Число параметров функции.

 

Прототипы позволяют компилятору выполнить три важных операции:

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

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

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

 

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

 

тип имя-функции(тип имя-параметра 1, тип имя-параметра2,…, тип имя-параметраN);

 

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

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

 

/*Эта программа использует прототип функции для активизации строгой проверки типов.

*/

 

void sqr_it(int *i); // прототип

 

int main (){

int х;

х = 10;

sqr_it(х); // Ошибка! Несоответствие типов!;

 

return 0;

}

void sqr_it(int *i)

{

*i = *i * *i;

}

 

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

// Использование определения функции в качестве ее прототипа

#include <iostream>

using namespace std;

 

// Определим, является ли число четным.

bool isEven(int num) {

if(! (num %2)) return true; // num четно

return false;

}

 

int main()

{

if (isEven (4)) cout << "4 четно\n";

if(isEven(3)) cout << "это не будет выведено";

 

return 0; I

}

 

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

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

I




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


Дата добавления: 2014-01-06; Просмотров: 321; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.01 сек.