КАТЕГОРИИ: Архитектура-(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; Просмотров: 350; Нарушение авторских прав?; Мы поможем в написании вашей работы! Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет |