Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Паппас К., Мюррей У. - Visual C++ 6. Руководство разработчика - 2000

.pdf
Скачиваний:
288
Добавлен:
13.08.2013
Размер:
4.96 Mб
Скачать

#include <stdio.h> #include <math.h>

void vpower(double dt, double du); int main () {

double dtnum, dunum;

printf("Введите основание степени: "); scanf("%lf",&dtnum);

printf("\nВведите показатель степени: "); scanf("%lf",&dunum);

vpower(dtnum, dunum); return(0) ;

}

void vpower(double dt, double du) double danswer;

danswer = pow(dt, du) ;

printf("\n%fв степени%f равно%f\n",dt, du, danswer);}

Массивы в качестве аргументов

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

/*

*fpointer.с

*Эта программа на языке С демонстрирует, как передать в функцию массив

*данных. Функция получает указатель на первый элемент массива.

*/

#include <stdio.h>

void voutput(int *pinums); int main ()

{

int iyourarray[7] = {2,7, 15,32,45,3, 1} ; printf("Передаем массив данных ,в функцию.\n"); voutput(iyourarray);

return(0); }

void voutput (int*pinurns) , { int t ;

for(t= 0; t < 7; t++)

printf("Массив данных: %d \n",pinums[t]); } printf("Введите основание степени: "); scanf("%lf",&dtnum);

printf("\nВведите показатель степени: "); scanf("%lf",&dunum);

vpower(dtnum, dunum); return(0);

}

void vpower(double dt, double du) { double danswer;

danswer = pow(dt,du) ;

printf("\n%fв степени%f равно%f\n",dt,du, danswer), }

По сути, функция voutput () получаетимямассива iyourarray [ ]. Но данное имя одновременно является указателем на первый элемент массива. Это справедливо для любых массивов.

121

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

//

//farray.cpp

//Эта программа на языке C++ вычисляет среднее арифметическое ряда чисел.

//

#include <iostream.h>

void avg (float fnums [ ]) ; int main () {

float iyourarray[8] = (12.3,25.7,82.1,6.0,7.01,0.25,4.2,6.28);

cout<< "Передаем массив в функцию для вычисления среднего значения. \n"; avg (iyourarray) ;

return (0); }

void avg (float f nums [ ] ) { int iv;

float fsum = 0.0; float faverage;

for(iv= 0; iv < 8; iv++) { fsum += fnums[iv];

cout<< lv+1

<< "-и элемент равен

" << fnums[iv] <<

"\n";

}

faverage

=

 

fsum/iv; cout <<

"\nСреднее равно

"

<<

faverage

<<

"\n";

 

 

 

}

 

 

 

 

 

 

Типы значений, возвращаемых функциями

Вданном параграфе вы найдете примеры функций, возвращающих значения всех стандартных типов. В предыдущих параграфах мы рассматривали функции, которые не возвращали никаких данных. В таких случаях говорят, что функция возвращает значение типа void. По сути, функция voutput() получает имя массива iyourarray[ ]. Но данное имя одновременно является указателем на первый элемент массива. Это справедливо для любых массивов.

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

//

//farray.cpp

//Эта программа на языке C++ вычисляет среднее арифметическое ряда чисел.

//

#include <iostream.h>

void avg (float f nums [] ) ; int main() {

float iyourarray[8] = (12.3,25.7,82.1,6.0,7.01,0.25,4.2,6.28);

cout<< "Передаем массив в функцию для вычисления среднего значения. \n"; avg (iyourarray) ;

return (0); }

void avg (float fnums[]) { int iv;

float fsum = 0.0; float f average;

for(iv= 0; iv < 8; iv++) { fsum += fnums[iv];

cout<< iv+1 << "-и элемент равен " << fnumsfiv] << "\n"; }

122

faverage = fsum/iv; cout <<

"\nСреднее равно " << faverage

<< "\n";

 

}

 

Тип результата: void

 

Поскольку с функциями, возвращающими значения типа void, мы уже познакомились, рассмотрим чуть более сложный пример. Как вы знаете, в C/C++ можно выводить числовую информацию в шестнадцатеричном, десятичном и восьмеричном формате, но не в двоичном. В следующей программе функция vbinary() преобразовывает полученное десятичное значение в двоичную форму и выводит его на экран. Цифры, составляющие двоичное число, не объединены в единое значение, а представляют собой массив данных.

/*

*voidf.c

*Эта программа на языке С находит двоичный эквивалент заданного

*десятичного числа.

*/

#include <stdio.h>

void vbinary(int idata) ; int main ()

int ivalue;

printf ("Введите десятичное число: "); scanf("%d",Sivalue) ; vbinary (ivalue);

return (0); }

void vbinary (int idata) int t = 0;

int iyourarray [50]; while (idata != 0) {

iyourarray [t]= (idata % 2); idata /= 2;

t++; ) printf("\n");

for( ; t >= 0; t--) printf("%d",iyourarray[t]); }

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

В функции vbinary() этот алгоритм реализуется в цикле while. В результате операции деления по модулю (%) остаток от деления (0 или 1) заносится в массив iyourarray[]. Целая часть, полученная при делении, присваивается переменной idata. Этот процесс продолжается до тех пор, пока целая часть результата деления (переменная idata) не станет равной нулю.

Тип результата: char

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

Вфункции clowercase() вызывается библиотечная функция tolower(), прототип которой находится в файле CTYPE.H, она переводит символ в нижний регистр.

/*

*charf.c

*Эта программа на языке С преобразует символ из верхнего регистра' в нижний.

*/

#include <stdio.h>

123

#include <ctype.h>

char clowercase(char c) ; int main () {

char clowchar, chichar;

printf("Введите букву в верхнем регистре. \n"); chichar = getchar();

clowchar = clowercase(chichar); printf("%c\n",clowchar); return(0);

char clowercase(char c) { return(tolower(c));

}

Тип результата: bool

Ниже дан пример использования двух функций, is_upper() и is_lower(),которые возвращают значения типа bool, проверяя, представлен ли переданный им символ в верхнем или нижнем регистре соответственно. Этот тип данных специфичен для языка C++.

//

//boolf.cpp

//Эта программа на языке C++ демонстрирует возможность

//возвращения функциями значений типа bool.

//

#include <iostream.h>

bool is_upper(void) ; bool is_lower(void) ; int main () {

char cTestChar = 'T';

bool bIsUppercase, bIsLowercase;

bIsUppercase = is__upper (cTestChar) ; bIsLowercase = is_lower(cTestChar);

cout << "Буква " << (blsUppercase ? "является " : "не является ")

<<"прописной.\n";

cout<<

"Буква "

<< {bIsLowercase? "является " : "не является ")

<<

"строчной.\n";

 

return(0); }

 

{

bool

is_upper(int ch)

return(ch>= 'A'&& ch <= 'Z'); }

bool

is_lower(int ch)

{

return(ch >= 'a'&& ch

<= 'z'); }

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

Тип результата: int

В следующем примере функция icube() принимает целое число, возводит его в куб и возвращает результат тоже в виде целого числа.

/*

*intf.c

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

*/

#include <stdio.h>

int icube(int ivalue); int n(ain() int k, inumbercube;

for(k=0;k < 20;k += 2) {

124

inumbercube = icube(k);

printf("Ky6 числа%d равен%d\n",k, inumbercube) }

return(0);

ivalue)

int icube(int

return(ivalue

* ivalue * ivalue);

}

 

Тип результата: long

В следующей программе, написанной на языке C++, функция Ipower() получает целочисленный аргумент, возводит число 2 в степень, заданную аргументом, и возвращает значение типа long.

//

//longf .cpp

//Эта программа на языке C++ демонстрирует возможность возвращения

//функциями значений типа long. Функция Ipower() получает целое число.и

//возводит 2 в степень, определяемую этим числом.

//

#include <iostream.h> long Ipower(int ivalue); int main() int k;

long lanswer;

for(k =0;k < 20; k++) { lanswer = Ipower(k);

cout<< "2 в степени " << k<< " равно " << ianswer<< "\n" return(0); }

long Ipower(int ivalue) . int t;

long Iseed = 1;

for(t =0;t < ivalue; t++) Iseed *= 2; return(Iseed);

}

В функции Ipower() используется цикл, повторяющийся заданное число раз, в котором число 2 последовательно умножается само на себя. На практике для этого лучше применять стандартную функцию pow(), объявленную в файле МАТН.Н.

Тип результата: float

В следующем примере в функцию fproduct () передается массив чисел типа float и возвращается значение того же типа. Данная программа, написанная на языке C++, вычисляет произведение всех элементов массива.

//

//floatf.cpp

//Эта программа на языке C++ демонстрирует возможность возвращения

//функциями значений типа float. Функция fproductО получает массив

//данных типа floatи возвращает произведение элементов массива.

//

#include <iostream.h>

float fproduct(float farray[]); int main()

float fmyarray[7] = (4.3,1.8,6.12,3.19,0.01234,0.1,9876.2}, float fmultiplied;

fmultiplied = fproduct(fmyarray) ;

cout<< "Произведение всех элементов массива равно: " << fmultiplied << "\n";

return(0); }

float fproduct(float farray[])

125

int i;

float fpartial;

fpartial = farray[0]; for (1 = 1; i < 7; i++) fpartial *= farray[i];

return (fpartial); }

Значение первого элемента массива присваивается переменной fpartial еще до начала цикла for. Вот почему цикл начинается с индекса 1, а не 0.

Тип результата: double

В следующем примере функция dtrigcosine() находит значение косинуса угла, заданного в градусах.

/*

*doublef.c

*Эта программа на языке С последовательно находит косинусы углов

*от 0 до 90 градусов с интервалом в пять градусов.

*/

#include <stdio.h> #include <math.h>

const double dPi = 3.14159265359; double dtrigcosine(double dangle); int main() {

int j;

double dcosine;

for(j= 0; j < 91;j+=5) {>

dcosine = dtrigcosine((double) j);

printf("Косинус угла%d градусов равен%.3f\n",j, dcosine); } return(0);}

double dtrigcosine(double dangle) { double dpartial;

dpartial = cos((dPi/180.0) * dangle); return(dpartial);}

Для вычисления косинуса в функции dtrigcosine() вызывается стандартная функция cos(),объявленная в файле МАТН.Н. Но предварительно необходимо преобразовать величину угла из градусов в радианы. Для этого параметр dangleделится на 180 градусов и умножается на число пи, заданное в программе как константа dpi.

Аргументы командной строки

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

имя_программы аргумент1, аргумент2 ...

Аргументы командной строки обрабатываются в функции main(),котoрая принимает два параметра: argc и argv[ ]. Целочисленный параметр а где содержит число аргументов командной строки плюс 1 — с учетом имени программы, которое, в принципе, тоже является аргументом. Вторым параметром является указатель на массив строковых указателей. Все аргументы представляют собой строки, поэтому массив argv[ ] имеет тип char*. Имена параметров — argc и argv— не являются стандартными элементами языка, но называть их именно так — общепринятое соглашение, широко применяемое большинством программистов на C/C++.

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

Текстовые аргументы

126

Аргументы, задаваемые в командной строке, всегда передаются в программу в виде наборов символов, что облегчает работу с ними. В следующей программе на языке С от пользователя ожидается ввод в командной строке ряда аргументов. При запуске программы проверяется значение параметра argc. Если оно меньше двух, то пользователю будет предложено перезапустить программу.

/*

*sargv.c

*Эта программа на языке С демонстрирует процесс

*считывания строковых аргументов командной строки.

*/

#include <stdio.h> #include <process.h>

int main(int argc, char *argv[]) { int t;

if(argc < 2) {

printf("Необходимо ввести несколько аргументов командной строки.\n"); printf("Повторите запуск программы.\n");

exit (1);

forft =1;t < argc; t++)

. printf("Аргумент№%d — %s\n", t, argv[t] ); exit(0);

}

Все аргументы, введенные в командной строке, выводятся на экран в той же последовательности. Если были введены числовые значения, они все равно будут рассматриваться как ASCII-символы.

Целочисленные аргументы

Часто в командной строке нужно указывать числовые значения. В таком случае необходимо выполнить преобразование строк в числа. Следующая программа на языке C++ читает из командной строки символьный аргумент и преобразовывает его в целое число с помощью стандартной функции atoi(). Полученное число сохраняется в переменной ivalueи передается в функцию vbinary(), которая выводит его двоичный эквивалент. В функции main() отображаются также восьмеричный и шестнадцатеричный эквиваленты числа.

//

//iargv.cpp

//Эта программа на языке C++ преобразует аргумент

//командной строки в целое число.

//

 

 

#include

<iostream.h>

#include

<stdlib.h>

void vbinary (int idigits);

int main

(int argc, char *argv[]) {

int ivalue;

2) {

if (argc

!=

cout<< "Введите в командной строке целое число. \n";

cout<< "Это

число будет преобразовано в двоичный, \n"

cout<< "восьмеричный и шестнадцатеричный форматы . \n";

return (0);

 

}

 

 

ivalue =

atoi(argv[1]);

vbinary(ivalue) ;

cout <<

восьмеричном формате: " << oct << ivalue << "\n";

cout <<

шестнадцатеричном формате: " << hex<< ivalue << "\n"

return(0) ;

}

void vbinary (int idigits)

127

int t = 0;

int iyourarray[50]; while(idigits != 0) { iyourarray[t]= (idigits % 2); idigits /= 2;

t++; } t-- ;

cout<< "В двоичном формате: "; for(; t >= 0; t--)

cout << dec << iyourarray[t] ; cout << "\n"; }

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

Для вывода числа в восьмеричном формате используется следующая запись: cout<< "В восьмеричном формате: " << oct << ivalue << "\n";

Чтобы вывести то же число в шестнадцатеричном формате, достаточно просто поменять флаг oкна флаг hex:

cout<< "В шестнадцатеричном формате: " << hex << ivalue << "\n";

При отсутствии дополнительного форматирования шестнадцатеричные цифры а, b, с, d, e и f будут отображаться в нижнем регистре. Более подробно о средствах форматирования, используемых в языке C++, рассказано в главе "Основы ввода-вывода в языке C++". Среди прочего в ней объясняется, как управлять выводом шестнадцатиричных цифр в верхнем и нижнем регистре.

Аргументы с плавающей запятой

Следующая программа на языке С принимает в командной строке несколько значений углов в градусах. Полученные данные используются для вычисления косинусов.

/*

*fargv.c

*Эта программа на языке С демонстрирует процесс считывания аргументов

*командной строки с плавающей запятой.

*/

#include <stdio.h> #include <math.h> #include <process.h>

const double dPi = 3.14159265359; int main(int argc, char *argv[]) { int t;

double ddegree; if(argc< 2) {

printf("Введите в командной строке значения углов в градусах.\n") , printf("Программа вычислит косинусы углов.\n"),•

exit(l);

}

 

 

 

for(t= 1; t

< argc; t++)

{

ddegree = atof<argv[t]);

 

printf("Косинус угла

%f равен

%.3f\n", ddegree,

cos((dPi/180.0)

*

ddegree)); )

exit(0);

 

 

 

}

 

 

 

Функция atof() преобразовывает строковые значения в значения типа double. Для вычисления косинуса используется библиотечная функция cos().

128

Дополнительные особенности функций

Макроподстановка функций

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

Ключевое слово inlineявляется особым видом спецификатора. Его можно представить как рекомендацию компилятору C++ подставить в программный код тело функции по месту ее вызова. Компилятор может проигнорировать эту рекомендацию, если, например, функция слишком велика. Макроподстановка, как правило, применяется, когда какая-нибудь небольшая функция вызывается в программе много раз.

//

//inline. срр

//Эта программа на языке C++ содержит пример макроподстановки функции.

//

#include <iostream.h>

inline long squareit(int iValue) (return iValue * iValue;} int main ()

{

 

 

int iValue;

=

1; ivalue <= 10; iValue++)

for(iValue

cout<<

"Квадрат

числа " << iValue<< " равен "

<< squareit(iValue) << "\n";. return(0); }

Функция squareit(),возвращающая квадрат целочисленного аргумента ivalue, описана со спецификатором inline. Когда в программе будет обнаружен вызов данной функции, компилятор подставит в этом месте строку ivalue*ivalue. Другими словами, компилятор заменяет вызов функции ее телом, присваивая при этом аргументам функции их фактические значения.

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

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

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

Вследующей программе создаются два прототипа функции с одним именем и общей областью видимости, но аргументами разных типов. При вызове функции adder() будут обрабатываться данные либо типа int, либо типа float.

//

//overload.cpp

//Эта программа на языке C++ содержит пример перегрузки функции.

#include <iostream.h>

int adder (int iarray[]); float adder (float f array []); int main() {

129

int iarray[7] = {5,1, 6, 20,15,0, 12);

float farray[7] = {3.3,5.2,0.05,1.49,3.12345,31.0,2.007}; int isum;

float fsum;

isura = adder (iarray) ; fsum= adder (f array) ;

cout<< "Сумма массива целых чисел равна " << isura << "\n"; cout<< "Сумма массива дробных чисел равна " << fsum<< "\n"; return ( 0 ).;

}

int adder(int iarrayt]) { int i;

int ipartial;

ipartial = iarray[0]; for(i= 1; i < 7; i++) ipartial += iarray[i]; return(ipartial);

}

float adder (float farrayf]) { int i;

float f partial, fpartial = f array [0]; for(i= 1; i < 7; i++) fpartial += farray[i]; return (fpartial) ; }

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

int имя_функции(int имя_аргумента) ;

int имя_функции(int имя_аргумента) ; // недопустимая перегрузка имени

Это неправильно, поскольку аргументы имеют одинаковый тип.

Функции с переменным числом аргументов

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

void имя_функции(int first,

float second,

. . . ) ;

Данный прототип говорит компилятору о том, что за аргументами firstи secondмогут следовать и другие аргументы, если возникнет такая необходимость. При этом тип последних не контролируется компилятором.

В следующей программе, написанной на языке С, создается функция vsmalltest( ) с переменным числом аргументов. Текст этой программы может вам показаться трудным для понимания, поскольку мы еще не рассматривали подробно работу с указателями. В таком случае рекомендуем вернуться к этой программе после прочтения главы "Указатели".

/*

*ellipsis. с

*Эта программа на языке С содержит пример функции с переменным числом

*аргументов и демонстрирует использование макросов va_arg, va_startи va_end.

*/

#include <stdio.h> #include <stdarg.h> #include <string.h>

void vsmallest (char *szmessage, ...);

130

Соседние файлы в предмете Программирование на C++