Jump to content
Trinkes

Duvida em fscanf

Recommended Posts

Trinkes

Boa tarde,

queria ler um ficheiro texto com a seguinte informação:

Equipa1 – Equipa2 : 1 – 0

Equipa2 – Equipa3 : 2 – 2

Equipa1 – Equipa4 : 4 – 0

Equipa2 – Equipa4 : 3 – 1

Equipa4 – Equipa3 : 4 – 0

Equipa5 – Equipa2 : 0 – 0

gostaria de saber se posso usar o fscanf da seguinte maneira para ler as consecutivas linhas:

while(fscanf(f,"%s - %s : %d - %d\n",eq1,eq2,&gol1,&gol2)!=EOF){

}

Share this post


Link to post
Share on other sites
pmg

O melhor é leres linhas completas com fgets() e depois tirar a informacao de cada linha, possivelmente com sscanf().

char linha[120];
while (fgets(linha, sizeof linha, f)) {
   if (sscanf(linha, "%s-%s:%d-%d", eq1, eq2, &gol1, &gol2) == 4) {
       /* informacoes reconhecidas */
   } else {
       /* informacoes na linha nao foram reconhecidas */
   }
}

Edited by pmg

What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
Trinkes

O melhor é leres linhas completas com fgets() e depois tirar a informacao de cada linha, possivelmente com sscanf().

char linha[120];
while (fgets(linha, sizeof linha, f)) {
if (sscanf(linha, "%s-%s:%d-%d", eq1, eq2, &gol1, &gol2) == 4) {
	/* informacoes reconhecidas */
} else {
	/* informacoes na linha nao foram reconhecidas */
}
}

eu já tinha tentado isso também mas só me lê um valor...tal como no fscanf...não percebo porquê...vou por aqui a função:

struct equipa* func(char *fich, int *n_equipas){
char eq1[20],eq2[20],linha[100];
int gol1,gol2,i,ver1=0,ver2=0,eq_actuais=0;
struct equipa *e;
FILE *f;
e=malloc(sizeof(struct equipa)*(*n_equipas));
f=fopen(fich,"r");
for(i=0;i<*n_equipas;i++){
 (e+i)->d=0;
 (e+i)->v=0;
 (e+i)->e=0;
 (e+i)->jogos=0;
}
while (fgets(linha, sizeof linha, f)) {
 if (sscanf(linha, "%s - %s : %d - %d", eq1, eq2, &gol1, &gol2) == 4) {
  for(i=0;i<*n_equipas || ver1==0 || ver2==0;i++){
if(strcmp(eq1,(e+i)->nome)==0){
 if(gol1>gol2)
  (e+i)->v++;
 if(gol1=gol2)
  (e+i)->e++;
 if(gol1<gol2)
  (e+i)->d++;
 (e+i)->jogos++;
 ver1=1;
}
if(strcmp(eq2,(e+i)->nome)==0){
 if(gol2>gol1)
  (e+i)->v++;
 if(gol1=gol2)
  (e+i)->e++;
 if(gol2<gol1)
  (e+i)->d++;
 (e+i)->jogos++;
 ver2=1;
}
  }
  if (ver1==0){
strcpy((e+eq_actuais)->nome,eq1);
if(gol1>gol2)
 (e+eq_actuais)->v++;
if(gol1=gol2)
 (e+eq_actuais)->e++;
if(gol1<gol2)
 (e+eq_actuais)->d++;
(e+eq_actuais)->jogos++;
  }
  if (0==ver2){
strcpy((e+eq_actuais)->nome,eq2);
if(gol1<gol2)
 (e+eq_actuais)->v++;
if(gol1=gol2)
 (e+eq_actuais)->e++;
if(gol1>gol2)
 (e+eq_actuais)->d++;
(e+eq_actuais)->jogos++;
  }
 } else {
  /* informacoes na linha nao foram reconhecidas */
 }
}


return e;
}

O fgets lê tudo bem...mas depois o sscanf já não

Edited by Trinkes

Share this post


Link to post
Share on other sites
brunoais

E o que é que o fgets lê, mais exactamente?


"[Os jovens da actual geração]não lêem porque não envolve um telecomando que dê para mirar e atirar, não falam porque a trapalhice é rainha e o calão é rei" autor: thoga31

Life is a genetically transmitted disease, induced by sex, with death rate of 100%.

Share this post


Link to post
Share on other sites
HappyHippyHippo

tens a certeza que os dados estão nesse formato (com espaços e tudo) ?


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
Trinkes

tens a certeza que os dados estão nesse formato (com espaços e tudo) ?

sim...eu fiz copy paste para aqui...se quiseres posso fazer upload=x

E o que é que o fgets lê, mais exactamente?

Deveria ler uma linha inteira..e lê correctamente mas depois o sscanf só consegue ler a primeira equipa.

Share this post


Link to post
Share on other sites
HappyHippyHippo

sim...eu fiz copy paste para aqui...se quiseres posso fazer upload=x

parece ser a única solução


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
HappyHippyHippo

faz isto :

 int result = 0;

 result = sscanf(linha, "%s - %s : %d - %d", eq1, eq2, &gol1, &gol2);
 printf("sscanf result : %d\n", result);
 if (result == 4) {


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
Trinkes

faz isto :

 int result = 0;

 result = sscanf(linha, "%s - %s : %d - %d", eq1, eq2, &gol1, &gol2);
 printf("sscanf result : %d\n", result);
 if (result == 4) {

o result deu 1...

Sem_T_tulo.png

Share this post


Link to post
Share on other sites
HappyHippyHippo

não acredito ... tens a porcaria do hifen vindo do office !!!

edita essa cena no notepad e altera todas as '-' por '-' reais

e nunca copies nada vinda do office !!!!!!!!!

Edited by HappyHippyHippo
  • Vote 1

IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
Trinkes

não acredito ... tens a porcaria do hifen vindo do office !!!

edita essa cena no notepad e altera todas as '-' por '-' reais

e nunca copies nada vinda do office !!!!!!!!!

E pronto...assim se perde um dia...

Não fazia ideia que isto poderia acontecer...Eles não usam a tabela ascii?

de qualquer forma está resolvido...muito obrigado pela atenção, nunca iria descobrir..

Share this post


Link to post
Share on other sites
simaocbr

podias meter aqui a tua resolução? tambem estou a treinar e nao estou a ver como vou meter as coisas para a lista

Share this post


Link to post
Share on other sites
Trinkes

podias meter aqui a tua resolução? tambem estou a treinar e nao estou a ver como vou meter as coisas para a lista

Se estás a fazer o mesmo exercício que eu não podes usar listas..tens de alocar dinamicamente, é possível fazê-lo visto que à partida já sabes o número de equipas(é enviado para a função).

O código final com que fiquei foi:

struct equipa* func(char *fich, int *n_equipas){
char eq1[20],eq2[20],linha[100];
int gol1,gol2,i,ver1=0,ver2=0,eq_actuais=0,result=0;
struct equipa *e;
FILE *f;
e=malloc(sizeof(struct equipa)*(*n_equipas));
f=fopen(fich,"r");
for(i=0;i<*n_equipas;i++){
 (e+i)->d=0;
 (e+i)->v=0;
 (e+i)->e=0;
 (e+i)->jogos=0;
}

while (fgets(linha, sizeof linha, f)) {
 ver1=0;
 ver2=0;
 result = sscanf(linha, "%s - %s : %d - %d", eq1, eq2, &gol1, &gol2);
 if (result == 4) {
  for(i=0;i<eq_actuais;i++){
if(strcmp(eq1,(e+i)->nome)==0){
 if(gol1>gol2)
  (e+i)->v++;
 if(gol1==gol2)
  (e+i)->e++;
 if(gol1<gol2)
  (e+i)->d++;
 (e+i)->jogos++;
 ver1=1;
}
if(strcmp(eq2,(e+i)->nome)==0){
 if(gol2>gol1)
  (e+i)->v++;
 if(gol1==gol2)
  (e+i)->e++;
 if(gol2<gol1)
  (e+i)->d++;
 (e+i)->jogos++;
 ver2=1;
}
  }
  if (ver1==0){
strcpy((e+eq_actuais)->nome,eq1);
if(gol1>gol2)
 (e+eq_actuais)->v++;
if(gol1==gol2)
 (e+eq_actuais)->e++;
if(gol1<gol2)
 (e+eq_actuais)->d++;
(e+eq_actuais)->jogos++;
eq_actuais++;
  }
  if (0==ver2){
strcpy((e+eq_actuais)->nome,eq2);
if(gol1<gol2)
 (e+eq_actuais)->v++;
if(gol1==gol2)
 (e+eq_actuais)->e++;
if(gol1>gol2)
 (e+eq_actuais)->d++;
(e+eq_actuais)->jogos++;
eq_actuais++;
  }
 } else {
  printf(" informacoes na linha nao foram reconhecidas ");
 }
}
return e;
}

Já verifiquei e penso que está a fazer tudo correctamente

Edited by Trinkes

Share this post


Link to post
Share on other sites
HappyHippyHippo

é de lembrar que o vosso professor é uma pessoa inteligente e deverá seguir de alguma forma o fórum ou fazer uma pesquisa na net da qual este tópico aparecerá, logo o uso do seguinte código será desaconselhado.

no entanto, é bom para vos elucidar de algumas maneira de como fazer as coisas assim como de um ponto muito importante sobre os argumentos da função:

#define BUFFER_SIZE 256;

/**
* Função que lê um ficheiro de resultados retornando a lista de equipas lidas do ficheiro,
* assim como os seu resultados
*
* NOTA : o argumento n_equipas não é para fornecer o número de equipas,
* mas sim para retornar o número de equipas criadas/lidas do ficheiro !!!
*
* @param fich      Nome do ficheiro do qual os dados serão lidos
* @param n_equipas Ponteiro que guardará o número de equipas lidas do ficheiro
* @return          Ponteiro com uma lista alocada dinamicamente contendo a informação das equipas lidas do ficheiro
*/
struct equipa * func(char * fich, int * n_equipas) {
struct equipa * teams = NULL, * aux = NULL, * team1 = NULL, team2 = NULL;

char buffer[bUFFER_SIZE], team1_name[bUFFER_SIZE], team2_name[bUFFER_SIZE];
unsigned int team1_score = 0, team2_score = 0;

FILE * fd = NULL;
unsigned int iter = 0;

/* abrir o ficheiro */
if (fopen(fich, "r") == NULL)
	return NULL;

/* ciclo de leitura */
*n_equipas = 0;
while (fgets(buffer, BUFFER_SIZE, fd)) {
	/* interpretar linha */
	if (sscanf(buffer, "%s - %s : %d - %d", team1_name, team2_name, &team1_score, &team2_score) == 4) {
		team1 = NULL;
		team2 = NULL;

		/* ciclo de pesquisa das equipas já criada */
		iter = 0;
		while (iter < *n_equipas && team1 == NULL && team2 == NULL) {
			/* verificação da primeira equipa */
			if (team1 == NULL && strcmp(teams[iter].nome, team1_name) == 0)
				team1 = &teams[iter];

			/* verificação da segunda equipa */
			if (team2 == NULL && strcmp(teams[iter].nome, team2_name) == 0)
				team2 = &teams[iter];

			iter++;
		}

		/* verificar se é para criar a primeira equipa */
		if (team1 == NULL) {
			/* verificar se é a primeira alocação */
			if (teams == NULL) {
				/* malloc */
				if ((teams = malloc(sizeof(struct equipa))) == NULL)
					return NULL;
			} else {
				/* realloc */
				if ((aux = realloc(teams, sizeof(struct equipa) * ((*n_equipas) + 1))) == NULL) {
					free(teams);
					return NULL;
				}
				teams = aux;
			}

			/* gravar a informação da equipa */
			strcpy(teams[*n_equipas].nome, team1_name);
			teams[*n_equipas].v = teams[*n_equipas].e = teams[*n_equipas].d = 0;

			/* guardar ponteiro para a equipa */
			team1 = &teams[*n_equipas];

			*n_equipas += 1;
		}

		/* verificar se é para criar a segunda equipa */
		if (team1 == NULL) {
			/* realloc (será sempre um realloc, a primeira tem de existir) */
			if ((aux = realloc(teams, sizeof(struct equipa) * ((*n_equipas) + 1))) == NULL) {
				free(teams);
				return NULL;
			}
			teams = aux;

			/* gravar a informação da equipa */
			strcpy(teams[*n_equipas].nome, team2_name);
			teams[*n_equipas].v = teams[*n_equipas].e = teams[*n_equipas].d = 0;

			/* guardar ponteiro para a equipa */
			team2 = &teams[*n_equipas];

			*n_equipas += 1;
		}

		/* actualizar resultados das equipas */
		if (team1_score < team2_score) {
			team1->d++;
			team2->v++;
		} else if (team1_score > team2_score) {
			team1->v++;
			team2->d++;
		} else {
			team1->e++;
			team2->e++;
		}
	}
}

fclose(fich);
return teams;
}


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
Trinkes

Tens razão...fui verificar o enunciado e era assim que deveria ter sido resolvido o exercício...erro meu ao ler o enunciado, quando o fiz percebi mal e pensava que recebia o número de equipas por argumento.

Edited by Trinkes

Share this post


Link to post
Share on other sites
HappyHippyHippo

Eu estou a fazer exercícios e eles lá dizem que temos de usar alocação dinâmica e que a função recebe por ponteiro o número de equipas existentes no ficheiro, por isso é que fiz daquela maneira.

isso não faz sentido. imagina que vais ao ficheiro e editas qualquer coisa adicionando uma equipa, a função deixa de funcionar correctamente


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
Trinkes

isso não faz sentido. imagina que vais ao ficheiro e editas qualquer coisa adicionando uma equipa, a função deixa de funcionar correctamente

Sim...tens razão...fui reler o enunciado e o erro foi meu ao ler.

Tira-me só uma dúvida sfv:

O realloc devolve um ponteiro para o inicio do bloco de memória alocada e copia o que estava no bloco anterior certo?

E o que acontece se o bloco for menor depois do realloc?

Share this post


Link to post
Share on other sites
HappyHippyHippo

o comportamento do realloc não é exactamente esse.

o realloc funciona desta maneira:

- se for possível usar o local actual, existem duas situações dentro deste esquema

- se o número de bytes a serem re-alocados forem menos do que o original, então é só libertar o excedente ("perdendo" o que lá existe)

- se o número de bytes a serem re-alocados forem mais do que o original, então o resto é alocado (normalmente com "lixo")

no entanto, como o local da memória é o mesmo, não necessitas de te preocupar com nada

- se não for possível usar o local actual (só acontece quando estás a aumentar o número de bytes necessários)

- os bytes da memória original são copiados para a memória agora alocada e a memória original é libertada

novamente, não necessitas de preocupar com nada sobre os dados existentes na memória.

no entanto, é necessário ter uma preocupação no uso do realloc:


void * mem = malloc(20); // vamos supor que o malloc é realizado com sucesso

mem = realloc(mem, 40); // agora imagina que o realloc falha e retorna NULL
// o realloc falha, mas nada acontece à memória previamente alocada
// no entanto, estás a perder o ponteiro para a memória alocada com o malloc anterior

// é por isso que é necessário fazer realloc com um ponteiro auxiliar
void * aux = NULL;

if ((aux = realloc(mem, 40)) == NULL) { // se o realloc falhar, não há problema porque
// desta forma não estás a perder o ponteiro para o malloc anterior
// erro ...
}
mem = aux; // seja aux um ponteiro para a mesma posição ou uma nova posição, mem apontará para a posição correcta
[/Code]

edit : adicionado código de verificação na chamada do realloc

Edited by HappyHippyHippo

IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
Trinkes

o comportamento do realloc não é exactamente esse.

o realloc funciona desta maneira:

- se for possível usar o local actual, existem duas situações dentro deste esquema

- se o número de bytes a serem re-alocados forem menos do que o original, então é só libertar o excedente ("perdendo" o que lá existe)

- se o número de bytes a serem re-alocados forem mais do que o original, então o resto é alocado (normalmente com "lixo")

no entanto, como o local da memória é o mesmo, não necessitas de te preocupar com nada

- se não for possível usar o local actual (só acontece quando estás a aumentar o número de bytes necessários)

- os bytes da memória original são copiados para a memória agora alocada e a memória original é libertada

novamente, não necessitas de preocupar com nada sobre os dados existentes na memória.

no entanto, é necessário ter uma preocupação no uso do realloc:


void * mem = malloc(20); // vamos supor que o malloc é realizado com sucesso

mem = realloc(mem, 40); // agora imagina que o realloc falha e retorna NULL
// o realloc falha, mas nada acontece à memória previamente alocada
// no entanto, estás a perder o ponteiro para a memória alocada com o malloc anterior

// é por isso que é necessário fazer realloc com um ponteiro auxiliar
void * aux = NULL;

aux = realloc(mem, 40); // se o realloc falhar, não há problema porque
// desta forma não estás a perder o ponteiro para o malloc anterior
mem = aux; // seja aux um ponteiro para a mesma posição ou uma nova posição, mem apontará para a posição correcta
[/Code]

se nesse caso o realloc falhar vai fazer return NULL, ou seja aux=NULL, quando fazes mem=aux não vai ficar NULL na mesma?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.