Médio C
Gravando e lendo structs com fwrite/fread
Enunciado
Defina uma struct Pessoa com campos nome (string de até 50 caracteres) e idade (int). Crie um programa que:
- Abra o arquivo
pessoas.binpara escrita binária ("wb"). - Grave 3 pessoas usando
fwrite. - Feche o arquivo.
- Reabra para leitura binária (
"rb"). - Leia e imprima cada pessoa usando
fread. Trate erros de abertura e de leitura/escrita.
Requisitos
- Definir a
struct Pessoacorretamente. - Usar
fopencom modos"wb"e"rb". - Usar
fwritepara gravar o array de structs de uma vez ou individualmente. - Usar
freadpara ler e verificar se a leitura foi bem-sucedida. - Imprimir os dados no formato
Nome: <nome>, Idade: <idade>.
Código inicial
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NOME 50
typedef struct {
char nome[MAX_NOME];
int idade;
} Pessoa;
int main(void) {
// Seu código aqui
return 0;
}
Saída esperada
Nome: Alice, Idade: 30
Nome: Bob, Idade: 25
Nome: Carol, Idade: 40
Ver dica
Use fwrite(pessoas, sizeof(Pessoa), 3, fp) para gravar o array inteiro. Na leitura, leia uma struct por vez com fread e verifique se retornou 1.
Mostrar solução
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NOME 50
typedef struct {
char nome[MAX_NOME];
int idade;
} Pessoa;
int main(void) {
Pessoa pessoas[3] = {
{"Alice", 30},
{"Bob", 25},
{"Carol", 40}
};
// Abre para escrita binária
FILE *fp = fopen("pessoas.bin", "wb");
if (fp == NULL) {
perror("Erro ao abrir para escrita");
return 1;
}
// Grava o array inteiro de uma vez
size_t escritos = fwrite(pessoas, sizeof(Pessoa), 3, fp);
if (escritos != 3) {
fprintf(stderr, "Erro ao gravar: esperado 3, obtido %zu\n", escritos);
fclose(fp);
return 1;
}
fclose(fp);
// Abre para leitura binária
fp = fopen("pessoas.bin", "rb");
if (fp == NULL) {
perror("Erro ao abrir para leitura");
return 1;
}
Pessoa p;
// Lê uma struct por vez até o fim do arquivo
while (fread(&p, sizeof(Pessoa), 1, fp) == 1) {
printf("Nome: %s, Idade: %d\n", p.nome, p.idade);
}
fclose(fp);
return 0;
}
Passo a passo
- Definimos a
struct Pessoacom um array de char para o nome e um int para a idade. - Criamos um array
pessoascom 3 elementos já inicializados. - Abrimos o arquivo
pessoas.binno modo"wb"(escrita binária). Verificamos sefopenretornouNULL. - Usamos
fwritepara gravar o array inteiro: passamos o endereço do array, o tamanho de cada elemento (sizeof(Pessoa)) e a quantidade (3). O retorno é o número de elementos escritos; deve ser 3. - Fechamos o arquivo.
- Reabrimos no modo
"rb"(leitura binária) e verificamos erro. - Declaramos uma
Pessoa pe usamosfreadpara ler um elemento por vez. O loop continua enquantofreadretornar 1 (um elemento lido). - Imprimimos os dados e fechamos o arquivo.
Por que funciona
fwrite e fread operam em blocos de bytes, sendo ideais para gravar structs diretamente na memória. O modo "wb" garante que nenhuma tradução de caracteres (como \n para \r\n no Windows) ocorra, preservando a representação binária. Verificar os retornos assegura que a operação foi completa.
Erros comuns
- Usar modo texto (
"w") para dados binários: pode corromper os dados em sistemas que traduzem quebras de linha. Use"wb"e"rb". - Esquecer de verificar o retorno de
fwrite: se o disco estiver cheio, a gravação pode ser parcial. Compare com o número esperado. - Ler com
freadsem verificar o retorno: o loop pode tentar processar dados inválidos. Usewhile (fread(...) == 1). - Não fechar o arquivo antes de reabrir: pode causar comportamento indefinido. Sempre
fclose.
Outra forma de resolver
Poderia gravar cada struct individualmente com fwrite(&pessoas[i], sizeof(Pessoa), 1, fp) dentro de um loop. A leitura seria similar. A abordagem em bloco é mais eficiente para arrays grandes.
Saída esperada
Nome: Alice, Idade: 30
Nome: Bob, Idade: 25
Nome: Carol, Idade: 40