Inventário de material. Você é o dono de uma loja de materiais e precisa manter um inventário que poderá informar quais e quantas ferramentas você possui, e o custo de cada uma. Escreva um programa que inicialize o arquivo “hardware.dat” para 100 registros vazios, e permita que você insira os dados referentes a cada ferramenta, liste todas as suas ferramentas, exclua um registro para a ferramenta que não possui mais e atualize qualquer informação no arquivo. O número de identificação da ferramenta deverá ser o número do registro. Use a informação a seguir para iniciar seu arquivo:
Passo 1
Vamos criar um programa orientado por menus que permitirá ao usuário adicionar, atualizar, excluir e listar todos os registros de ferramentas armazenados em um arquivo.
As seções do programa serão divididas em funções menores que utilizaremos na função principal onde definiremos o menu.
Para começar, aqui está o cabeçalho do programa.
É sempre uma boa prática definir constantes que são usadas em todo o programa. Isso simplifica a alteração das especificações de um programa.
Também vamos definir uma estrutura de ferramenta indefinida que usaremos para inicializar os registros do arquivo e nos ajudará a comparar os valores com os indefinidos, se necessário.
Passo 2
#include
#include
#define NUM_MAX 4
#define NAME_MAX 20
#define QUANTITY_MAX 4
#define COST_MAX 8
#define SIZE (NUM_MAX+NAME_MAX+QUANTITY_MAX+COST_MAX)
struct Tool {
char recordNumber[NUM_MAX];
char name[NAME_MAX];
char quantity[QUANTITY_MAX];
char cost[COST_MAX];
}
undef = {
"", "unassigned", "0", ""
};
Vamos criar uma subfunção que será usada para solicitar ao usuário que insira as informações de uma ferramenta:
struct Tool initializeTool()
{
struct Tool tool;
printf("Enter record number >> ");
scanf("%s", &tool.recordNumber);
printf("Enter tool name >> ");
scanf("%s", &tool.name);
printf("Enter quantity >> ");
scanf("%s", &tool.quantity);
printf("Enter the cost >> ");
scanf("%s", &tool.cost);
return tool;
}
Agora, vamos criar a função addTool().
Esta função irá adicionar um registro de ferramenta ao arquivo se o número do registro for válido e o registro da ferramenta for indefinido.
A função retornará:
Inteiro -1, o registro já está definido.
Inteiro 1, adição bem-sucedida.
Inteiro 0, o registro não foi encontrado (entrada inválida).
Comece solicitando ao usuário que insira as informações para a ferramenta e definindo o ponteiro do arquivo para o início do arquivo:
int addTool(FILE* outFile)
{
struct Tool tool = initializeTool();
fseek(outFile, 0, SEEK_SET);
...
}
Passo 3
Em seguida, insira um loop infinito que irá percorrer os registros da ferramenta até que o registro seja encontrado ou o final do arquivo seja alcançado.
Primeiro, leia a "chave" (número do registro) da seguinte forma:
int addTool(FILE* outFile)
{
...
while (1)
{
char key[NUM_MAX];
fread(&key, NUM_MAX, 1, outFile);
...
}
}
Agora, compare o número do registro com o número do registro da nova ferramenta.
Se os números dos registros corresponderem, verifique se a ferramenta está definida lendo o nome do registro e comparando-o com um nome indefinido (variável de estrutura undef):
int addTool(FILE* outFile)
{
...
while (1)
{
...
if (strcmp(key, tool.recordNumber) == 0)
{
char name[NAME_MAX];
fread(&name, NAME_MAX, 1, outFile);
if (strcmp(name, undef.name) != 0)
return -1;
...
}
...
}
}
Se o registro for indefinido, é válido para a adição.
Temos que fazer backup do ponteiro de arquivo por nome de registro e tamanhos de número e, em seguida, continuar a escrever a substituição (nova ferramenta):
int addTool(FILE* outFile)
{
...
while (1)
{
...
if (strcmp(key, tool.recordNumber) == 0)
{
...
fseek(outFile, -(NUM_MAX + NAME_MAX), SEEK_CUR);
fwrite(&tool, sizeof(struct Tool), 1, outFile);
return 1;
}
...
}
}
Passo 4
A cada iteração, temos que verificar se o ponteiro do arquivo chegou ao final do arquivo.
Se tiver, limpe o sinalizador EOF utilizando a função clearerr().
Caso contrário, mova o ponteiro do arquivo para o próximo registro da seguinte maneira:
int addTool(FILE* outFile)
{
...
while (1)
{
...
if (!feof(outFile))
{
fseek(outFile, SIZE - NUM_MAX, SEEK_CUR);
}
else
{
clearerr(outFile);
return 0;
}
}
}
Em seguida, usamos a função displayTools().
Primeiro, defina o ponteiro do arquivo para o início do arquivo porque queremos percorrer todos os registros.
void displayTools(FILE* outFile)
{
fseek(outFile, 0, SEEK_SET);
printf("\n");
...
}
Em seguida, insira um loop infinito e pule os dados do número do registro porque estamos interessados apenas no nome do registro para ver se ele está definido:
void displayTools(FILE* outFile)
{
...
while (1)
{
fseek(outFile, NUM_MAX, SEEK_CUR);
...
}
...
}
Agora, vamos ler o nome e compará-lo com o nome indefinido armazenado na variável de estrutura undef.
Se o registro estiver definido, volte o ponteiro do arquivo para o início do registro, leia as informações e imprima no console da seguinte forma:
void displayTools(FILE* outFile)
{
...
while (1)
{
...
int read = 0;
char name[NAME_MAX];
fread(&name, NAME_MAX, 1, outFile);
if (strcmp(name, undef.name) != 0)
{
fseek(outFile, -(NUM_MAX + NAME_MAX), SEEK_CUR);
struct Tool tmp;
fread(&tmp.recordNumber, NUM_MAX, 1, outFile);
fread(&tmp.name, NAME_MAX, 1, outFile);
fread(&tmp.quantity, QUANTITY_MAX, 1, outFile);
fread(&tmp.cost, COST_MAX, 1, outFile);
printf("%s %s %s %s",
tmp.recordNumber,
tmp.name,
tmp.quantity,
tmp.cost);
read = 1;
}
...
}
...
}
Por fim, temos que verificar se o final do arquivo foi atingido.
Se estiver, limpe o sinalizador EOF. Caso contrário, usando o valor da variável read do passo anterior, indicando se o registro foi totalmente lido ou não, moveremos o ponteiro do arquivo se necessário.
void displayTools(FILE* outFile)
{
...
while (1)
{
...
if (!feof(outFile))
{
if (!read)
fseek(outFile, SIZE - NUM_MAX - NAME_MAX,
SEEK_CUR);
}
else
{
clearerr(outFile);
break;
}
}
printf("\n");
}
Em seguida, temos a função deleteTool().
Primeiro, solicite ao usuário que insira o número do registro que deve ser excluído e mova o ponteiro do arquivo para o início do arquivo:
int deleteTool(FILE* outFile)
{
char key[NUM_MAX];
printf("Enter record number to be deleted >> ");
scanf("%s", &key);
fseek(outFile, 0, SEEK_SET);
...
}
Passo 5
Digite um loop, que lerá os números do registro e comparará o valor com a "chave" (entrada do usuário).
Se os valores corresponderem, volte o ponteiro do arquivo para o início do registro e coloque a variável de estrutura indefinida undef para substituir o registro por informações indefinidas da seguinte forma:
int deleteTool(FILE* outFile)
{
...
while (1)
{
char value[NUM_MAX];
fread(&value, NUM_MAX, 1, outFile);
if (strcmp(value, key) == 0)
{
fseek(outFile, -NUM_MAX, SEEK_CUR);
fwrite(&undef, SIZE, 1, outFile);
return 1;
}
...
}
}
Para cada iteração, temos que verificar se o ponteiro do arquivo chegou ao final do arquivo:
int deleteTool(FILE* outFile)
{
...
while (1)
{
...
if (!feof(outFile))
{
fseek(outFile, SIZE - NUM_MAX, SEEK_CUR);
}
else
{
clearerr(outFile);
return 0;
}
}
}
Em seguida, a função updateTool().
Primeiro, solicite ao usuário que insira as informações atualizadas de um registro de ferramenta e defina o ponteiro do arquivo para o início do arquivo:
int updateTool(FILE* outFile)
{
struct Tool tool = initializeTool();
fseek(outFile, 0, SEEK_SET);
...
}
Passo 6
Agora, leia os números de registro e compare-os com o valor "chave" (o novo número de registro da ferramenta do usuário).
Se o registro for encontrado, certifique-se de que o registro esteja definido antes de reescrever o registro da seguinte forma:
int updateTool(FILE* outFile)
{
...
while (1)
{
char value[NUM_MAX];
fread(&value, NUM_MAX, 1, outFile);
if (strcmp(value, tool.recordNumber) == 0)
{
char name[NAME_MAX];
fread(&name, NAME_MAX, 1, outFile);
if (strcmp(name, undef.name) == 0)
return -1;
fseek(outFile, -(NUM_MAX + NAME_MAX), SEEK_CUR);
fwrite(&tool, SIZE, 1, outFile);
return 1;
}
...
}
}
Como fizemos nas funções anteriores, temos que verificar o EOF:
int updateTool(FILE* outFile)
{
...
while (1)
{
...
if (!feof(outFile))
{
fseek(outFile, SIZE - NUM_MAX, SEEK_CUR);
}
else
{
clearerr(outFile);
return 0;
}
}
}
Por fim, a função main().
Antes de tudo, abra o arquivo e inicialize-o com 100 registros indefinidos:
int main()
{
FILE* outFile = fopen("hardware.dat", "w+");
for (int i = 0; i
{
char buffer[NUM_MAX];
fwrite(itoa(i, buffer, 10), NUM_MAX, 1, outFile);
fwrite(&undef.name, NAME_MAX, 1, outFile);
fwrite(&undef.quantity, QUANTITY_MAX, 1, outFile);
fwrite(&undef.cost, COST_MAX, 1, outFile);
}
...
}
Exibir o cardápio:
int main()
{
...
while (1)
{
printf("\n1 Add tool"
"\n2 List tools"
"\n3 Delete record for a tool"
"\n4 Update record"
"\n0 Exit"
"\nChoose >> ");
int choice;
scanf("%d", &choice);
...
}
...
}
Use uma estrutura de instrução if-else para cobrir todas as opções.
Envie mensagens apropriadas que correspondam aos valores de saída das funções chamadas:
int main()
{
...
while (1)
{
...
if (choice == 1)
{
int val = addTool(outFile);
if (val == -1)
printf("\nRecord already exists\n");
else if (val == 0)
printf("\nInvalid record number\n");
else
printf("\nAddition successful\n");
}
else if (choice == 2)
{
displayTools(outFile);
}
else if (choice == 3)
{
if (deleteTool(outFile))
printf("\nDeletion successful\n");
else
printf("\nTool not found\n");
}
else if (choice == 4)
{
int val = updateTool(outFile);
if (val == -1)
printf("\nRecord doesn't exist\n");
else if (val == 0)
printf("\nInvalid record number\n");
else
printf("\nUpdate successful\n");
}
else if (choice == 0)
{
break;
}
else
{
printf("\nInvalid input\n");
}
}
...
}
Por fim, lembre-se de fechar o arquivo:
int main()
{
...
fclose(outFile);
return 0;
}
É isso, finalmente terminamos. RECEBAAA!!!
Resposta
Ver todo o desenvolvimento.