Quando uso o fread a variavel cont zera

1. Quando uso o fread a variavel cont zera

Antonio Lorival Baesso
4n7onio

(usa Nenhuma)

Enviado em 11/03/2018 - 09:53h

quando tento recuperar as informacoes do txt usando fread vetorizado a variavel cont zera , queria saber o porque

/* Programa 1
data 06/02/18
Alunos: Antonio Lorival Baesso
Djionathan de Oliveira
Objetivo: Cadastro de empregados mostrando salario
*/

#include<stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

struct empregado{

int cod; //Cria um estrutura onde vai ser pedido o código, nome e salário.
char nome[256];
float salario;
} em[1000]; //Podem ser cadastrados até 1001 funcionários.

int cont = 0; //contador definido em 0 sendo uma variavel global

void recuperar(); //Declaração das mesmas abaixo
void nucleo();

int main (void){

int menu = 0, size;
FILE *con;//aponta para um variavel (con)
con = fopen("cont.txt", "rb");//con sera igual o arquivo que sera pra escrita e leitura
if (con == NULL) {
printf ("ERRO! ARQUIVO NAO EXISTENTE\n");
exit (1);
};
fread(&cont, sizeof(int), 1, con);//pega as informações de dentro do txt
printf("\n%d", cont);
fclose(con);
recuperar(); // recupera os dados do txt que já foram salvas
do {
printf("|__MENU___|\n");
printf("|[1]CADASTRO\n"); //menu
printf("|[2]LISTAR\n");
printf("|[0]SAIR\n");
scanf (" %d", &menu);
switch(menu){

case 1:
nucleo();//conta
break;

case 2:
printf ("\n%d", cont);
for (int i = 0; i <= cont ; i++){
printf("\nCODIGO: %d", em[i].cod);
printf("\nNOME: %s", em[i].nome);
printf("\nSALARIO: %.2f\n\n", em[i].salario);
}
break;

case 0:
exit(1);//sai
break;

default:
printf("OPCAO NAO ENCONTRADA!\n");
break;
}
} while( menu != 0);

return 0;
}

void nucleo(void){
int opcao = 0, p = 0, au = 0;
float aux = 0;
FILE *arquivo;//abre o arquivo
arquivo = fopen ("arquivo.txt", "ab");//abre em modo apendice(abre o documento e acrescente sem excluir)
if (arquivo == NULL) {
printf ("ERRO! ARQUIVO NAO EXISTENTE\n");
exit (1);
};
do{
printf("%d\n", cont);
cont += 1;
do {
printf ("Digite o codigo do funcionario:\n");//digita o codigo
scanf ("%d", &em[cont].cod);//salva dentro da estrutura
for (int i = 0 ; i < cont; i++) {//vai repetir até o i ser igual o contador
if ( em[i].cod == em[cont].cod ) {
printf ( "Esse cadastro ja existe \n" );
p = 1;
} else {
p = 0;
};
}
}while ( p == 1 );
do {
printf ("Digite o nome do funcionario:\n");
scanf (" %[^\n]s", & em[cont].nome);// [^/n]s obriga a aceitar toda a string ate o /n , jogando o /n pra proxima string (o espaco entre " %[^/n]s" serve pra limpar o buff.
setbuf(stdin, NULL);//remove o /n da proxima string;
for (int i = 0 ; i < cont; i++) {
if ( stricmp(em[i - 1].nome, em[cont].nome) == 0 ) {
printf ( "Esse cadastro ja existe \n" );
p = 1;
} else {
p = 0;
};
}
}while (p != 0);
printf ( "Digite o salario do funcionaro:\n" );
scanf ( "%f",& em[cont].salario );
printf ( "Deseja continuar cadastrando?\n [1]SIM\t [2]NAO \n" );
scanf ("%d", &opcao);
aux = em[cont].salario;//tudo que ta dentro de salario vai para aux
if ( em[cont].salario < 2500 ) {//se o salario for menor que 2500 a varial aux vai ser multiplicada por 11, se ser maior vai ser por 9
aux *= 11;

} else {
aux *= 9;
}
aux /= 100;//aux divite por 100 e salva dentro da aux( /= )
em[cont].salario -= aux;//desconta o valor dentro de auxiliar com o salario e já salva em salario
fwrite(&em[cont], sizeof(em), 1, arquivo);
//manda a estrutura pra dentro do documento
}while (opcao == 1);
fclose(arquivo);//fecha o arquivo
FILE *con;//aponta para um variavel (con)
con = fopen("cont.txt", "wb");
fwrite(&cont, sizeof(int), 1, con);//manda as informações pra dentro do txt
fclose(con);
system ("cls");
}

void recuperar(void){

FILE *arquivo;// file aponta para um contador (arquivo)
arquivo = fopen("arquivo.txt","rb");
if(arquivo == NULL) {
printf("ARQUIVO NAO EXISTENTE!");
exit(1);
}
for (int i = 0; i <= cont ; i++){
fread(&em, sizeof(em), 1, arquivo);//salva a estrutura inteira pra dentro do variavel
}
fclose(arquivo);//fecha o arquivo
}


  


2. Re: Quando uso o fread a variavel cont zera

Paulo
paulo1205

(usa Ubuntu)

Enviado em 13/03/2018 - 16:10h

4n7onio escreveu:

quando tento recuperar as informacoes do txt usando fread vetorizado a variavel cont zera , queria saber o porque

/* Programa 1
data 06/02/18
Alunos: Antonio Lorival Baesso
Djionathan de Oliveira
Objetivo: Cadastro de empregados mostrando salario
*/

#include<stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

struct empregado{

int cod; //Cria um estrutura onde vai ser pedido o código, nome e salário.
char nome[256];
float salario;
} em[1000]; //Podem ser cadastrados até 1001 funcionários.


Aqui você cometeu um erro. A quantidade máxima de funcionários é exatamente igual ao valor que vai entre colchetes no momento da declaração do vetor. Na hora de usar o vetor é que os índices, por começar em 0, só podem ir até 999.

Mas fora isso, se você terá os registros dispostos em disco, por que ficar guardando-os também em memória?


int cont = 0; //contador definido em 0 sendo uma variavel global

void recuperar(); //Declaração das mesmas abaixo
void nucleo();

int main (void){

int menu = 0, size;
FILE *con;//aponta para um variavel (con)
con = fopen("cont.txt", "rb");//con sera igual o arquivo que sera pra escrita e leitura
if (con == NULL) {
printf ("ERRO! ARQUIVO NAO EXISTENTE\n");
exit (1);
};
fread(&cont, sizeof(int), 1, con);//pega as informações de dentro do txt


Você está trabalhando com arquivos binários, de modo que é temerariamente enganoso referir-se a eles como “txt”, assim como usar “.txt” como sufixo de tais arquivos.

Além disso, se você quiser ter certeza de ter recebido um dado válido nessa leitura, deveria verificar o valor de retorno de fread().

	printf("\n%d", cont);
fclose(con);
recuperar(); // recupera os dados do txt que já foram salvas


Acho interessante notar que você não precisaria de dois arquivos, sendo um para conter os dados e o outro para indicar quantos registros o arquivo de dados tem.

Uma das vantagens de trabalhar com arquivos com registro de tamanho fixo é poder calcular a quantidade de registros a partir do tamanho do arquivo, uma vez que a quantidade de registros será igual ao tamanho total do arquivo dividido pelo tamanho de cada registros.

Leia sobre as funções fseek() e ftell().

	do {
printf("|__MENU___|\n");
printf("|[1]CADASTRO\n"); //menu
printf("|[2]LISTAR\n");
printf("|[0]SAIR\n");
scanf (" %d", &menu);
switch(menu){

case 1:
nucleo();//conta
break;

case 2:
printf ("\n%d", cont);
for (int i = 0; i <= cont ; i++){
printf("\nCODIGO: %d", em[i].cod);
printf("\nNOME: %s", em[i].nome);
printf("\nSALARIO: %.2f\n\n", em[i].salario);
}
break;

case 0:
exit(1);//sai


Se a saída foi bem-sucedida, o convencional é retornar o valor zero.

Mas neste caso, você não precisaria fazer nada, pois o laço de repetição terminaria por causa do valor de menu (ver abaixo).

			break;

default:
printf("OPCAO NAO ENCONTRADA!\n");
break;
}
} while( menu != 0);

return 0;
}

void nucleo(void){


Note que, acima, você declarou nucleo como “void nucleo()”, e aqui diz que é “void nucleo(void)”. Tecnicamente falando, a declaração e a definição estão incompatíveis: a primeira significa que a função poderia receber qualquer quantidade de parâmetros de quaisquer tipos; já a segunda proíbe a presença de parâmetros.

	int opcao = 0, p = 0, au = 0;
float aux = 0;
FILE *arquivo;//abre o arquivo
arquivo = fopen ("arquivo.txt", "ab");//abre em modo apendice(abre o documento e acrescente sem excluir)
if (arquivo == NULL) {
printf ("ERRO! ARQUIVO NAO EXISTENTE\n");


Essa mensagem é inadequada, pois o modo de abertura "a" deve criar o arquivo, se ele não existir. Se uma falha ocorrer, a natureza do erro será outra, como problema de permissão ou algum erro do ambiente de execução.

Você provavelmente terá como saber o tipo do erro através do indicador global errno (que pode ser uma variável ou macro), e pode receber a mensagem de erro detalhada com a função strerror().

       exit (1);  
};
do{
printf("%d\n", cont);
cont += 1;


Não é um erro, mas é não-usual fazer dessa maneira. A maioria dos programadores em C diria “cont++;” ou “++cont;”.

No entanto, como veremos logo abaixo, você parece estar incrementando o contador antes da hora.

		do {
printf ("Digite o codigo do funcionario:\n");//digita o codigo
scanf ("%d", &em[cont].cod);//salva dentro da estrutura


Lembra que os índices de um array começam em zero? Então, se cont indica a quantidade de registros válidos, você deveria, aqui, usar como índice o valor de cont-1.

Alternativamente, você poderia continuar usando cont, se movesse o incremento que fez acima para depois de ter lido e validado todo o registro.

			for (int i = 0 ; i < cont; i++) {//vai repetir até o i ser igual o contador
if ( em[i].cod == em[cont].cod ) {
printf ( "Esse cadastro ja existe \n" );
p = 1;
} else {
p = 0;
};
}
}while ( p == 1 );
do {
printf ("Digite o nome do funcionario:\n");
scanf (" %[^\n]s", & em[cont].nome);// [^/n]s obriga a aceitar toda a string ate o /n , jogando o /n pra proxima string (o espaco entre " %[^/n]s" serve pra limpar o buff.


Aqui você comete um erro muito comum, que é o de tratar o que vai entre colchetes na string de formatação de scanf() como se fosse um modificador da conversão "%s".

Não é o caso. Em vez disso, "%[" é uma conversão diferente de "%s", inclusive com regras diferentes quanto a tratamento de espaços, mas principalmente pelo fato de que "%[" aceita parâmetros pós-fixados não-nulos, que terminam quando se encontra o caráter “]”.

Assim sendo, aquele “s” após o fechamento dos colchetes está sobrando. Na verdade, sua string de formatação “" %[^\n]s"” significa exatamante o seguinte, por partes:

  • “ ” (espaço em branco no começo da string): leia uma quantidade qualquer de espaços em branco (espaços comuns, tabulações, marcas de fim-de-linha etc.), e descarte-os.
  • “%[^\n]”: leia um ou mais caracteres diferentes de quebra de linha, armazenando-os no vetor de caracteres correspondente.
  • “s”: procure o caráter s, e descarte-o após o encontrar.

Com tal string de formatação, é impossível satisfazer ao mesmo tempo as duas últimas partes, com qualquer conjunto de dados que você imaginar. A função scanf() sempre vai ser prematuramente interrompida.

Além disso, a prudência recomendaria que você especificasse a quantidade máxima de caracteres a ser lida pela segunda parte, para não permitir que um usuário mal-intencionado extrapole os limites do vetor que recebe tais caracteres.

			setbuf(stdin, NULL);//remove o /n da proxima string; 


Essa chamada a setbuf() é inválida e ilegal (o padrão diz que não se deve chamá-la sobre um stream que já tenha sofrido operações ativas de transferência de dados), e não se presta a fazer o que você gostaria que fizesse. Não use isso.

Em lugar dessa coisa estranha, consuma/descarte efetivamente o '\n' na leitura anterior (ou na próxima).

			for (int i = 0 ; i < cont; i++) {
if ( stricmp(em[i - 1].nome, em[cont].nome) == 0 ) {


stricmp() não é uma função padronizada. Ela existe em implementações do Windows, mas não no resto do universo.

					printf ( "Esse cadastro ja existe \n" );
p = 1;
} else {
p = 0;
};
}
}while (p != 0);
printf ( "Digite o salario do funcionaro:\n" );
scanf ( "%f",& em[cont].salario );
printf ( "Deseja continuar cadastrando?\n [1]SIM\t [2]NAO \n" );
scanf ("%d", &opcao);
aux = em[cont].salario;//tudo que ta dentro de salario vai para aux
if ( em[cont].salario < 2500 ) {//se o salario for menor que 2500 a varial aux vai ser multiplicada por 11, se ser maior vai ser por 9
aux *= 11;

} else {
aux *= 9;
}
aux /= 100;//aux divite por 100 e salva dentro da aux( /= )
em[cont].salario -= aux;//desconta o valor dentro de auxiliar com o salario e já salva em salario
fwrite(&em[cont], sizeof(em), 1, arquivo);
//manda a estrutura pra dentro do documento
}while (opcao == 1);
fclose(arquivo);//fecha o arquivo
FILE *con;//aponta para um variavel (con)
con = fopen("cont.txt", "wb");
fwrite(&cont, sizeof(int), 1, con);//manda as informações pra dentro do txt
fclose(con);
system ("cls");
}

void recuperar(void){

FILE *arquivo;// file aponta para um contador (arquivo)
arquivo = fopen("arquivo.txt","rb");
if(arquivo == NULL) {
printf("ARQUIVO NAO EXISTENTE!");
exit(1);
}
for (int i = 0; i <= cont ; i++){
fread(&em, sizeof(em), 1, arquivo);//salva a estrutura inteira pra dentro do variavel
}


Se você quer ler o vetor (não estrutura) inteiro numa tacada só, então a forma de fazer não seria essa. A própria fread() se encarregaria de ler vários registros, de modo que não precisaria do laço com for.

Se você tirar o laço acima e deixar a chamada a fread() do jeito como está, ela até funcionaria, mas somente se o arquivo tivesse 1000 registros ou mais (com o for, o que você acaba fazendo é tentando ler 1000 registros um total de cont vezes). Se o arquivo tiver menos de 1000 registros, não haverá quantidade de dados suficientes para satisfazer a solicitação de sizeof(em) bytes por registro.

Uma forma melhor de fazer seria a seguinte:
	cont=fread(em, sizeof *em, sizeof em/sizeof *em, arquivo); 

Explicação: eu tento ler múltiplos registros, cada um deles com tamanho sizeof *em (tamanho de um elemento de em, que é o segundo argumento), limitando a quantidade máxima de registros (terceiro parâmetro) ao número de elementos do array em (seu tamanho total dividido pelo tamanho de cada registro). Ao final da leitura, a quantidade de registros lidos será o valor devolvido pela função, que eu posso atribuir diretamente à variável cont, que representa a quantidade de registros ativos dentro do vetor.

	fclose(arquivo);//fecha o arquivo
}









Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts