Introdução
Neste laboratório, você aprenderá sobre as funções em C++. Você aprenderá como definir e chamar funções, e como passar argumentos para funções.
Neste laboratório, você aprenderá sobre as funções em C++. Você aprenderá como definir e chamar funções, e como passar argumentos para funções.
Às vezes, uma certa porção de código precisa ser usada muitas vezes. É melhor colocá-los em uma "sub-rotina" -- função, e "chamar" essa função muitas vezes - para facilitar a manutenção e a compreensão.
Duas partes estão envolvidas no uso de uma função: um chamador (caller) que chama a função, e a função chamada. O chamador passa argumento(s) para a função. A função recebe esses argumento(s), realiza as operações programadas dentro do corpo da função e retorna um pedaço de resultado de volta ao chamador.
Suponha que precisamos avaliar a área de um círculo muitas vezes, é melhor escrever uma função chamada getArea() e reutilizá-la quando necessário.
/* Test Function */
#include <iostream>
using namespace std;
const int PI = 3.14159265;
// Function Prototype (Declaração da Função)
double getArea(double radius);
int main() {
double radius1 = 1.1, area1, area2;
// call function getArea()
area1 = getArea(radius1);
cout << "area 1 is " << area1 << endl;
// call function getArea()
area2 = getArea(2.2);
cout << "area 2 is " << area2 << endl;
// call function getArea()
cout << "area 3 is " << getArea(3.3) << endl;
}
// Function Definition
// Return the area of a circle given its radius
double getArea(double radius) {
return radius * radius * PI;
}
Saída:
area 1 is 3.63
area 2 is 14.52
area 3 is 32.67


Em C++, você precisa declarar um protótipo de função (antes que a função seja usada) e fornecer uma definição de função, com um corpo contendo as operações programadas.
A sintaxe para a definição da função é a seguinte:
returnValueType functionName ( parameterList ) {
functionBody ;
}
Um protótipo de função informa ao compilador a interface da função, ou seja, o tipo de retorno, o nome da função e a lista de tipos de parâmetros (o número e o tipo de parâmetros). A função agora pode ser definida em qualquer lugar no arquivo. Por exemplo,
// Function prototype - placed before the function is used.
double getArea(double); // without the parameter name
double getArea(double radius); // parameter names are ignored, but serve as documentation
O Tipo de Retorno "void"
Sem a necessidade de retornar um valor ao chamador, você pode declarar seu tipo de valor de retorno como void. No corpo da função, você pode usar uma instrução "return;" sem um valor de retorno para retornar o controle ao chamador.
Parâmetros Reais vs. Parâmetros Formais
No exemplo acima, a variável (double radius) declarada na assinatura de getArea(double radius) é conhecida como parâmetro formal. Seu escopo está dentro do corpo da função. Quando a função é invocada por um chamador, o chamador deve fornecer os chamados parâmetros reais (ou argumentos), cujo valor é então usado para o cálculo real. Por exemplo, quando a função é invocada via "area1 = getArea(radius1)", radius1 é o parâmetro real, com um valor de 1.1.
Escopo das Variáveis Locais e Parâmetros da Função
Todas as variáveis, incluindo os parâmetros da função, declaradas dentro de uma função estão disponíveis apenas para a função. Elas são criadas quando a função é chamada e liberadas (destruídas) após a função retornar. Elas são chamadas de variáveis locais porque são locais para a função e não estão disponíveis fora da função.
C++ introduz os chamados argumentos padrão (default arguments) para funções. Esses valores padrão seriam usados se o chamador omitir o argumento real correspondente ao chamar a função. Os argumentos padrão são especificados no protótipo da função e não podem ser repetidos na definição da função. Os argumentos padrão são resolvidos com base em suas posições. Portanto, eles só podem ser usados para substituir os argumentos finais para evitar ambiguidade. Por exemplo,
/* Test Function default arguments */
#include <iostream>
using namespace std;
// Function prototype - Specify the default arguments here
int fun1(int = 1, int = 2, int = 3);
int fun2(int, int, int = 3);
int main() {
cout << fun1(4, 5, 6) << endl; // No default
cout << fun1(4, 5) << endl; // 4, 5, 3(default)
cout << fun1(4) << endl; // 4, 2(default), 3(default)
cout << fun1() << endl; // 1(default), 2(default), 3(default)
cout << fun2(4, 5, 6) << endl; // No default
cout << fun2(4, 5) << endl; // 4, 5, 3(default)
// cout << fun2(4) << endl;
// error: too few arguments to function 'int fun2(int, int, int)'
}
int fun1(int n1, int n2, int n3) {
// cannot repeat default arguments in function definition
return n1 + n2 + n3;
}
int fun2(int n1, int n2, int n3) {
return n1 + n2 + n3;
}
Saída:
15
12
9
6
15
12

C++ introduz a sobrecarga de funções (function overloading) (ou polimorfismo de funções), que permite ter múltiplas versões do mesmo nome de função, diferenciadas pela lista de parâmetros (número, tipo ou ordem dos parâmetros). Funções sobrecarregadas não podem ser diferenciadas pelo tipo de retorno (erro de compilação). A versão que corresponde à lista de argumentos do chamador será selecionada para execução. Por exemplo,
/* Test Function Overloading */
#include <iostream>
using namespace std;
void fun(int, int, int); // Version 1
void fun(double, int); // Version 2
void fun(int, double); // Version 3
int main() {
fun(1, 2, 3); // version 1
fun(1.0, 2); // version 2
fun(1, 2.0); // version 3
fun(1.1, 2, 3); // version 1 - double 1.1 casted to int 1 (without warning)
// fun(1, 2, 3, 4);
// error: no matching function for call to 'fun(int, int, int, int)'
// fun(1, 2);
// error: call of overloaded 'fun(int, int)' is ambiguous
// note: candidates are:
// void fun(double, int)
// void fun(int, double)
// fun(1.0, 2.0);
// error: call of overloaded 'fun(double, double)' is ambiguous
}
void fun(int n1, int n2, int n3) { // version 1
cout << "version 1" << endl;
}
void fun(double n1, int n2) { // version 2
cout << "version 2" << endl;
}
void fun(int n1, double n2) { // version 3
cout << "version 3" << endl;
}
Saída:
version 1
version 2
version 3
version 1

Você também pode passar arrays para funções. No entanto, você também precisa passar o tamanho do array para a função. Isso ocorre porque não há como saber o tamanho do array a partir do argumento do array dentro da função chamada. Por exemplo,
/* Function to compute the sum of an array */
#include <iostream>
using namespace std;
// Function prototype
int sum(int array[], int size); // Need to pass the array size too
void print(int array[], int size);
// Test Driver
int main() {
int a1[] = {8, 4, 5, 3, 2};
print(a1, 5); // {8,4,5,3,2}
cout << "sum is " << sum(a1, 5) << endl; // sum is 22
}
// Function definition
// Return the sum of the given array
int sum(int array[], int size) {
int sum = 0;
for (int i = 0; i < size; ++i) {
sum += array[i];
}
return sum;
}
// Print the contents of the given array
void print(int array[], int size) {
cout << "{";
for (int i = 0; i < size; ++i) {
cout << array[i];
if (i < size - 1) {
cout << ",";
}
}
cout << "}" << endl;
}
Saída:
{8,4,5,3,2}
sum is 22

Existem duas maneiras pelas quais um parâmetro pode ser passado para uma função: passagem por valor vs. passagem por referência.
Passagem por Valor
Na passagem por valor, uma "cópia" do argumento é criada e passada para a função. A função invocada trabalha no "clone" e não pode modificar a cópia original. Em C/C++, tipos fundamentais (como int e double) são passados por valor.
/* Fundamental types are passed by value into Function */
#include <iostream>
using namespace std;
// Function prototypes
int inc(int number);
// Test Driver
int main() {
int n = 8;
cout << "Before calling function, n is " << n << endl; // 8
int result = inc(n);
cout << "After calling function, n is " << n << endl; // 8
cout << "result is " << result << endl; // 9
}
// Function definitions
// Return number+1
int inc(int number) {
++number; // Modify parameter, no effect to caller
return number;
}
Saída:
Before calling function, n is 8
After calling function, n is 8
result is 9

Passagem por Referência
Por outro lado, na passagem por referência, uma referência da variável do chamador é passada para a função. Em outras palavras, a função invocada trabalha nos mesmos dados. Se a função invocada modificar o parâmetro, a mesma cópia do chamador também será modificada. Em C/C++, arrays são passados por referência. C/C++ não permite que funções retornem um array.
/* Function to increment each element of an array */
#include <iostream>
using namespace std;
// Function prototypes
void inc(int array[], int size);
void print(int array[], int size);
// Test Driver
int main() {
int a1[] = {8, 4, 5, 3, 2};
// Before increment
print(a1, 5); // {8,4,5,3,2}
// Do increment
inc(a1, 5); // Array is passed by reference (having side effect)
// After increment
print(a1, 5); // {9,5,6,4,3}
}
// Function definitions
// Increment each element of the given array
void inc(int array[], int size) { // array[] is not const
for (int i = 0; i < size; ++i) {
array[i]++; // side-effect
}
}
// Print the contents of the given array
void print(int array[], int size) {
cout << "{";
for (int i = 0; i < size; ++i) {
cout << array[i];
if (i < size - 1) {
cout << ",";
}
}
cout << "}" << endl;
}
Saída:
{8,4,5,3,2}
{9,5,6,4,3}

Use const sempre que possível para passar referências, pois isso impede que você modifique inadvertidamente os parâmetros e o protege contra muitos erros de programação.
Em uma busca linear, a chave de busca é comparada com cada elemento do array linearmente. Se houver uma correspondência, ela retorna o índice do elemento correspondente; caso contrário, retorna -1. A busca linear tem complexidade de O(n).
/* Search an array for the given key using Linear Search */
#include <iostream>
using namespace std;
int linearSearch(const int a[], int size, int key);
int main() {
const int SIZE = 8;
int a1[SIZE] = {8, 4, 5, 3, 2, 9, 4, 1};
cout << linearSearch(a1, SIZE, 8) << endl; // 0
cout << linearSearch(a1, SIZE, 4) << endl; // 1
cout << linearSearch(a1, SIZE, 99) << endl; // 8 (not found)
}
// Search the array for the given key
// If found, return array index [0, size-1]; otherwise, return size
int linearSearch(const int a[], int size, int key) {
for (int i = 0; i < size; ++i) {
if (a[i] == key) return i;
}
// a[0] = 1;
// It will result in an error,because a[] is const, means read only
return -1;
}
Saída:
0
1
-1

Você pode passar um parâmetro de tipo fundamental por referência via o parâmetro de referência denotado por &.
/* Test Pass-by-reference for fundamental-type parameter
via reference declaration */
#include <iostream>
using namespace std;
int squareByValue (int number); // Pass-by-value
void squareByReference (int &number); // Pass-by-reference
int main() {
int n1 = 8;
cout << "Before call, value is " << n1 << endl; // 8
cout << squareByValue(n1) << endl; // no side-effect
cout << "After call, value is " << n1 << endl; // 8
int n2 = 9;
cout << "Before call, value is " << n2 << endl; // 9
squareByReference(n2); // side-effect
cout << "After call, value is " << n2 << endl; // 81
}
// Pass parameter by value - no side effect
int squareByValue (int number) {
return number * number;
}
// Pass parameter by reference by declaring as reference (&)
// - with side effect to the caller
void squareByReference (int &number) {
number = number * number;
}
Saída:
Before call, value is 8
64
After call, value is 8
Before call, value is 9
After call, value is 81

C++ fornece muitas funções matemáticas comumente usadas na biblioteca <cmath>
sin(x), cos(x), tan(x), asin(x), acos(x), atan(x):
Take argument-type and return-type of float, double, long double.
sinh(x), cosh(x), tanh(x):
hyper-trigonometric functions.
pow(x, y), sqrt(x):
power and square root.
ceil(x), floor(x):
returns the ceiling and floor integer of floating point number.
fabs(x), fmod(x, y):
floating-point absolute and modulus.
exp(x), log(x), log10(x):
exponent and logarithm functions.
O cabeçalho cstdlib (portado do stdlib.h de C) fornece uma função rand(), que gera um número integral pseudo-aleatório entre 0 e RAND_MAX (inclusive).
/* Test Random Number Generation */
#include <iostream>
#include <cstdlib> // for rand(), srand()
#include <ctime> // for time()
using namespace std;
int main() {
// rand() generate a random number in [0, RAND_MAX]
cout << "RAND_MAX is " << RAND_MAX << endl; // 32767
// Generate 10 pseudo-random numbers between 0 and 99
// without seeding the generator.
// You will get the same sequence, every time you run this program
for (int i = 0; i < 10; ++i) {
cout << rand() % 100 << " "; // need <cstdlib> header
}
cout << endl;
// Seed the random number generator with current time
srand(time(0)); // need <cstdlib> and <ctime> header
// Generate 10 pseudo-random numbers
// You will get different sequence on different run,
// because the current time is different
for (int i = 0; i < 10; ++i) {
cout << rand() % 100 << " "; // need <cstdlib> header
}
cout << endl;
}
Saída:
RAND_MAX is 2147483647
83 86 77 15 93 35 86 92 49 21
29 0 83 60 22 55 97 80 68 87

- name: check if keyword exist
script: |
#!/bin/bash
grep -i 'rand' /home/labex/Code/test.cpp
error: Oops! We find that you didn't use "rand()" method in "test.cpp".
timeout: 3
Os benefícios de usar funções são: