[C] Leggere dati da un .txt e sistemarli in una struttura

frab1
Sono sempre fermo alle strutture.
Questa volta l'esercizio proposto mi chiede, dato un file .txt in cui sono inserite 4 squadre di calcio(con dati relativi a nome squadra,vittorie,sconfitte,pareggi,gol fatti,subiti tutti spaziati) , di scrivere un programmache,definita un'opportuna struttura dati, carichi questi dati in memoria, e scriva un secondo file ove in ogni riga si hanno: nome_squadra,numero_partite giocate,punti,media gol fatti e subiti.

Io ho pensato alla fscanf, e ho scritto questo sorgente...
#include <stdio.h>

struct classifica{
	char squadra;
	int vinte;
	int perse;
	int pareggi;
	int goal;
	int subiti;
};

int main(void)
{
	struct classifica squad1;
	FILE *fp;
	fp=fopen("input_classifica.txt","r");
	fscanf(fp,"%c %d %d %d %d %d",&squad1.squadra,&squad1.vinte,&squad1.perse,&squad1.pareggi,&squad1.goal,&squad1.subiti);
	fclose(fp);

	printf("%c ha vinto %d partite segnando %d goals\n",squad1.squadra,squad1.vinte,squad1.goal);
}


La cosa che non mi è chiara è: le strutture hanno una "forma matriciale"? Provando a stampare qualcosa mi ritorna i valori relatiivi solo alla prima riga...come posso fare per spostarmi alla riga successiva e come posso gestire i dati relativi alle singole squadre in modo da combinarli fra loro per fornire l'outout desiderato? :cry:

Risposte
apatriarca
In che senso "hanno una forma matriciale"? Devi creare un array di strutture e poi fare un ciclo di lettura in cui leggi una riga per volta che hai fatto in quel codice.

frab1
eh infatti mi sembrava di aver capito STRUTTURA=TABELLA con elementi che possono aver tipi diversi, invece no....
per dichiarare un array di strutture, come posso fare? non saprei che tipo assegnare all'array...struct? :-(

EDIT: ho provato in questa maniera che formalemente mi sembra corretta..
#include <stdio.h>

struct classifica{
	char squadra;
	int vinte;
	int perse;
	int pareggi;
	int goal;
	int subiti;
};

int main(void)
{
	struct classifica squad[4];
	int i=0;
	FILE *fp;
	fp=fopen("input_classifica.txt","r");
	for(i=0;i<=4;i++) {
	fscanf(fp,"%c %d %d %d %d %d",&squad[i].squadra,&squad[i].vinte,&squad[i].perse,&squad[i].pareggi,&squad[i].goal,&squad[i].subiti);
	}	
	fclose(fp);
/*	for(i=0;i<4;i++) {
	printf("%c ha vinto %d partite segnando %d goals\n",squad[i].squadra,squad[i].vinte,squad[i].goal);
	}
*/
}


COMPILA, ma mi restituisce un bell'errore di segmentazione... :?

Dante.utopia
"frab":
COMPILA, ma mi restituisce un bell'errore di segmentazione... :?


Ti consiglio questa lettura:

http://www.fis.uniroma3.it/CALCOLO_DOC/unix/appuntilinux/al125.htm

apatriarca
Il problema è che hai fatto un ciclo da 0 a 4 compreso, ma l'array ha solo 4 elementi i cui indici vanno da 0 a 3.

frab1
"Dante.utopia":

Ti consiglio questa lettura:

http://www.fis.uniroma3.it/CALCOLO_DOC/unix/appuntilinux/al125.htm


GRAZIE! La tengo come riferimento valido. Mi sembra un ottimo documento.

"apatriarca":

Il problema è che hai fatto un ciclo da 0 a 4 compreso, ma l'array ha solo 4 elementi i cui indici vanno da 0 a 3.


ho sistemato, ma mi legge ora la prima riga correttamente, poi mi legge dati a caso, poi mi legge la seconda riga correttamente e poi mi legge un'altra riga di dati a caso ed esce...
Potrebbe esserci qualcosa di sbagliato nell'incremento? :roll:
#include <stdio.h>

struct classifica{
	char squadra;
	int vinte;
	int perse;
	int pareggi;
	int goal;
	int subiti;
};

int main(void)
{
	struct classifica squad[4];
	int i=0;
	FILE *fp;
	fp=fopen("input_classifica.txt","r");
	for(i=0;i<4;i++) {
	fscanf(fp,"%c %d %d %d %d %d",&squad[i].squadra,&squad[i].vinte,&squad[i].perse,&squad[i].pareggi,&squad[i].goal,&squad[i].subiti);
	}	
	fclose(fp);
	for(i=0;i<4;i++) {
	printf("%c ha vinto %d partite segnando %d goals\n",squad[i].squadra,squad[i].vinte,squad[i].goal);
	}

}

apatriarca
Il problema è dovuto all'uso di %c. Legge un singolo carattere che non deve necessariamente essere alfanumerico o stampabile. Puoi inserire uno spazio davanti a %c per fare in modo che gli spazi (e quindi anche il carattere per andare a capo) vengano ignorati.

frab1
ok! La prendo come regola fissa per ignorare l'a capo nelle scanf! Grazie

frab1
AGGIORNAMENTO:
provando a leggere il nome completo della squadra, e inserendo un puntatore a char nella struttura, ho un errore di segmentazione, probabilmente presente nella fscanf...
#include <stdio.h>

struct classifica{
	char *squadra;
	int vinte;
	int perse;
	int pareggi;
	int goal;
	int subiti;
};

int main(void)
{
	struct classifica squad[4];
	int i=0;
	FILE *fp;
	fp=fopen("input_classifica.txt","r");
	for(i=0;i<4;i++) {
	fscanf(fp," %s %d %d %d %d %d",squad[i].squadra,&squad[i].vinte,&squad[i].perse,&squad[i].pareggi,&squad[i].goal,&squad[i].subiti);
	}	
	fclose(fp);
	for(i=0;i<4;i++) {
	printf("%s ha vinto %d partite segnando %d goals\n",squad[i].squadra,squad[i].vinte,squad[i].goal);
	}

}

apatriarca
Un puntatore è solo un indirizzo di memoria, non una stringa correttamente allocata. Quando viene creato conterrà un valore completamente casuale e quando fscanf tenta di scrivere in quella locazione di memoria casuale causa il tuo errore di segmentazione. Devi usare un array di char o allocare una stringa dinamicamente prima della lettura. Per esempio, supponendo che il nome della squadra abbia meno di 31 caratteri, potresti scrivere qualcosa come il seguente:
struct classifica{
   char squadra[32];
   int vinte;
   int perse;
   int pareggi;
   int goal;
   int subiti;
};

// ...

fscanf(fp,"%31s %d %d %d %d %d", squad[i].squadra, &squad[i].vinte, &squad[i].perse, 
    &squad[i].pareggi, &squad[i].goal, &squad[i].subiti);

Nota l'inserimento nella stringa di formato della dimensione massima della stringa..

frab1
capito, ho provato anche ad omettere il 31 nella stringa di formato..e funziona ugualmente...è indispensabile?

frab1
ora sto provando ad utilizzare i dati letti per creare un file che per ogni squadra mi dia :
-n° partite giocate;
-punti;
-media gol fatti;
-media gol subiti;

mi sono creato una nuova struttura analisi e ho creato un vettore an[4] di strutture analisi.
Ma inizio ad aver problemi anche solo con il copiare il nome squadra da una struttura all'altra...
#include <stdio.h>

struct classifica{
	char squadra[32];
	int vinte;
	int perse;
	int pareggi;
	int goal;
	int subiti;
};

struct analisi{
	char squadra[32];
	int partite;
	int punti;
	float media_segnati;
	float media_subiti;
};

int main(void)
{
	struct classifica squad[4];
	int i=0;
	FILE *fp;
	fp=fopen("input_classifica.txt","r");
	for(i=0;i<4;i++) {
	fscanf(fp," %31s %d %d %d %d %d",squad[i].squadra,&squad[i].vinte,&squad[i].perse,&squad[i].pareggi,&squad[i].goal,&squad[i].subiti);
	}	
	fclose(fp);
	for(i=0;i<4;i++) {
	printf("%s ha vinto %d partite segnando %d goals\n",squad[i].squadra,squad[i].vinte,squad[i].goal);
	}
	
	struct analisi an[4];

	for(i=0;i<4;i++) {
		an[i].squadra=squad[i].squadra;
	}
	i=0;
		printf(" %s\n",an[i].squadra);

}

Avrei pensato di scriverlo cosi, ma mi restituisce un errore di compilazione...mentre scrivendolo cosi:
an[i].squadra[i]=squad[i].squadra[i];

compila ma stampa caratteri assurdi.... :roll: :roll:

Perche' sono cosi ste strutture?!!?!? :cry: :cry:

apatriarca
Non ha niente a che fare con le strutture il tuo problema. Non puoi copiare una stringa in un altra in quel modo in C.. Ti consiglio di ripassarti la teoria sulle stringhe. Per quanto riguarda invece la dimensione nella stringa di formato, non è necessaria ma evita possibili problemi nel caso in cui la stringa inserita sia troppo lunga.

frab1
la strcpy...vero...:-)
Provo a sistemarlo!! Ero convinto, sbagliando in pieno, che i contenuti delle strutture si potessero copiare come tranquillamente..

apatriarca
Puoi copiare una intera struttura, ma non i singoli campi. Personalmente credo che sarebbe stato meglio supportare in C tali costrutti invece di richiedere la scrittura dei cicli equivalenti.

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.