Semana 15 — Manipulação de arquivos (simples)¶
Nesta semana
Unidade 3 · Seg 16/11 · Qua 18/11 · Sex 20/11 · ⚠️ feriado: 20/11 (Consciência Negra)
Chegamos à última semana de conteúdo do semestre. Todo programa que escrevemos até agora tinha um "defeito" silencioso: quando ele terminava, tudo o que estava na memória desaparecia. Nesta semana resolvemos isso. Vamos aprender a gravar dados em arquivos — no disco, de forma permanente — e a lê-los de volta em uma execução futura. É a ideia de persistência, e ela transforma um programa que "esquece tudo" em um programa que guarda o trabalho do usuário.
O tema fecha com chave de ouro a jornada da Unidade 3: depois de entender endereços, ponteiros e memória, os arquivos são a ponte entre o que vive dentro do programa (RAM) e o que precisa sobreviver a ele (disco). Como há feriado na sexta (20/11), aproveite a segunda e a quarta com disciplina — e reserve um tempo próprio para o estudo dirigido.
🎯 Objetivos de aprendizagem¶
Ao final desta semana, você deverá ser capaz de:
- explicar o que é persistência e por que dados na RAM são perdidos ao fim do programa, enquanto arquivos no armazenamento sobrevivem;
- abrir um arquivo com
fopen, escolhendo o modo correto ("r","w","a"e variantes), e fechar comfclose; - verificar sempre se a abertura deu certo, testando o retorno contra
NULL; - escrever em arquivos-texto com
fprintfefputs; - ler de arquivos-texto com
fscanfefgets, detectando corretamente o fim do arquivo (EOF); - salvar e recarregar estruturas do curso (vetores e vetores de
struct) em disco, integrando tudo o que você aprendeu.
📖 Segunda — Estudo do conteúdo¶
1. O problema: tudo o que a RAM guarda, ela esquece¶
Retome a Semana 01. Lá vimos que, quando um
programa executa, ele é carregado para a memória RAM, e é ali que vivem
todas as suas variáveis, vetores, structs e blocos alocados com malloc.
A RAM é rápida — mas é volátil: ao encerrar o programa (ou desligar o
computador), o conteúdo se perde.
Isso explica um incômodo que você talvez já tenha sentido: você roda um programa
de cadastro, digita 50 alunos com todo o carinho, o programa imprime o
relatório, retorna 0… e, na próxima execução, está tudo vazio de novo. Os
dados nunca saíram da RAM.
| Onde os dados vivem | Velocidade | Duração | Exemplos |
|---|---|---|---|
| Memória RAM | muito rápida | volátil (some ao terminar) | variáveis, vetores, malloc |
| Armazenamento (HD/SSD) | mais lenta | permanente (sobrevive) | arquivos, fotos, documentos |
A solução é gravar os dados importantes em um arquivo no armazenamento. Um arquivo é permanente: ele continua existindo depois que o programa termina, depois que você fecha o editor e mesmo depois de reiniciar a máquina. Essa capacidade de salvar dados que sobrevivem ao fim do programa é o que chamamos de persistência.
flowchart LR
subgraph exec["Durante a execucao"]
R["dados na RAM<br/>(volateis)"]
end
R -->|"escrita (fprintf)"| A["arquivo no disco<br/>(permanente)"]
A -->|"leitura (fscanf)"| R2["dados de volta na RAM<br/>(proxima execucao)"]
Curiosidade 💡 — a bancada e a despensa
Na Semana 01 comparamos a RAM com a bancada onde o cozinheiro trabalha, e o armazenamento com a despensa/geladeira. A bancada é perto e prática, mas você não guarda comida ali de um dia para o outro — ela é esvaziada. O que você quer manter vai para a despensa. Gravar um arquivo é exatamente isso: tirar o dado da bancada volátil e guardá-lo na despensa permanente.
2. O tipo FILE * e a função fopen¶
Em C, um arquivo aberto é representado por um ponteiro para arquivo, do tipo
FILE * (o tipo FILE está declarado em <stdio.h>). Você não precisa
saber o que há dentro de um FILE — ele é uma "ficha de controle" que o sistema
usa para saber qual arquivo é, onde você parou de ler/escrever, etc. Você só
guarda o FILE * e o passa para as funções de arquivo.
Para abrir um arquivo, usamos fopen, que recebe o nome do arquivo e o
modo de abertura, e devolve um FILE *:
O modo (o segundo argumento, uma string) diz o que você pretende fazer com o arquivo. Os três modos essenciais:
| Modo | Nome | O que faz | Se o arquivo… |
|---|---|---|---|
"r" |
read (leitura) | abre para ler | não existe → falha (NULL) |
"w" |
write (escrita) | abre para escrever | existe → APAGA todo o conteúdo!; não existe → cria |
"a" |
append (acréscimo) | escreve no fim | não existe → cria; existe → preserva e acrescenta |
Preste muita atenção ao "w": ele cria o arquivo se não existir, mas se o
arquivo já existe, ele zera o conteúdo antes de você escrever a primeira
linha. Já o "a" (append) preserva o que estava lá e só acrescenta ao
final — perfeito para um log ou um diário.
O modo \"w\" apaga o conteúdo existente
Abrir um arquivo em "w" descarta imediatamente tudo o que havia nele —
mesmo que você nunca chegue a escrever nada. Se o objetivo é acrescentar
sem perder o que já existe, use "a". Trocar um pelo outro é um erro que
"come" dados silenciosamente.
Existem também as variantes com +, para leitura e escrita ao mesmo tempo:
"r+"— abre para ler e escrever (o arquivo precisa existir);"w+"— cria/apaga e permite ler e escrever;"a+"— abre para ler e acrescentar no fim.
Por ora, foque nos três básicos ("r", "w", "a"); as variantes ficam de
conhecimento para quando você precisar.
Curiosidade 💡 — texto × binário (\"rb\", \"wb\")
Você verá modos com um b, como "rb" ou "wb". O b significa binário:
os dados são gravados byte a byte, exatamente como estão na memória
(usando fread/fwrite, que veremos de leve na seção 8). Sem o b, o
arquivo é tratado como texto: legível em qualquer editor, com números e
letras escritos como caracteres. Nesta semana trabalhamos com arquivos de
texto, que são mais simples de entender e depurar (você abre no Bloco de
Notas e lê).
3. SEMPRE verifique se abriu: o teste == NULL¶
fopen pode falhar. Motivos comuns: o arquivo não existe (no modo "r"),
você não tem permissão para acessá-lo, o disco está cheio, o caminho está
errado. Quando falha, fopen não trava o programa — ele apenas devolve
NULL, aquele ponteiro "para lugar nenhum" que estudamos na
Semana 10.
Por isso, todo fopen deve ser seguido de uma verificação:
FILE *f = fopen("dados.txt", "r");
if (f == NULL) {
printf("Erro: nao foi possivel abrir o arquivo.\n");
return 1; // encerra sinalizando erro (valor != 0)
}
// ... aqui em diante, f e' seguro de usar ...
Se você não verificar e o arquivo não abriu, f valerá NULL, e usar
fprintf(f, ...) ou fscanf(f, ...) sobre um ponteiro nulo provoca
comportamento indefinido — normalmente um travamento (o famoso segmentation
fault da Semana 10). Este teste é tão importante quanto o & no scanf: é um
reflexo que você deve treinar.
Não confie que o arquivo abriu
Nunca escreva fscanf(f, ...) sem antes ter checado if (f == NULL). Um
caminho errado, uma letra a mais no nome, um arquivo que não existe — tudo
isso resulta em NULL, e ignorar isso é um dos bugs mais comuns (e mais
frustrantes) com arquivos.
4. Ao terminar, fclose¶
Quando você não precisa mais do arquivo, feche-o com fclose:
Fechar um arquivo faz duas coisas importantes:
- Libera recursos — o sistema operacional tem um limite de arquivos abertos ao mesmo tempo; deixar arquivos abertos "vaza" esse recurso.
- Garante a gravação — o que você "escreveu" pode ainda estar num buffer
temporário (veja a curiosidade adiante). O
fclosedescarrega esse buffer para o disco. Esquecer ofclosepode fazer com que parte do que você escreveu nunca chegue ao arquivo.
A regra é simétrica e fácil de lembrar: para cada fopen que deu certo, um
fclose.
Curiosidade 💡 — o buffer e o fflush
Escrever no disco a cada caractere seria lento. Por isso, a stdio acumula o
que você escreve em uma área temporária na memória, o buffer, e só
descarrega de fato no disco de tempos em tempos (quando o buffer enche,
quando você chama fflush(f), ou quando faz fclose). Isso explica um
fenômeno curioso: se o programa trava antes do fclose, as últimas
linhas "escritas" podem sumir — elas estavam no buffer, não no disco.
Fechar o arquivo (ou chamar fflush) resolve isso.
5. Escrita em arquivo-texto: fprintf e fputs¶
Escrever em arquivo é praticamente idêntico a imprimir na tela. A função
principal é fprintf, que é igual ao printf — só que o primeiro
argumento é o FILE * de destino:
Compare:
printf("Media: %.2f\n", media); // escreve na TELA
fprintf(f, "Media: %.2f\n", media); // escreve no ARQUIVO f
Mesmíssima string de formato, mesmos especificadores (%d, %f, %c, %s…),
mesmas sequências de escape (\n, \t). A única diferença é para onde o
texto vai.
Há também fputs, que escreve uma string já pronta (sem formatação):
Um exemplo salvando vários registros de uma vez:
#include <stdio.h>
int main(void) {
FILE *f = fopen("notas.txt", "w"); // CRIA (ou apaga) e abre para escrita
if (f == NULL) {
printf("Erro ao abrir o arquivo para escrita.\n");
return 1;
}
// grava tres registros: nome e nota
fprintf(f, "Ana %.1f\n", 9.5);
fprintf(f, "Bruno %.1f\n", 7.0);
fprintf(f, "Carla %.1f\n", 8.25);
fclose(f); // fecha: garante que tudo foi para o disco
printf("Arquivo notas.txt gravado com sucesso.\n");
return 0;
}
Depois de rodar, abra notas.txt em qualquer editor de texto: você verá,
gravadas em disco, as três linhas. Elas continuarão lá quando o programa
terminar — este é o momento em que a persistência acontece de verdade.
6. Leitura de arquivo-texto: fscanf, fgets e o fim do arquivo¶
Para ler, o espelho do scanf é o fscanf — mesma ideia, com o FILE *
na frente:
Assim como o scanf na leitura de double usa %lf, o fscanf também:
O ponto novo — e essencial — é: como saber que o arquivo acabou? Você não
sabe de antemão quantas linhas ele tem. A resposta é o valor EOF
(End Of File, "fim do arquivo"), uma constante especial de <stdio.h>.
O fscanf devolve a quantidade de itens que conseguiu ler. Quando chega ao
fim do arquivo (não há mais o que ler), ele devolve EOF. Esse é o jeito
mais seguro de fazer um laço de leitura: ler no próprio teste do laço e
parar quando o retorno for EOF.
#include <stdio.h>
int main(void) {
FILE *f = fopen("notas.txt", "r"); // abre para leitura
if (f == NULL) {
printf("Erro: arquivo notas.txt nao encontrado.\n");
return 1;
}
char nome[50];
double nota;
// le um par (nome nota) por vez; para quando fscanf nao ler os 2 itens
while (fscanf(f, "%s %lf", nome, ¬a) == 2) {
printf("%s tirou %.2f\n", nome, nota);
}
fclose(f);
return 0;
}
Repare no teste == 2: pedimos ao fscanf para ler dois itens (um %s e um
%lf). Enquanto ele conseguir ler os dois, o laço continua; quando o arquivo
acaba (ou o formato não bate), ele devolve algo diferente de 2 (no fim do
arquivo, EOF), e o laço para. Comparar o retorno com a quantidade esperada
é uma técnica robusta.
Também é muito comum ler linha a linha com fgets, que lê uma linha
inteira (incluindo espaços) para dentro de um vetor de char:
char linha[100];
while (fgets(linha, 100, f) != NULL) { // le ate uma linha; NULL no fim
printf("Linha lida: %s", linha); // (a propria linha ja traz o \n)
}
O fgets devolve NULL quando não há mais nada para ler — daí o teste
!= NULL no laço. Ele é ótimo quando cada linha é um "texto livre" que você quer
processar depois.
O cuidado clássico com feof
Existe a função feof(f), que devolve verdadeiro depois que uma leitura
"bateu" no fim do arquivo. É tentador escrever while (!feof(f)) { fscanf(...); ... },
mas isso costuma processar o último registro DUAS vezes. O motivo: o
feof só acusa fim após uma leitura falhar — então, no fim, o fscanf
falha, mas o corpo do laço ainda roda uma vez com os valores antigos. A
regra de ouro: teste o retorno da própria leitura (fscanf(...) == 2,
fgets(...) != NULL), e não confie em feof como condição do laço.
Curiosidade 💡 — stdin, stdout e stderr já são FILE *
Você deve estar pensando: "como o fscanf/fprintf se parecem tanto com
scanf/printf?". Não é coincidência. O teclado (stdin), a tela
(stdout) e a saída de erros (stderr) são, na verdade, arquivos já
abertos para você — três FILE * prontos, definidos em <stdio.h>. Ou
seja: printf("oi\n") é essencialmente fprintf(stdout, "oi\n"), e
scanf("%d", &x) é fscanf(stdin, "%d", &x). Os scanf/printf são apenas
atalhos que já usam esses arquivos-padrão. Você conhece arquivos desde a
Semana 01 sem saber!
7. Exemplo completo: salvar e recarregar um vetor de struct¶
Agora vamos juntar tudo com o que você viu na
Semana 14: um vetor de struct. Vamos cadastrar
alguns alunos na memória, gravá-los em um arquivo e, em seguida, ler de
volta — provando que os dados sobreviveram.
#include <stdio.h>
#define MAX 100
typedef struct {
char nome[50];
int matricula;
double media;
} Aluno;
// grava um vetor de alunos em um arquivo-texto
void salvar(const char *caminho, Aluno v[], int n) {
FILE *f = fopen(caminho, "w"); // "w": cria/apaga o arquivo
if (f == NULL) {
printf("Erro ao abrir %s para escrita.\n", caminho);
return;
}
fprintf(f, "%d\n", n); // 1a linha: quantos alunos
for (int i = 0; i < n; i++) {
// um aluno por linha: nome matricula media
fprintf(f, "%s %d %.2f\n", v[i].nome, v[i].matricula, v[i].media);
}
fclose(f);
}
// le os alunos de volta; devolve quantos foram lidos
int carregar(const char *caminho, Aluno v[]) {
FILE *f = fopen(caminho, "r"); // "r": leitura
if (f == NULL) {
printf("Erro ao abrir %s para leitura.\n", caminho);
return 0;
}
int n = 0;
fscanf(f, "%d", &n); // le a quantidade
for (int i = 0; i < n; i++) {
fscanf(f, "%s %d %lf", v[i].nome, &v[i].matricula, &v[i].media);
}
fclose(f);
return n;
}
int main(void) {
Aluno turma[MAX] = {
{"Ana", 2026001, 9.5},
{"Bruno", 2026002, 7.0},
{"Carla", 2026003, 8.25}
};
int n = 3;
salvar("turma.txt", turma, n); // grava no disco
printf("Turma gravada em turma.txt.\n\n");
// simula uma "nova execucao": le tudo de volta para outro vetor
Aluno recarregada[MAX];
int m = carregar("turma.txt", recarregada);
printf("Alunos recarregados do arquivo (%d):\n", m);
for (int i = 0; i < m; i++) {
printf(" %-8s mat %d media %.2f\n",
recarregada[i].nome,
recarregada[i].matricula,
recarregada[i].media);
}
return 0;
}
O padrão aqui é muito comum e vale memorizar: gravar primeiro a quantidade
(n) e depois cada registro. Na leitura, lemos n e então repetimos a leitura
n vezes. Assim o programa que lê sabe exatamente quantos registros esperar —
não precisa nem detectar o EOF. (Alternativamente, você poderia ler em laço
até fscanf devolver algo diferente de 3, como fizemos na seção 6.)
Note ainda que, ao ler os double, usamos %lf (&v[i].media), e que
passamos v[i].nome sem & — porque um vetor de char (string) já é um
endereço, como você viu ao estudar vetores.
8. Uma palavra sobre arquivos binários (fread/fwrite)¶
Tudo o que vimos usa texto: números e nomes gravados como caracteres legíveis.
Existe outra família de funções — fwrite e fread — que grava e lê
dados em binário, copiando os bytes da memória diretamente para o arquivo.
Com elas, você poderia gravar o vetor de struct de uma vez, sem formatar
campo a campo. É mais rápido e compacto, mas o arquivo deixa de ser legível em um
editor de texto e fica dependente de detalhes da máquina. Fica como
conhecimento de fronteira — no nosso curso, ficamos com o texto, que é mais
simples de entender, depurar e conferir "a olho".
9. Boas práticas desta semana¶
- Sempre verifique o retorno do
fopen(if (f == NULL) ...) antes de usar o arquivo. Sem exceção. - Sempre
fcloseao terminar — libera recursos e garante que o buffer foi para o disco. - Cuidado com
"w": ele apaga o conteúdo existente. Para acrescentar sem perder, use"a". - Na leitura de
double, use%lfnofscanf(como noscanf). - Detecte o fim do arquivo pelo retorno da leitura, não confiando só em
feof. - Grave a quantidade de registros no início do arquivo quando isso simplificar a releitura.
10. Erros comuns desta semana (resumão)¶
Checklist de armadilhas
- Usar o arquivo sem checar
if (f == NULL)depois dofopen. - Abrir em
"w"um arquivo que você queria preservar (apagou tudo!). - Esquecer o
fclose(dados podem ficar presos no buffer). - Usar
%fem vez de%lfao lerdoublecomfscanf. - Usar
while (!feof(f))e processar o último registro em dobro. - Esquecer o
FILE *como primeiro argumento defprintf/fscanf. - Colocar
&antes de um vetor dechar(nome) nofscanf— ele já é um endereço. - Caminho/nome de arquivo errado →
fopendevolveNULL.
👥 Quarta — Encontro¶
Chegue ao encontro tendo estudado o material acima e tendo executado os
exemplos (rode salva_notas.c e depois le_notas.c, e abra os arquivos
gerados no seu editor para ver o resultado no disco). O encontro é para
consolidar e integrar — é a última aula prática do semestre. Roteiro
previsto:
- Revisão relâmpago: persistência,
FILE *,fopen/fclose, os modos"r"/"w"/"a", e o teste== NULL. - Escrita e leitura ao vivo: gravar dados e lê-los de volta, discutindo o
laço de leitura correto (retorno de
fscanf×feof). - Integração com a Unidade 3: salvar e recarregar um vetor de
struct, fechando o ciclo memória → disco → memória. - Galeria de erros: provocamos de propósito um
NULL(arquivo inexistente) e a perda de dados com"w", para você reconhecer os sintomas.
Problema-guia do encontro — agenda de contatos persistente: um programa que mantém uma agenda (nome + telefone) em um arquivo. Ao iniciar, ele carrega os contatos já salvos; permite adicionar um novo; e, ao sair, regrava tudo — de modo que, na próxima execução, os contatos continuem lá.
#include <stdio.h>
#define MAX 200
typedef struct {
char nome[50];
char telefone[20];
} Contato;
// carrega os contatos do arquivo; devolve quantos leu (0 se nao existir ainda)
int carregar(const char *caminho, Contato v[]) {
FILE *f = fopen(caminho, "r");
if (f == NULL) {
return 0; // arquivo ainda nao existe: agenda vazia
}
int n = 0;
// le pares "nome telefone" ate o fim do arquivo
while (n < MAX && fscanf(f, "%s %s", v[n].nome, v[n].telefone) == 2) {
n++;
}
fclose(f);
return n;
}
// regrava todos os contatos (modo "w": reescreve o arquivo inteiro)
void salvar(const char *caminho, Contato v[], int n) {
FILE *f = fopen(caminho, "w");
if (f == NULL) {
printf("Erro ao salvar a agenda.\n");
return;
}
for (int i = 0; i < n; i++) {
fprintf(f, "%s %s\n", v[i].nome, v[i].telefone);
}
fclose(f);
}
int main(void) {
Contato agenda[MAX];
int n = carregar("agenda.txt", agenda);
printf("Agenda carregada com %d contato(s).\n", n);
for (int i = 0; i < n; i++) {
printf(" %-10s %s\n", agenda[i].nome, agenda[i].telefone);
}
// adiciona um novo contato (nome sem espacos, por causa do %s)
if (n < MAX) {
printf("\nNovo contato (nome telefone): ");
if (scanf("%s %s", agenda[n].nome, agenda[n].telefone) == 2) {
n++;
}
}
salvar("agenda.txt", agenda, n); // persiste tudo de volta
printf("Agenda salva com %d contato(s). Rode de novo para conferir!\n", n);
return 0;
}
Perguntas para pensar antes do encontro: por que carregar devolve 0 (em vez
de dar erro) quando o arquivo não existe? O que aconteceria se usássemos "a" em
vez de "w" na função salvar? Como o while (... == 2) sabe que a agenda
acabou?
✍️ Sexta — Estudo dirigido¶
Feriado em 20/11 — organize seu tempo
A sexta desta semana (20/11) é feriado (Dia da Consciência Negra). Não haverá encontro nem atividade síncrona. Reserve um horário próprio, ainda esta semana, para fazer o estudo dirigido abaixo — é o fechamento prático do curso.
Arquivos e o Beecrowd: por que quase não aparecem
Diferentemente das semanas anteriores, manipulação de arquivos raramente é
cobrada no Beecrowd. O motivo é técnico: o juiz online alimenta seu
programa pela entrada padrão (stdin) e confere a saída padrão
(stdout) — ele não deixa você criar arquivos no disco dele. Por isso, aqui
o foco não é a tabela de exercícios do juiz, e sim os desafios do zero
abaixo, que você roda e confere na sua própria máquina, abrindo os
arquivos gerados no editor de texto.
(Curiosidade útil: como scanf/printf são fscanf(stdin,...)/fprintf(stdout,...),
tudo o que você aprendeu de E/S para o Beecrowd é a mesma máquina de
arquivos — só que apontada para os arquivos-padrão.)
Desafios para escrever do zero¶
Todos abaixo criam e/ou leem arquivos no seu computador. Depois de rodar, abra o arquivo gerado no editor e confira o conteúdo com os próprios olhos.
- Soma de N números salvos: peça
Nnúmeros ao usuário e grave-os emnumeros.txt(um por linha). Em seguida, abra o arquivo de novo para leitura, some todos e imprima o total. (Prove que a soma veio do arquivo, não da memória.) - Agenda simples: grave vários pares
nome telefoneemcontatos.txt(modo"w") e, num segundo momento, leia e liste todos. Adapte a partir doagenda.cdo encontro. - Contador de linhas e palavras: dado um arquivo-texto qualquer, leia-o e
conte quantas linhas e quantas palavras ele tem. (Dicas:
fgetspara contar linhas;fscanf(f, "%s", palavra) == 1num laço para contar palavras.) - Vetor de
structem disco: crie um vetor deAluno(nome, matrícula, média), salve emalunos.txte depois recarregue para outro vetor, imprimindo os dados lidos. (Baseie-se emalunos_arquivo.c.) - Diário incremental: um programa que, a cada execução, acrescenta
(modo
"a") uma linha emdiario.txt(por exemplo, uma frase digitada pelo usuário). Rode várias vezes e observe o arquivo crescendo sem perder as linhas anteriores — o oposto do"w".
Para investigar (curiosidade prática)¶
- O
NULLna prática: tente abrir, em modo"r", um arquivo que não existe (invente um nome). Testeif (f == NULL)e imprima uma mensagem. Confirme que o programa não trava — ele apenas detecta a falha. Relacione com a Semana 10. - O
"w"que apaga: crie um arquivo com algum conteúdo (pelo editor, ou com um programa). Depois, abra-o em"w"no seu programa, escreva uma única linha nova e feche. Abra o arquivo no editor: onde foi parar o conteúdo antigo? Agora repita o experimento trocando"w"por"a"e compare.
✅ Checklist de autoavaliação¶
Marque com sinceridade — se algum item não estiver ✅, volte à seção correspondente.
- Explico o que é persistência e por que a RAM perde os dados ao fim do programa.
- Sei declarar um
FILE *, abrir comfopene escolher o modo certo ("r","w","a"). - Sempre verifico
if (f == NULL)antes de usar o arquivo. - Fecho o arquivo com
fclosee entendo por que isso importa (buffer/recursos). - Escrevo com
fprintf/fputse leio comfscanf/fgets. - Detecto o fim do arquivo pelo retorno da leitura (e sei por que
while(!feof(f))é arriscado). - Uso
%lfao lerdoublecomfscanf. - Consigo salvar e recarregar um vetor de
structem disco.
Avaliação 3 (A3)
A Avaliação 3 cobre o conteúdo da Unidade 3, das semanas S10 a S15:
ponteiros e memória, alocação dinâmica, listas, struct e, agora,
manipulação de arquivos. A data e o formato estão no
plano de curso — confira com antecedência e organize
sua revisão. Refaça os exemplos e os desafios "do zero" que ficaram difíceis:
é a melhor preparação possível.
Encerramento do semestre — parabéns pela jornada!
Chegamos ao fim do conteúdo de Introdução às Técnicas de Programação. Vale
a pena olhar para trás e ver o quanto você caminhou. Começamos na Semana 01
escrevendo o primeiro printf, entendendo variáveis, tipos e o que a máquina
faz "por baixo". Passamos por decisões, repetição e funções — a
arte de dividir para conquistar. Fomos além dos tipos simples com
vetores, matrizes, strings e estruturas de dados. E, na Unidade 3,
encaramos o coração do C: endereços, ponteiros, alocação dinâmica de
memória e o modelo real de como os dados vivem na RAM. Hoje, com
arquivos, fechamos o ciclo: seus programas já não "esquecem tudo" ao
terminar — eles guardam e recuperam o trabalho.
Fundamentos → funções → estruturas de dados → memória e ponteiros → arquivos:
essa é uma base sólida que serve para qualquer linguagem que você aprender
daqui em diante. Foi um semestre de esforço real, de erros de compilação, de
segmentation fault teimosos e de aquela alegria quando o programa enfim
roda. Parabéns por chegar até aqui. Agora é revisar com carinho para a A3
— e seguir programando. O melhor jeito de honrar tudo isso é: continue
escrevendo código.
🔗 Referências e para se aprofundar¶
- Material 2026.1 — Aula 14: Manipulação de arquivos.
- BACKES, André. Linguagem C: completa e descomplicada (arquivos:
fopen,fprintf/fscanf,fgets, modos de abertura). - KERNIGHAN, B.; RITCHIE, D. The C Programming Language (o clássico "K&R"), cap. 7 (entrada/saída, incluindo arquivos).
- MIZRAHI, Victorine V. Treinamento em Linguagem C (arquivos).
- Referência: cppreference —
fopen/FILE(detalhes dos modos e do tipoFILE). - Prática: Beecrowd — lembre que arquivos quase não são cobrados; use-o para revisar o conteúdo geral do semestre.