Jump to content

Duvida em fscanf


Trinkes
 Share

Recommended Posts

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){

}
Link to comment
Share on other sites

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!

Link to comment
Share on other sites

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
Link to comment
Share on other sites

Deixo aqui uns prints com as variáveis enquanto estou a fazer debug.

linha.png

linhav2.png

a variável eq2 fica com lixo e depois com o nome da primeira equipa...significa algo isso?

parece ser a única solução

https://dl.dropboxusercontent.com/u/18119333/resultados.txt

está aí o ficheiro.

obrigado pela ajuda

Edited by Trinkes
Link to comment
Share on other sites

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..

Link to comment
Share on other sites

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
Link to comment
Share on other sites

é 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
Link to comment
Share on other sites

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
Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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
Link to comment
Share on other sites

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?

Link to comment
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
 Share

×
×
  • 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.