Seu primeiro programa
por Huxley SterlingEntenda o conceito
Todo programa em C começa pela função main. Quando você executa o binário, o sistema chama main, que roda as instruções de cima para baixo e, ao terminar, devolve um número: 0 significa sucesso.
Para escrever na tela, usamos funções da biblioteca padrão declaradas em <stdio.h>. A diretiva #include <stdio.h> traz essas declarações; sem ela, o compilador não sabe o que é printf nem puts.
puts imprime um texto e já pula a linha. printf é mais flexível: ela só quebra a linha quando encontra \n e aceita especificadores de formato como %d (inteiro), %.2f (número com duas casas) e %s (texto), que são trocados pelos valores passados depois da vírgula.
C é compilada: o código-fonte vira um executável antes de rodar. Com o GCC, gcc -Wall -Wextra ola.c -o ola compila e ./ola executa. Os avisos de -Wall -Wextra apontam boa parte dos erros de iniciante.
- A execução começa em
int main(void)e oreturn 0;avisa ao sistema que deu tudo certo. #include <stdio.h>é obrigatório para usarprintfeputs.putsquebra a linha sozinha;printfsó quebra com\nno texto.- Em
printf, cada especificador (%d,%.2f,%s) recebe o próximo argumento, na ordem e no tipo certos;%%imprime o próprio%. - Compile com
gcc -Wall -Wextra arquivo.c -o programae rode com./programa.
Do conceito à prática
3 exemplos para ver a ideia funcionando.
01Olá, mundo com printf e puts
/* ola.c: o menor programa útil em C */
/* #include traz as declarações de printf e puts */
#include <stdio.h>
/* Todo programa em C começa a rodar pela função main */
int main(void)
{
/* printf escreve o texto; \n é a quebra de linha */
printf("Olá, mundo!\n");
/* puts escreve o texto e já acrescenta a quebra de linha */
puts("Bem-vindo à loja Daily.");
puts("Hoje tem cupom na vitrine.");
/* 0 avisa ao sistema que tudo correu bem */
return 0;
}
O programa mínimo: um #include, a função main e um return 0. Ele mostra as duas formas mais comuns de escrever na tela: printf, que precisa do \n para pular a linha, e puts, que pula sozinha.
Os comentários /* ... */ são ignorados pelo compilador e servem só para quem lê o código.
02Receita com várias linhas e caracteres especiais
/* receita.c: várias linhas, tabulação e caracteres especiais */
#include <stdio.h>
int main(void)
{
puts("=== Bolo de caneca ===");
/* \t insere uma tabulação, útil para recuar itens */
printf("Ingredientes:\n");
printf("\t- 4 colheres de farinha\n");
printf("\t- 2 colheres de açúcar\n");
printf("\t- 1 ovo\n");
/* Para mostrar aspas dentro da string, escape com \" */
printf("Dica: use a caneca \"grande\" do armário.\n");
/* Uma única chamada pode imprimir várias linhas */
printf("Modo de preparo:\n"
"1. Misture tudo na caneca.\n"
"2. Leve ao micro-ondas por 3 minutos.\n");
/* Para imprimir o próprio %, escreva %% */
printf("Rendimento: 100%% de uma porção.\n");
return 0;
}
Strings em C aceitam sequências de escape: \n quebra a linha, \t insere uma tabulação e \" coloca aspas dentro do texto. Já o % tem significado especial no printf, por isso o símbolo é escrito como %%.
O exemplo também mostra que strings vizinhas são unidas pelo compilador, o que permite quebrar um texto longo em várias linhas do código com uma única chamada de printf.
03Resumo de compra com especificadores de formato
/* cupom.c: printf com especificadores de formato */
#include <stdio.h>
#include <stdlib.h> /* EXIT_SUCCESS */
int main(void)
{
/* %s recebe texto, %d um inteiro e %.2f um número com 2 casas */
printf("Cliente: %s\n", "Ana");
printf("Itens no carrinho: %d\n", 3);
printf("Subtotal: R$ %.2f\n", 149.90);
/* Os valores entram na ordem dos especificadores */
printf("Cupom %s: %d%% de desconto\n", "BEMVINDO", 10);
/* Contas podem ser feitas direto nos argumentos */
printf("Desconto: R$ %.2f\n", 149.90 * 0.10);
printf("Total: R$ %.2f\n", 149.90 - 149.90 * 0.10);
/* %-12s alinha o texto à esquerda em 12 colunas; %6.2f usa 6 */
printf("%-12s%6.2f\n", "Frete", 15.00);
printf("%-12s%6.2f\n", "A pagar", 149.90 * 0.90 + 15.00);
/* EXIT_SUCCESS é o nome padrão para "terminou sem erro" */
return EXIT_SUCCESS;
}
Aqui o printf recebe valores: %s para o nome, %d para a quantidade e %.2f para os preços, sempre na ordem em que aparecem na string. As contas, como o desconto, são feitas direto nos argumentos.
Nas duas últimas linhas, %-12s reserva 12 colunas para o texto alinhado à esquerda e %6.2f reserva 6 para o número, o que deixa os valores alinhados. O return EXIT_SUCCESS, de <stdlib.h>, é um nome mais legível para o mesmo 0.
Agora é com você
Tente resolver no rascunho antes de abrir a resposta. Os códigos não são executados nesta página.
01Cartão do leitor da bibliotecaFácil
Escreva um programa que imprima o cartão de um leitor da biblioteca, com uma informação por linha, exatamente como na saída esperada.
- Incluir
<stdio.h>e escrever todo o código dentro deint main(void). - Usar
putspara cada uma das quatro linhas. - Terminar com
return 0;.
#include <stdio.h>
int main(void)
{
/* Imprima as quatro linhas do cartão aqui */
return 0;
}
Biblioteca Central
Leitor: Marcos Lima
Livros emprestados: 2
Devolução até: 20/10
Ver dica
Cada puts gera exatamente uma linha e já coloca a quebra no fim; você não precisa de \n.
Ver resposta
#include <stdio.h>
int main(void)
{
/* puts já coloca a quebra de linha no fim */
puts("Biblioteca Central");
puts("Leitor: Marcos Lima");
puts("Livros emprestados: 2");
puts("Devolução até: 20/10");
/* 0 indica que o programa terminou bem */
return 0;
}
Passo a passo
#include <stdio.h>traz a declaração deputs; sem ela o compilador não conhece a função e recusa a chamada.int main(void)é o ponto de entrada: o sistema chamamainao iniciar o programa, evoiddiz que ela não recebe argumentos.- Cada
puts("...")escreve o texto e acrescenta uma quebra de linha, então cada chamada vira exatamente uma linha da saída. - As linhas aparecem na mesma ordem das chamadas, porque o C executa as instruções de cima para baixo.
return 0;encerramaine devolve 0 ao sistema, o código que significa "terminou sem erro".
Por que funciona
Um programa em C é uma sequência de instruções dentro de main, executadas na ordem em que foram escritas. O cartão é só texto fixo, então basta uma chamada de saída por linha.
puts foi escolhida porque o texto não tem nenhum valor variável: ela é mais simples que printf e já cuida da quebra de linha, o que evita esquecer o \n no fim.
Erros comuns
- Esquecer o
#include <stdio.h>: em C23 o GCC para comimplicit declaration of function 'puts'. Coloque o include na primeira linha. - Escrever
puts("Leitor: Marcos Lima\n");: o\nextra soma-se à quebra queputsjá coloca e aparece uma linha em branco. Computs, não use\nno fim. - Esquecer o ponto e vírgula depois de uma chamada: o compilador acusa
expected ';' before ...na linha seguinte. Toda instrução termina com;. - Usar aspas simples (
puts('Biblioteca Central');): aspas simples são para um único caractere; texto vai sempre entre aspas duplas.
Outra forma de resolver
Dá para usar printf com \n explícito em cada linha, ou até uma única chamada com strings vizinhas, que o compilador junta:
printf("Biblioteca Central\n"
"Leitor: Marcos Lima\n"
"Livros emprestados: 2\n"
"Devolução até: 20/10\n");
Essa forma é preferível quando o bloco de texto é grande e fixo, como um menu ou um aviso.
Saída esperada
Biblioteca Central
Leitor: Marcos Lima
Livros emprestados: 2
Devolução até: 20/10
02Etiqueta de preço da lojaMédio
Imprima a etiqueta de um caderno com nome, estoque, preço, porcentagem de promoção e preço final com desconto. O preço final deve ser calculado pelo programa, não digitado.
- Usar
printfcom%spara o nome,%dpara estoque e promoção e%.2fpara os preços. - Mostrar o símbolo de porcentagem com
%%. - Calcular o preço final (
18.50com 20% de desconto) no argumento doprintf.
#include <stdio.h>
int main(void)
{
printf("Produto: %s\n", "Caderno");
/* Complete: estoque, preço, promoção e preço final */
return 0;
}
Produto: Caderno
Estoque: 42 unidades
Preço: R$ 18.50
Promoção: 20% off
Preço final: R$ 14.80
Ver dica
Pagar com 20% de desconto é o mesmo que pagar 80% do preço.
Ver resposta
#include <stdio.h>
int main(void)
{
/* %s para texto, %d para inteiro */
printf("Produto: %s\n", "Caderno");
printf("Estoque: %d unidades\n", 42);
/* %.2f mostra o número com duas casas decimais */
printf("Preço: R$ %.2f\n", 18.50);
/* %% imprime o caractere % */
printf("Promoção: %d%% off\n", 20);
/* A conta é feita no próprio argumento */
printf("Preço final: R$ %.2f\n", 18.50 * 0.80);
return 0;
}
Passo a passo
printf("Produto: %s\n", "Caderno")troca o%spelo texto passado depois da vírgula.%drecebe o inteiro42; o restante da string (" unidades") é impresso como está.%.2fmostra18.50com duas casas decimais; sem o.2, o padrão seria seis casas (18.500000).- Em
"Promoção: %d%% off\n", o%dvira20e o%%vira um único%, porque um%sozinho seria lido como início de especificador. 18.50 * 0.80é calculado antes da chamada e o resultado (14.80) entra no%.2f.- Cada string termina com
\n, já que, diferente deputs,printfnão quebra a linha sozinho.
Por que funciona
printf lê a string de formato da esquerda para a direita: o texto comum vai direto para a saída e cada especificador (%s, %d, %.2f) é substituído pelo próximo argumento da lista. Por isso a ordem e o tipo dos argumentos precisam combinar com os especificadores.
O desconto de 20% é o mesmo que pagar 80% do preço, e a multiplicação com double resulta em 14.8, que %.2f exibe como 14.80.
Erros comuns
- Trocar o tipo:
printf("Estoque: %d\n", 42.0);passa umdoublepara%d. O comportamento é indefinido e costuma imprimir lixo; o-Wallavisa. Use%dpara inteiros e%fpara números com vírgula. - Escrever
%sozinho ("%d% off"): oprintftenta ler% ocomo especificador e a saída sai errada. Para o símbolo, use%%. - Esquecer o
\n: as linhas grudam (Produto: CadernoEstoque: 42 unidades). Termine cada string com\n. - Usar
%.2d: a precisão em%dsignifica número mínimo de dígitos, não casas decimais. Para preço, use%.2f.
Outra forma de resolver
Os valores podem ficar em variáveis com nome, o que deixa a conta mais legível:
double preco = 18.50;
int desconto = 20;
printf("Preço final: R$ %.2f\n", preco * (100 - desconto) / 100.0);
É a melhor escolha quando o mesmo valor aparece em mais de uma linha, como aqui o preço.
Saída esperada
Produto: Caderno
Estoque: 42 unidades
Preço: R$ 18.50
Promoção: 20% off
Preço final: R$ 14.80
03Placar alinhado da rodadaDesafio
Monte o placar de uma rodada de jogo em forma de tabela, com colunas alinhadas para jogador, pontos e partidas, uma linha de total e a média de pontos com uma casa decimal.
- Usar o mesmo formato
%-10s%8d%10d(ou%-10s%8s%10sno cabeçalho) em todas as linhas da tabela. - Separadores com 28 traços, a soma das larguras das colunas.
- Calcular total e média nos argumentos do
printf, sem digitar os resultados. - Mostrar a média com
%.1f, sem perder a parte decimal na divisão.
#include <stdio.h>
int main(void)
{
puts("PLACAR DA RODADA");
/* Cabeçalho, separador, três jogadores, separador, total e média */
return 0;
}
PLACAR DA RODADA
Jogador Pontos Partidas
----------------------------
Lia 1250 5
Davi 980 4
Bia 1430 6
----------------------------
Total 3660 15
Média de pontos: 1220.0
Ver dica
O número entre % e a letra é a largura da coluna; o - alinha à esquerda. Para a média, pense no que acontece ao dividir dois inteiros.
Ver resposta
#include <stdio.h>
int main(void)
{
puts("PLACAR DA RODADA");
/* Mesmo formato no cabeçalho e nas linhas: as colunas ficam alinhadas */
printf("%-10s%8s%10s\n", "Jogador", "Pontos", "Partidas");
puts("----------------------------");
/* %-10s: texto à esquerda em 10 colunas; %8d e %10d: números à direita */
printf("%-10s%8d%10d\n", "Lia", 1250, 5);
printf("%-10s%8d%10d\n", "Davi", 980, 4);
printf("%-10s%8d%10d\n", "Bia", 1430, 6);
puts("----------------------------");
/* Totais calculados nos argumentos do printf */
printf("%-10s%8d%10d\n", "Total", 1250 + 980 + 1430, 5 + 4 + 6);
/* Dividir por 3.0 (não 3) mantém as casas decimais */
printf("Média de pontos: %.1f\n", (1250 + 980 + 1430) / 3.0);
return 0;
}
Passo a passo
puts("PLACAR DA RODADA")imprime o título; não há valores a formatar, entãoputsbasta.- O cabeçalho usa
%-10s%8s%10s: o-alinha "Jogador" à esquerda em 10 colunas, e%8se%10salinham os títulos à direita em 8 e 10 colunas. - O separador tem 28 traços, exatamente 10 + 8 + 10, a largura somada das três colunas.
- Cada jogador usa
%-10s%8d%10d, as mesmas larguras do cabeçalho, então os números ficam sob os títulos, alinhados pela direita. - A linha de total soma os valores direto nos argumentos (
1250 + 980 + 1430); o resultado é uminte casa com%8d. - A média divide por
3.0: com um operandodouble, a divisão mantém a parte decimal e o resultado combina com%.1f. %.1farredonda para uma casa decimal, o que dá1220.0.
Por que funciona
O alinhamento sai de graça da largura de campo do printf: o número entre % e a letra diz quantas colunas o valor ocupa, completando com espaços. Usar as mesmas larguras em todas as linhas faz cada coluna começar e terminar no mesmo lugar, como numa tabela.
A largura mínima nunca corta o valor; se ele for maior, a coluna simplesmente cresce. Por isso as larguras foram escolhidas com folga para o maior número (1430) e o maior nome (Total). Os nomes estão sem acento de propósito: letras como á ocupam 2 bytes em UTF-8 e o printf conta bytes, o que desalinharia a coluna.
Erros comuns
- Larguras diferentes no cabeçalho e nas linhas: com
%-10s%6sno título e%-10s%8dnos dados, os números ficam deslocados dois espaços. Use exatamente as mesmas larguras. - Esquecer o
-em%-10s:%10salinha o nome à direita e a tabela ficaLia 1250. O-é o que encosta o texto à esquerda. - Dividir por
3:(1250 + 980 + 1430) / 3é divisão inteira e resulta em1220do tipoint; passar isso para%.1fé comportamento indefinido e imprime lixo (o-Wallavisa). Divida por3.0. - Contar os traços errado: um separador de 26 ou 30 traços não fecha com a tabela. Some as larguras das colunas (10 + 8 + 10 = 28).
Outra forma de resolver
A largura pode vir de um argumento com *, o que evita repetir números mágicos:
printf("%-*s%*d%*d\n", 10, "Lia", 8, 1250, 10, 5);
Ela compensa quando a largura muda com os dados, por exemplo calculada a partir do maior nome. Para uma tabela fixa como esta, as larguras escritas na string são mais fáceis de ler.
Saída esperada
PLACAR DA RODADA
Jogador Pontos Partidas
----------------------------
Lia 1250 5
Davi 980 4
Bia 1430 6
----------------------------
Total 3660 15
Média de pontos: 1220.0