#include #include #include #include #include #include // Alguns exemplos de funcoes // Estes sao os prototipos das funcoes // Prototipos sao usados para declarar as interfaces // das funcoes, para que elas possam ser usadas. // Tendo o prototipo da funcao podemos usa-la mesmo // que o codigo dela seja fornecido mais tarde (veja abaixo). // A interface de uma funcao consiste em: // 1. O nome da funcao // 2. Os argumentos e seus tipos // 3. O tipo do valor de retorno void nada(); void calcula_10_fatorial(); void saudacao(); int fatorial_de_10(); int fatorial(int n); int fat_rec(int n); int combinacoes(int n, int m); std::vector fibonacci(int n); std::tuple div_mod(int n, int m); void escala(std::vector &v, int c); int soma(std::vector const &v); std::vector comb_lin(std::vector const &v1, std::vector const &v2, double a = 1, double b = 1); bool muito_grande(int i); bool muito_grande(double x); bool muito_grande(std::string s); // Programa principal int main(int, char *[]) { // Chamando algumas funcoes inuteis nada(); calcula_10_fatorial(); // Escrevendo uma mensagem saudacao(); // Calculando o fatorial de 10 auto fat_10 = fatorial_de_10(); std::cout << "Fatorial de 10: " << fat_10 << std::endl; std::cout << "Deve ser o mesmo que " << fatorial(10) << std::endl; std::cout << "E o mesmo que " << fat_rec(10) << std::endl; // Calculando o numero de combinacoes de 10 elementos 2 a 2 std::cout << "Numero de combinacoes de 10 elementos dois a dois " << combinacoes(10, 2) << std::endl; // Isto e um erro. Viola pre-condicao da funcao. std::cout << "Surpresa! " << fatorial(-1) << std::endl; // Sequencia de Fibonacci auto fib_10 = fibonacci(10); std::cout << "Primeiros 10 de Fibonacci\n"; for (auto fi: fib_10) { std::cout << fi << " "; } std::cout << std::endl; // Retornando dois valores (quociente e resto) // A funcao get(t) pega o i-esimo elemento da tupla t auto dm = div_mod(11, 3); std::cout << "Quociente: " << std::get<0>(dm) << ", resto: " << std::get<1>(dm) << std::endl; // Outra forma (exige usar -std=c++17 na compilacao) auto [q, r] = div_mod(11, 3); std::cout << "Quociente: " << q << ", resto: " << r << std::endl; // Alterando os valores dos elementos de um vetor std::vector primeiros{1, 2, 4, 8, 16}; // O copy abaixo copia do vetor primeiros para o cout, // elementos a elemento. std::copy(primeiros.begin(), primeiros.end(), std::ostream_iterator(std::cout, " ")); std::cout << std::endl; // Multiplicando cada elemento por 10. escala(primeiros, 10); std::copy(primeiros.begin(), primeiros.end(), std::ostream_iterator(std::cout, " ")); std::cout << std::endl; // Somatoria de elementos do vetor std::cout << "A soma vale: " << soma(primeiros) << std::endl; // Algumas combinacoes lineares de dois vetores std::vector v1{1, 2, 3}; std::vector v2{1, 2, 4}; auto res23 = comb_lin(v1, v2, 2, 3); std::copy(res23.begin(), res23.end(), std::ostream_iterator(std::cout, " ")); std::cout << std::endl; auto res11 = comb_lin(v1, v2); std::copy(res11.begin(), res11.end(), std::ostream_iterator(std::cout, " ")); std::cout << std::endl; auto res21 = comb_lin(v1, v2, 2); std::copy(res21.begin(), res21.end(), std::ostream_iterator(std::cout, " ")); std::cout << std::endl; // Usando funcoes distintas de mesmo nome. if (muito_grande(12)) { std::cout << "12 e muito grande.\n"; } else { std::cout << "12 nao e muito grande.\n"; } if (muito_grande(12.0)) { std::cout << "12.0 e muito grande\n"; } else { std::cout << "12.0 nao e muito grande.\n"; } std::string mensagem{"A galinha do vizinho bota um ovo amarelinho"}; if (muito_grande(mensagem)) { std::cout << "\"" << mensagem << "\" tem muitos caracteres\n"; } else { std::cout << "\"" << mensagem << "\" e OK.\n"; } return 0; } // Funcao mais simples possivel: Nao faz nada. void nada() { } // Esta trabalha a toa: o resultado do calculo nao e usado. void calcula_10_fatorial() { int fat{1}; for (int i = 2; i <= 10; ++i) { fat *= i; } } // Esta tem um efeito colateral (escreve na tela) void saudacao() { std::cout << "Oi. Estou na funcao saudacao\n"; } // Esta calcula fatorial de 10. Mas so de 10. int fatorial_de_10() { int fat{1}; for (int i = 2; i <= 10; ++i) { fat *= i; } return fat; } // Esta calcula fatorial de um n dado; n precisa ser >= 0. int fatorial(int n) { int fat = 1; for (int i = 2; i <= n; ++i) { fat *= i; } return fat; } // Outra de fatorial, mas versao recursiva. int fat_rec(int n) { if (n <= 1) { return 1; } else { return n * fat_rec(n-1); } } // Calcula numero de combinacoes de n elemetos m a m. int combinacoes(int n, int m) { return fatorial(n) / (fatorial(m) * fatorial(n-m)); } // Sequencia dos n primeiros numeros de Fibonacci std::vector fibonacci(int n) { std::vector sequencia{1, 1}; for (int i = 2; i < n; ++i) { auto novo = sequencia[i-1] + sequencia[i-2]; sequencia.push_back(novo); } return sequencia; } // Uma funcao que retorna dois valores. // Tem que retornar uma tupla com os dois valores. // std::tuple indica uma tupla com dois int std::tuple div_mod(int n, int m) { auto div = n / m; auto mod = n % m; return {div, mod}; } // Esta funcao altera o conteudo do vetor v. // Para alterar o conteudo do argumento, nao podemos // fazer uma copia, mas temos que usar referencia. // Por isso o & antes do nome do argumento. // Isto faz com que v desta funcao seja apenas um novo // nome (sinonimo) da variavel passada na chamada da // funcao. void escala(std::vector &v, int c) { for (auto &vi: v) { vi *= c; } } // Soma de todos os elementos de v. // Evita copiar o vetor usando uma referencia, // mas como nao queremos alterar o vetor, marcamos // como const int soma(std::vector const &v) { int resultado{0}; for (auto vi: v) { resultado += vi; } return resultado; } // Uma funcao com dois parametros com valores assumidos. // Os valores assumidos sao especificados no prototipo (acima) std::vector comb_lin(std::vector const &v1, std::vector const &v2, double a, double b) { auto n = static_cast(v1.size()); std::vector resultado(n); for (int i = 0; i < n; ++i) { resultado[i] = a * v1[i] + b * v2[i]; } return resultado; } // As tres funcoes abaixo tem o mesmo nome, mas operam sobre // argumentos de tipos diferente. // Quando funcoes tem o mesmo nome, dizemos que existe // sobrecarga de nome de funcao. bool muito_grande(int i) { return i > 100; } bool muito_grande(double x) { return x > 10; } bool muito_grande(std::string s) { return s.length() > 10; }