Uma função permite que você determine um trecho de código que executa uma tarefa específica e que você reutilize esse trecho de código sempre que necessário, sem a necessidade de recriar ou redigitar aquele código. As funções são os recursos mais importante em C e estão presentes em grande parte das linguagens de programação.
O próprio main do C é uma função, assim como o printf e o scanf, mas essas são funções internas da linguagem.
Veja como trabalhamos com funções em C:
void escrevaNome(); // Isso avisa o compilador que existem funções.
int main(void) {
setlocale(LC_ALL,"portuguese"); // Isso não tem nada a ver com a função, apenas corrige acentuações. Importe locale.h.
escrevaNome(); // Invocação da Função.
return 0;
}
// Abaixo é a função, no caso, "escrevaNome()" é o nome que podemos definir pra função. Foi definida como void pra não retornar nada.
void escrevaNome() {
printf("Introdução à Funções em C!\n");
}
Dentro da função principal int main, podemos colocar a invocação da função mais de uma vez, para ela ser executada mais vezes, por exemplo:
int main(void) {
setlocale(LC_ALL,"portuguese");
escrevaNome();
escrevaNome();
escrevaNome();
escrevaNome();
return 0;
}
PS: É recomendado que cada função faça apenas uma coisa por vez.
Também é possível passar parâmetros nas funções, passando as variáveis (por exemplo funcao(int num, char let)
. Nos parâmetros também podemos passar arrays, passando a variável com ponteiro, algo tipo funcao(int* vetorpassado)
.
Elas também podem retornar valores, com a instrução return
no final dela, só que nesse caso a função não será void, e sim do mesmo tipo do retorno (por exemplo, int, char ou float). Veja por exemplo:
int quadrado(int n);
int main(void) {
setlocale(LC_ALL,"portuguese");
int num = 5;
printf("O quadrado de %d é %d!", num, quadrado(num));
return 0;
}
int quadrado(int n) {
return n * n;
}
Geralmente, os programadores de linguagens estruturadas costumam chamar as funções sem retorno (com void) de procedimentos, só chamam de funções mesmo as que retornam valores (como uma função int ou char, por exemplo).
PS: Também é possível implementar a funcão antes do método main, nesse caso, dispensa a indicação do mesmo, mas não é recomendado.
Caso deseje inicializar uma variável de um parâmetro com um valor padrão, coloque apenas na indicação, não coloque nada na função (a não ser que ela venha antes do main, nesse caso sim pode ser colocada a inicialização diretamente nela).
PS: Um return
encerra a execução da função, ao retornar um valor. Mesmo procedimentos void podem ter um return sem nenhum conteúdo finalizado com ponto e vírgula para isso (no caso return;
).
O escopo de uma variável determina como e onde uma variável é utilizada dentro de um programa.
Existem três escopos distintos em C:
As variáveis locais são declaradas dentro de uma função. Elas não podem ser acessadas de fora da função, nem serem usadas diretamente por outras funções. Quando a função onde a variável local foi declarada termina sua execução (quando retorna), a variável é "destruída" (memória desalocada).
Os parâmetros declarados em uma função são variáveis locais à função. Portanto, só podem ser acessados diretamente a partir de sua função, e sua existência cessa quando a função termina sua execução.
As variáveis globais são declaradas fora das funções, incluindo a função main. Assim, se tornam acessíveis a partir de qualquer parte do programa, incluindo dentro de qualquer função presente. Eles permanecem disponíveis durante toda a execução do programa.
PS: Podemos ter duas variáveis com o mesmo nome em um programa, se uma delas for local e a outra for globa, nesse caso, a variável local prevalece em seu escopo. Mas por conta da clareza do código, é altamente desaconselhável.
Veja um exemplo do escopo de variáveis:
void escrevaValor(); // Protótipo da função, apenas avisa que existe tal função no programa.
int numero = 15; // Global
int main(void) {
setlocale(LC_ALL,"portuguese"); // Importar locale.h
printf("O número é %d\n", numero);
escrevaValor();
return 0;
}
void escrevaValor() {
int dobro = numero * 2; // Local
printf("E o dobro é %d\n", dobro);
}
No código acima, se pegarmos a variável global (no caso, a numero) e colocarmos dentro da função (escrevaValor()), ele dará erro, porque assim ela se tornará local e só funciona dentro da função da qual está.
Um array é uma estrutura homogênea que mantém uma série de dados do mesmo tipo. Podemos acessar os elementos individuais por meio de um índice, geralmente numérico. Possuem tamanho fixo. Os arrays são contados a partir do 0.
Um array de uma dimensão pode ser chamado de vetor. Um array bidimensional é conhecido como matriz.
Veja um exemplo de uso de vetores:
float notas[4] = {7.5, 8.0, 6.5, 3.5}; // Itens do Array, de 0 à 3, o número dentro dos colchetes predefine as posições do array.
int i;
for(i = 0; i < 4; i++) {
printf("Nota %d = %4.2f\n", i + 1, notas[i]); // i define a posição do array, é somado com 1 pra exibir de 1 à 4.
}
Veja outro exemplo, só que o array não será inicializado, e terá valores passados pelo usuário:
float notas[4];
int i;
for(i = 0; i < 4; i++) {
printf("Entre com a %dª nota do aluno: ", i + 1);
scanf("%f", ¬as[i]);
}
for(i = 0; i < 4; i++) {
printf("Nota %d = %4.2f\n", i + 1, notas[i]);
}
PS: Podemos também ler o número de casas de um vetor através do método sizeof (dividindo o sizeof do vetor pelo sizeof do tipo dele), dessa forma:
float notas[4];
int i;
for(i = 0; i < sizeof(notas) / sizeof(float); i++) {
printf("Entre com a %dª nota do aluno: ", i + 1);
scanf("%f", ¬as[i]);
}
for(i = 0; i < sizeof(notas) / sizeof(float); i++) {
printf("Nota %d = %4.2f\n", i + 1, notas[i]);
}
Caso seja para ler a quantidade de casas de uma sequência de caracteres, use o método strlen()
, dessa forma:
char *frase;
frase = "Isso é uma sequência de char!";
int i;
for(i = 0; i < strlen(frase); i++) {
printf("%dº caractere: %c\n", i + 1, frase[i]);
}
O Bubblesort (classificação por bolhas) toma um vetor que tenha vários itens e ordenar os mesmos. Isso é muito útil para encontrar um valor com mais rapidez num código.
Veja um exemplo abaixo:
setlocale(LC_ALL,"portuguese"); // Importar locale.h.
int numeros[TAM]; // Array com constante, colocar #define no começo do programa.
int i, aux, cont;
printf("Entre com dez números para preencher o array (Pressione Enter após cada um):\n");
for(i = 0; i < TAM; i++) {
scanf("%d", &numeros[i]);
}
printf("Ordem atual dos itens no array:\n");
for(i = 0; i < TAM; i++) {
printf("%4d", numeros[i]);
}
// Ordenação Bubblesort.
for(cont = 1; cont < TAM; cont++) {
for(i = 0; i < TAM - 1; i++) {
if(numeros[i] > numeros[i + 1]) {
aux = numeros[i];
numeros[i] = numeros[i + 1];
numeros[i + 1] = aux;
}
}
}
printf("\nElementos do array em ordem crescente:\n");
for(i = 0; i < TAM; i++) {
printf("%4d", numeros[i]);
}
Como visto acima, o Bubblesort nada mais é do que uma estrutura com dois for encadeados e um if dentro o segundo for, isso que fará a ordenação.
PS: Para usar constantes, devemos colocar #define
no formato #define NOMEDACONSTANTE DADO (no caso acima é #define TAM 10
, para definir a quantidade de espaços do array, de 0 a 9). O #define é colocado junto com as bibliotecas, na parte superior do programa (sem ;), e pode ser usado também com comandos (como #define FRASE printf("Frase")
e chamando apenas por FRASE;
). Apesar de ser possível exibir usando números diretamente nos array, podemos usar as constantes. Em versões mais recentes do C podemos definir constantes simplesmente colocando const
antes do tipo, como por exemplo const int TAM = 10;
.
Uma matriz é um tipo de array que possuí duas dimensões (como se tivesse linhas e colunas, tipo uma tabela). As linhas e colunas são númeradas a partir do 0. Assim como os vetores, as matrizes só suportam dados do mesmo tipo. A grosso modo, são arrays dentro de arrays.
Veja uma representação gráfica de uma matriz com números:
7,5 | 6,8 | 9,6 | 6,7 |
6,5 | 6,3 | 8,4 | 7,6 |
5,7 | 8,6 | 9,0 | 4,5 |
4,5 | 5,8 | 6,8 | 7,0 |
3,6 | 7,6 | 8,1 | 6,5 |
Veja um exemplo de declaração de matriz:
setlocale(LC_ALL,"portuguese"); // Importar locale.h.
int linha, coluna;
// Matriz abaixo, não esquecer de definir as constantes no início do código, com NUM_L 5 e NUM_C 4.
float notas[NUM_L][NUM_C] = {{7.5, 6.8, 9.6, 6.7},
{6.5, 6.3, 8.4, 7.6},
{5.7, 8.6, 9.0, 4.5},
{4.5, 5.8, 6.8, 7.0},
{3.6, 7.6, 8.1, 6.5}};
printf("Exibindo o conteúdo da matriz declarada e inicializada:\n\n");
for(linha = 0; linha < NUM_L; linha++) {
for(coluna = 0; coluna < NUM_C; coluna++) {
printf("%5.1f", notas[linha][coluna]);
}
printf("\n");
}
printf("\nValor do elememnto na 2ª linha, 3ª coluna: %4.2f\n", notas[1][2]); // Aqui pode ter os números alterados, esse é só um exemplo. Também pode ter um scanf aqui.
Como visto acima, os dois for que farão a exibição de todos os dados da matriz. Não esqueça das constantes, que no caso, são a quantidade de colunas e linhas da matriz, e não a contagem delas.
Para usarmos comandos do CMD ou terminal, usamos o system (import stdlib.h) para isso, dessa forma:
#include <stdio.h>
#include <stdlib.h>
int main() {
system("color 79");
system("title System em C");
system("pause");
return 0;
}
A maioria dos comandos do terminal (CMD para programas do Windows e Terminal para sistemas Unix) do sistema podem ser usados normalmente, mas os comandos de caminhar em pastas (cd) costumam dar erro, principalmente pelo uso de barras e também pelo fato do system não manter os dados após cada chamada dele.
Para caminharmos por pastas no sistema, usamos o chdir para isso (importe unistd.h), dessa forma:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
chdir("C:/Windows/System32");
system("dir");
return 0;
}
Só que variáveis de ambiente como %username% e %userprofile% no Windows (ou coisas como $HOME no Unix), não funcionam o chdir, para isso, usamos o getenv (sem qualquer símbolo de indicação de variável), dessa forma (importe unistd.h):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
chdir(getenv("USERPROFILE"));
chdir("Desktop");
system("dir");
return 0;
}
Dessa forma, facilita a manipulação de arquivos, podendo criar funções para criar, mover ou deletar arquivos.
PS: No Windows, o chdir pode não funcionar, nesse caso use SetCurrentDirectory()
(importe windows.h) para isso. E mesmo no Windows, em ambos os casos, utilize a barra pro lado direito, se for usar pra esquerda coloque duas (tipo \\
). Isso acontece porque barras pra esquerda são interpretadas como sequências de escape.
O getenv funciona com esse parâmetros:
Variável | Conteúdo Exibido |
---|---|
USERPROFILE | C:\Users\UsuarioAtual |
PROGRAMDATA | C:\Programdata |
ALLUSERSPROFILE | C:\Programdata |
WINDIR | C:\Windows |
SYSTEMROOT | C:\Windows |
PROGRAMFILES | C:\Program Files |
COMMONPROGRAMFILES | C:\Program Files\Common Files |
USERNAME | "UsuarioAtual" |
COMPUTERNAME | Nome do Computador |
LOCALAPPDATA | C:\Users\Usuário Atual\AppData\Local |
APPDATA | C:\Users\Usuário Atual\AppData\Roaming |
ERRORLEVEL | Código de Erro do Último Comando (quando é diferente de 0). |
CD | Pasta Atual |
USERDOMAIN | Nome do Computador |
SYSTEMDRIVE | C: |
HOMEDRIVE | C: |
SYSTEMDIRECTORY | C:\Windows\System32 |
COMSPEC | C:\Windows\System32\cmd.exe |
TEMP | C:\Users\Usuário Atual\AppData\Local\Temp |
TMP | C:\Users\Usuário Atual\AppData\Local\Temp |
HOMEPATH | \Users\Usuário Atual |
PATH | Retorna o path do sistema |
PATHEXT | Retorna as extensões de executáveis |
OS | Retorna o nome do Sistema Operacional |
PROCESSOR_IDENTIFIER | Retorna dados sobre o processador |
PROCESSOR_ARCHITECTURE | Retorna a arquitetura do processador |
Para usar em Linux, o processo é o mesmo, só mudando a navegação entre pastas (seria coisas como /usr/local/bin) e os comandos do getenv, que são esses:
Variável | Conteúdo Exibido |
---|---|
HOME | /home/UsuarioAtual |
USER | "UsuarioAtual" |
LOGNAME | "UsuarioAtual" |
PWD | Diretório Atual |
LANG | Idioma Atual |
SHELL | /bin/bash (ou o Shell Atual) |
TERM | Tipo de Terminal Usado |
PATH | Diretórios a Pesquisar |
E-mail Definido | |
OSTYPE | Tipo de Sistema Usado |