Reunimos 13 exercícios em que você cria suas próprias funções, do nível iniciante ao avançado. Na maioria deles, a função main que lê a entrada e mostra o resultado já está pronta: você só precisa escrever o corpo da função pedida. Ao clicar em "Corrigir", seu código é testado com várias entradas usando gcc de verdade, e a saída é conferida.
Obs.: Executar e Corrigir enviam seu código ao Wandbox, um serviço externo e gratuito de compilação, que o executa com gcc.
int max3(int a, int b, int c), que recebe 3 inteiros e retorna o maior deles. A função main, que lê a entrada e mostra o resultado, já está pronta. A saída é "Máximo: valor"."Executar" roda seu código com a entrada acima. "Corrigir" testa com 5 entradas preparadas.
a em uma variável m e compare com b e depois com c: "se for maior que m, substitui m". No final, devolva o valor a quem chamou com return m;.#include <stdio.h> int max3(int a, int b, int c) { int m = a; if (b > m) m = b; if (c > m) m = c; return m; } int main(void) { int a, b, c; scanf("%d %d %d", &a, &b, &c); printf("Máximo: %d\n", max3(a, b, c)); return 0; }
return, que toma o lugar de max3(a, b, c) no ponto em que a função foi chamada. Fazer printf dentro da função não vira valor de retorno. Se o valor inicial do máximo for 0, a função retorna 0 quando todos os números são negativos (4º teste).void print_time(int sec), que recebe uma quantidade de segundos e a mostra em uma linha no formato "Hh Mmin Ss" (0 ≤ sec ≤ 1000000). Ela não retorna valor (void). A função main já está pronta."Executar" roda seu código com a entrada acima. "Corrigir" testa com 5 entradas preparadas.
sec / 3600, os minutos sec % 3600 / 60 e os segundos sec % 60. A exibição também é feita dentro da função.#include <stdio.h> void print_time(int sec) { int h = sec / 3600; int m = sec % 3600 / 60; int s = sec % 60; printf("%dh %dmin %ds\n", h, m, s); } int main(void) { int sec; scanf("%d", &sec); print_time(sec); return 0; }
void "não devolve valor, só faz um trabalho" (aqui, mostrar na tela). Mesmo sem escrever return, ao chegar ao fim da função a execução volta para quem a chamou. Se você calcular os minutos com sec / 60, o resultado inclui os minutos das horas (para 3661 segundos daria 61 minutos).int is_leap(int year), que retorna 1 se o ano year for bissexto e 0 caso contrário (1 ≤ year ≤ 9999). Um ano é bissexto se "for divisível por 4, exceto os divisíveis por 100, mas os divisíveis por 400 são bissextos". A função main já está pronta."Executar" roda seu código com a entrada acima. "Corrigir" testa com 5 entradas preparadas.
(year % 4 == 0 && year % 100 != 0) || year % 400 == 0. Em C, o resultado de comparações e operações lógicas é 1 (verdadeiro) ou 0 (falso), então você pode dar return nessa expressão diretamente.#include <stdio.h> int is_leap(int year) { return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0; } int main(void) { int year; scanf("%d", &year); if (is_leap(year)) { printf("O ano %d é bissexto\n", year); } else { printf("O ano %d não é bissexto\n", year); } return 0; }
is_xxx que retorna 1 para verdadeiro e 0 para falso, o código fica legível quase como uma frase: if (is_leap(year)). Se você testar só "divisível por 4 é bissexto", erra o ano 1900.double c_to_f(double c), que recebe uma temperatura c em graus Celsius e retorna a temperatura em Fahrenheit (c × 9 ÷ 5 + 32). A função main já está pronta e mostra o resultado com 1 casa decimal."Executar" roda seu código com a entrada acima. "Corrigir" testa com 5 entradas preparadas.
double, você pode devolver o resultado do cálculo diretamente, como em return c * 9.0 / 5.0 + 32.0;.#include <stdio.h> double c_to_f(double c) { return c * 9.0 / 5.0 + 32.0; } int main(void) { double c; scanf("%lf", &c); printf("%.1f°C = %.1f°F\n", c, c_to_f(c)); return 0; }
c * 9 / 5 o cálculo sai certo porque c é double, mas se você escrever 9 / 5 * c, o 9 / 5 é calculado primeiro como divisão entre inteiros e dá 1, e o resultado fica errado. Note também que, se o tipo de retorno for int, a parte decimal é descartada.int reverse_num(int n), que recebe um inteiro n ≥ 0 (0 ≤ n ≤ 99999999) e retorna o número formado pelos seus dígitos em ordem inversa (ex.: 1230 → 321). A função main já está pronta e, depois de chamar a função, também mostra o n original."Executar" roda seu código com a entrada acima. "Corrigir" testa com 5 entradas preparadas.
r em 0 e repita "r = r * 10 + n % 10; → n /= 10;" até n chegar a 0. Não tem problema alterar n dentro da função.#include <stdio.h> int reverse_num(int n) { int r = 0; while (n > 0) { r = r * 10 + n % 10; n /= 10; } return r; } int main(void) { int n; scanf("%d", &n); int r = reverse_num(n); printf("%d de trás para frente é %d\n", n, r); return 0; }
n que a função recebe é uma cópia do n de quem chamou, então, mesmo reduzindo-o a 0 dentro da função, o n da main não muda e o número original pode ser mostrado. Por outro lado, isso significa que alterar um argumento dentro da função não comunica nenhum resultado a quem chamou; por isso o resultado é devolvido com return.int sum_array(const int a[], int n), que recebe um array de int com n elementos e retorna a soma, e a função int max_array(const int a[], int n), que retorna o maior valor. A função main já está pronta: ela lê primeiro n (1 ≤ n ≤ 100), depois n inteiros (valor absoluto até 10000), e mostra a soma, o máximo e a média (com 2 casas decimais)."Executar" roda seu código com a entrada acima. "Corrigir" testa com 4 entradas preparadas.
const int a[], e o número de elementos vem em outro parâmetro, n. Para o máximo, use a[0] como máximo provisório e compare com a[1] em diante.#include <stdio.h> int sum_array(const int a[], int n) { int sum = 0; for (int i = 0; i < n; i++) { sum += a[i]; } return sum; } int max_array(const int a[], int n) { int max = a[0]; for (int i = 1; i < n; i++) { if (a[i] > max) max = a[i]; } return max; } int main(void) { int a[100]; int n; scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%d", &a[i]); } int sum = sum_array(a, n); printf("Soma: %d\n", sum); printf("Máximo: %d\n", max_array(a, n)); printf("Média: %.2f\n", (double)sum / n); return 0; }
sizeof(a) não é o tamanho do array inteiro). O const indica que "esta função não altera o array". Se o valor inicial do máximo for 0, o resultado fica errado quando todos os números são negativos (3º teste).void reverse_array(int a[], int n), que inverte, no próprio array, a ordem dos n elementos de um array de int. A função main já está pronta: ela lê n (1 ≤ n ≤ 100) e n inteiros, chama a função e mostra o array separado por espaços."Executar" roda seu código com a entrada acima. "Corrigir" testa com 5 entradas preparadas.
a[i] com o do fim a[n - 1 - i], repetindo até a metade (i < n / 2). Use uma variável temporária tmp para a troca.#include <stdio.h> void reverse_array(int a[], int n) { for (int i = 0; i < n / 2; i++) { int tmp = a[i]; a[i] = a[n - 1 - i]; a[n - 1 - i] = tmp; } } int main(void) { int a[100]; int n; scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%d", &a[i]); } reverse_array(a, n); for (int i = 0; i < n; i++) { printf("%d ", a[i]); } printf("\n"); return 0; }
a[i] dentro da função muda o array da main. Se o laço for até i < n, os elementos já trocados são trocados de novo e o array volta ao que era.int sum_divisors(int n), que retorna a soma dos divisores de n, sem contar o próprio n. Neste exercício a definição da função fica depois da main, por isso há uma declaração de protótipo no início. A função main já está pronta: se a soma dos divisores for igual a n, mostra que é perfeito; se for maior que n, abundante; se for menor, deficiente."Executar" roda seu código com a entrada acima. "Corrigir" testa com 6 entradas preparadas.
i de 1 até n / 2, some i se n % i == 0 (os divisores de n, sem contar o próprio n, são todos menores ou iguais a n/2). Quando n = 1, o laço não roda nenhuma vez e o resultado é 0.#include <stdio.h> int sum_divisors(int n); // declaração de protótipo int main(void) { int n; scanf("%d", &n); int s = sum_divisors(n); printf("Soma dos divisores: %d\n", s); if (s == n) { printf("%d é um número perfeito\n", n); } else if (s > n) { printf("%d é um número abundante\n", n); } else { printf("%d é um número deficiente\n", n); } return 0; } int sum_divisors(int n) { int sum = 0; for (int i = 1; i <= n / 2; i++) { if (n % i == 0) sum += i; } return sum; }
; no fim da declaração.char grade(int score), que recebe uma nota score (0 a 100) e retorna a letra do conceito: 90 ou mais é A, 80 ou mais é B, 70 ou mais é C, 60 ou mais é D e abaixo disso é F. A função main já está pronta: ela lê o número de alunos n (1 ≤ n ≤ 50) e as n notas, e mostra uma linha por aluno no formato "nota pontos: conceito"."Executar" roda seu código com a entrada acima. "Corrigir" testa com 4 entradas preparadas.
if (score >= 90) return 'A';, e dê return assim que uma condição for satisfeita. Caracteres são escritos entre aspas simples, como 'A'.#include <stdio.h> char grade(int score) { if (score >= 90) return 'A'; if (score >= 80) return 'B'; if (score >= 70) return 'C'; if (score >= 60) return 'D'; return 'F'; } int main(void) { int n; scanf("%d", &n); for (int i = 0; i < n; i++) { int score; scanf("%d", &score); printf("%d pontos: %c\n", score, grade(score)); } return 0; }
return, a função termina naquele ponto, então os testes seguintes não são feitos mesmo sem escrever else. "A" (aspas duplas) é uma string e não pode ser o valor de retorno de tipo char. Os testes conferem os limites exatos de 90, 80, 70 e 60 pontos.int is_new_max(int x), que recebe um inteiro x a cada chamada e retorna 1 se x for maior que todos os valores recebidos até agora (ou se for a primeira chamada), e 0 caso contrário. Guarde o máximo até o momento em uma variável static dentro da função (não use variáveis globais). A função main já está pronta: ela passa n inteiros (1 ≤ n ≤ 50) para a função, um de cada vez, e mostra uma linha "valor: novo máximo" ou "valor: -" para cada um."Executar" roda seu código com a entrada acima. "Corrigir" testa com 4 entradas preparadas.
static int max; e static int first = 1;. Variáveis static mantêm o valor mesmo depois que a função termina, e são inicializadas uma única vez, no início do programa. Se first for 1, trate como "primeira vez".#include <stdio.h> int is_new_max(int x) { static int first = 1; static int max; if (first || x > max) { first = 0; max = x; return 1; } return 0; } int main(void) { int n; scanf("%d", &n); for (int i = 0; i < n; i++) { int x; scanf("%d", &x); if (is_new_max(x)) { printf("%d: novo máximo\n", x); } else { printf("%d: -\n", x); } } return 0; }
balance (valor inicial 0), que representa o saldo, escreva a função de depósito void deposit(int amount) e a função de saque int withdraw(int amount). withdraw diminui o saldo e retorna 1 se houver saldo suficiente; caso contrário, retorna 0 sem alterar o saldo. A função main já está pronta: ela lê o número de operações n (1 ≤ n ≤ 20) e n linhas no formato "d valor" (depósito) ou "w valor" (saque), com valores de 1 a 100000."Executar" roda seu código com a entrada acima. "Corrigir" testa com 4 entradas preparadas.
balance += amount;. Em withdraw, trate primeiro o caso de falha com if (amount > balance) return 0;.#include <stdio.h> int balance = 0; // saldo (variável global) void deposit(int amount) { balance += amount; } int withdraw(int amount) { if (amount > balance) { return 0; } balance -= amount; return 1; } int main(void) { int n; scanf("%d", &n); for (int i = 0; i < n; i++) { char cmd; int amount; scanf(" %c %d", &cmd, &amount); if (cmd == 'd') { deposit(amount); printf("Depósito %d: saldo %d\n", amount, balance); } else if (withdraw(amount)) { printf("Saque %d: saldo %d\n", amount, balance); } else { printf("Saque %d: saldo insuficiente (saldo %d)\n", amount, balance); } } printf("Saldo final: %d\n", balance); return 0; }
int balance = 0; dentro da função, é criada uma nova variável local com o mesmo nome, e a variável global não muda (ocultação de nome). Um saque igual ao saldo (a 2ª operação, w 500) deve dar certo, então a condição é amount > balance. Variáveis globais são práticas porque podem ser alteradas de qualquer lugar, mas, justamente por isso, fica difícil rastrear onde mudaram; use-as só quando necessário.int days_in_month(int y, int m), que recebe o ano y e o mês m (1 a 12) e retorna o número de dias desse mês, e a função int day_of_year(int y, int m, int d), que recebe ano, mês e dia e retorna qual é o dia do ano, contando a partir de 1º de janeiro. A função de ano bissexto is_leap e a função main já estão prontas. A entrada é sempre uma data válida (1 ≤ y ≤ 9999)."Executar" roda seu código com a entrada acima. "Corrigir" testa com 7 entradas preparadas.
{31, 28, 31, 30, ...} e retorne 29 se for fevereiro em ano bissexto. day_of_year é "a soma dos dias dos meses 1 a m−1 + d", então dá para fazer chamando days_in_month repetidamente.#include <stdio.h> int is_leap(int y) { return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0; } int days_in_month(int y, int m) { const int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; if (m == 2 && is_leap(y)) { return 29; } return days[m - 1]; } int day_of_year(int y, int m, int d) { int total = d; for (int i = 1; i < m; i++) { total += days_in_month(y, i); } return total; } int main(void) { int y, m, d; scanf("%d %d %d", &y, &m, &d); printf("Dias em %d/%d: %d\n", m, y, days_in_month(y, m)); printf("%d/%d/%d é o dia %d do ano\n", d, m, y, day_of_year(y, m, d)); return 0; }
days[m - 1]. Se o laço for até i <= m, os dias do próprio mês também são somados.void sort_array(int a[], int n), que ordena um array de int com n elementos em ordem crescente. O método é livre (bubble sort, selection sort etc.). A função print_array, que mostra o array, e a função main já estão prontas: a main lê n (1 ≤ n ≤ 100) e n inteiros e mostra o array antes e depois da ordenação."Executar" roda seu código com a entrada acima. "Corrigir" testa com 5 entradas preparadas.
i de 0 a n−2, faça um laço com j de 0 a n−2−i e troque os vizinhos se a[j] > a[j + 1]. A cada volta, o maior valor restante fica definido na ponta direita.#include <stdio.h> void print_array(const char label[], const int a[], int n) { printf("%s:", label); for (int i = 0; i < n; i++) { printf(" %d", a[i]); } printf("\n"); } void sort_array(int a[], int n) { for (int i = 0; i < n - 1; i++) { for (int j = 0; j < n - 1 - i; j++) { if (a[j] > a[j + 1]) { int tmp = a[j]; a[j] = a[j + 1]; a[j + 1] = tmp; } } } } int main(void) { int a[100]; int n; scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%d", &a[i]); } print_array("Antes", a, n); sort_array(a, n); print_array("Depois", a, n); return 0; }
j < n, a[j + 1] lê fora dos limites do array (a[n]); por isso usamos j < n - 1 - i.