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.