[Risolto] Problema con liste in C

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
Feanaro
Prode Principiante
Messaggi: 76
Iscrizione: venerdì 2 marzo 2007, 16:47

[Risolto] Problema con liste in C

Messaggio da Feanaro »

Devo realizzare un programma in C che mi è stato assegnato come compito, però dopo averlo fatto, controllato e ricontrollato non riesco a capire che cosa non va...  >:(

La consegna del programma è questa (il testo è un po' lungo, ma molto scorrevole):

Codice: Seleziona tutto

Realizzare un programma in linguaggio C per la visualizzazione dell'andamento della temperatura di un 
paziente su un foglio di carta utilizzando un plotter. Il plotter è costituito da un braccio meccanico
che impugna una penna. Il plotter muove la penna su un foglio; la penna può essere alzata ( ed in tal 
caso non tocca il foglio) o abbassata ( in tal caso tocca il foglio ).
I comandi che il plotter è in grado di eseguire sono alzare la penna, abbassare la penna, e muovere il
braccio in posizione (X, Y), oltre ad un comando di inizializzazione che pone il plotter nella posizione
(0, 0) con la penna in su. Quando il braccio meccanico viene mosso in una posizione e la penna è abbassata
traccia una linea retta dalla posizione precedente alla nuova.
L'invio dei comandi al plotter deve essere ovviamente "simulato". Esempio di funzioni e loro effetto:
	void Initialize ( void ) : stampa su video: Posizione (0, 0), penna su.
	void Muovi ( int X, int Y ): stampa : Penna spostata alla posizione ( X, Y).
	void Abbassa_penna ( void ): stampa : Abbassa la penna.
	void Alza_penna ( void ): stampa: Alza la penna.

I dati da visualizzare sono in un file di tipo testo "cc.dat" contenente le temperature rilevate in un
mese per tutti i pazienti dell'ospedale; ogni linea contiene:
	il giorno (del mese) della rilevazione della temperatura (int);
	la temperatura che è stata rilevata (float);
	il nome del paziente (stringa di 20 caratteri);

I dati sul file "cc.dat" sono ordinati in ordine crescente di giorno.
Il programma deve accettare da tastiera il nome del paziente di cui si devono visualizzare i dati, poi
disegnare con il plotter l'andamento della temperatura del paziente, inviando al plotter (simulato) gli
opportuni comandi. Si visualizzi solo la parte intera della temperatura. Il ciclo di richieste continua
fino all'introduzione di EOF (S.O. Windows: Ctrl+Z; S.O. UNIX/Linux Ctrl+C).

È possibile che per una certa data non esistano rilevazioni per il paziente: in tal caso il programma
non deve tracciare la linea in quella data. Ad esempio, se il file contiene i seguenti dati:
	1	36.5	ROSSI
	1	36.6	BIANCHI
	2	37.1	ROSSI
	3	36.1	BIANCHI
	4	37.2	ROSSI
	5	37.1	ROSSI

e viene richiesto di visualizzare la temperatura di ROSSI, allora il programma deve disegnare un segmento
da (1, 36) a (2, 37) ed uno da (4, 37) a (5, 37). I comandi inviati al plotter (e visti dall'utente)
devono essere:
Posizione (0, 0), penna su.
Penna spostata in posizione (1, 36).
Penna giù.
Penna spostata in posizione (2, 37).
Penna su.
Penna spostata in posizione (4, 37).
Penna giù.
Penna spostata in posizione (5, 37).

NB: è richiesto che il file sia letto una sola volta e il contenuto salvato in una base dati dinamica.



Invece dell'EOF ho usato il carattere '1' per finire, perché devo ancora capire bene come funziona la funzione feof.
Nel mio programma ho utilizzato una lista di liste per agevolare lo scorrimento dei dati di una stessa persona.
Posto anche il codice sorgente:

Codice: Seleziona tutto

# include <stdio.h>

# include <stdlib.h>

# include <string.h>

# include <ctype.h>

# include <math.h>

# define MAX_NOME 20



/********************************************************

*  Strutture dati

********************************************************/



typedef struct _PAZIENTE {

	char nome [ 20 ];
	struct _DATI * dati;
	struct _PAZIENTE * next;

} PAZIENTE;

typedef struct _DATI {
	int data;
	int temp_int;
	float temp_fraz;
	struct _DATI * next;
} DATI;

typedef struct _LIST {
	PAZIENTE * head;
} LIST;



/********************************************************

*  Prototipi

********************************************************/



void Initialize ( void );
void Muovi ( int X, int Y );
void Abbassa_penna ( void );
void Alza_penna ( void );
LIST * CreaLista ( FILE * file );
void LeggiFile ( FILE * file, LIST * L );
void Alloca ( int data, int t_i, int t_f, char * nome, LIST * L );
LIST * NewList ( void );
void GestisciPlotter ( LIST * L );
FILE *ApriFile( int modo_di_apertura, int azione );
void StampaLista ( LIST * L );



/********************************************************

*  Algoritmo

********************************************************/

int main ( void )
{
	FILE * file;
	LIST * ListaPazienti;

	file = ApriFile ( 1, 1);

	ListaPazienti = CreaLista ( file );

	fclose ( file );

	StampaLista( ListaPazienti );

	GestisciPlotter ( ListaPazienti );

	printf ( "\nFine del Programma.\n" );

	return 0;
}

void Initialize ( void )
{
	printf ( "Posizione ( 0, 0), penna su.\n" );

	return;
}

void Muovi ( int X, int Y )
{
	printf ( "Penna spostata alla posizione ( %2d, %2d).\n", X, Y );

	return;
}

void Abbassa_penna ( void )
{
	printf ( "Abbassa la penna.\n" );

	return;
}

void Alza_penna ( void )
{
	printf ( "Alza la penna.\n" );

	return;
}

LIST * CreaLista ( FILE * file )
{
	LIST * L;

	L = NewList ();

	LeggiFile ( file, L );

	return L;
}

void LeggiFile ( FILE * file, LIST * L )
{
	PAZIENTE * P;
	DATI * D;
	float tempF;
	int data, tempI, i = 0;
	char nome [ MAX_NOME ];

	while ( !i ) {
		if ( fscanf ( file, "%d", &data ) == EOF )
			i = 1;
		else {
			fscanf ( file, "%d%f%s", &tempI, &tempF, nome );
			Alloca ( data, tempI, tempF, nome, L );
		}
	}
}

void Alloca ( int data, int t_i, int t_f, char * nome, LIST * L )
{
	PAZIENTE * P, * S;
	DATI * D, * T;
	int i = 0;

	S = L -> head;

	if ( S == NULL ) {
		if (	( P = ( PAZIENTE * ) malloc ( sizeof ( PAZIENTE ) ) ) != NULL &&
			( D = ( DATI * ) malloc ( sizeof ( DATI ) ) ) != NULL ) {

			L -> head = P;
			strcpy ( P -> nome, nome );
			P -> dati = D;
			D -> data = data;
			D -> temp_int = t_i;
			D -> temp_fraz = t_f;
			D -> next = NULL;
		}
		else
			exit ( fprintf ( stderr, "Yeuch!\n" ) );
	}
	else {
		while ( !i ) {
			if ( strncmp ( S -> nome, nome, strlen ( nome ) ) == 0 )
				i = 1;
			else {
				if ( S -> next != NULL )
					S = S -> next;
				else
					i = 2;
			}
		}

		if ( i = 1 ) {
			if ( ( D = ( DATI * ) malloc ( sizeof ( DATI ) ) ) != NULL ) {
				T = S -> dati;
				while ( T -> next != NULL )
					T = T -> next;
				T -> next = D;
				D -> data = data;
				D -> temp_int = t_i;
				D -> temp_fraz = t_f;
				D -> next = NULL;
			}
			else
				exit ( fprintf ( stderr, "Yeuch!\n" ) );
		}
		else {
			if ( 	( P = ( PAZIENTE * ) malloc ( sizeof ( PAZIENTE ) ) ) != NULL &&
				( D = ( DATI * ) malloc ( sizeof ( DATI ) ) ) != NULL ) {

				S -> next = P;
				P -> next = NULL;
				strcpy ( P -> nome, nome );
				P -> dati = D;
				D -> data = data;
				D -> temp_int = t_i;
				D -> temp_fraz = t_f;
				D -> next = NULL;
			}
			else
				exit ( fprintf ( stderr, "Yeuch!\n" ) );
		}
	}

	return;
}

LIST * NewList ( void )
{
	LIST * L;

	if ( ( L = ( LIST * ) malloc ( sizeof ( LIST ) ) ) != NULL )
		L -> head = NULL;
	else
		exit ( fprintf ( stderr, "Yeuch!\n" ) );

	return L;
}

void GestisciPlotter ( LIST * L )
{
	PAZIENTE * P;
	DATI * D;
	char richiesta [ MAX_NOME ];
	int i = 0;

	do {
		printf ( "Inserire nome paziente e premere <ENTER>, 1 per uscire: " );

		scanf ( "%s", richiesta );

		if ( richiesta [ 0 ] != '1' ) {

			P = L -> head;

			while ( strncmp ( P -> nome, richiesta, strlen ( richiesta ) ) != 0 && P -> next != NULL )
				P = P -> next;
			if ( P -> next == NULL )
				printf ( "Nome non corretto.\n" );	
			else {
				Initialize ();
				D = P -> dati;
				Muovi ( D -> data, D -> temp_int );
				Abbassa_penna ();
				if ( D -> next == NULL )
					Alza_penna ();
				else {
					do {
						if ( D -> next -> data == ( D -> data + 1 ) ) {
							D = D -> next;
							Muovi ( D -> data, D -> temp_int );
						}
						else {
							Alza_penna ();
							D = D -> next;
							Muovi ( D -> data, D -> temp_int );
							Abbassa_penna ();
						}
					}
					while ( D -> next == NULL );
				}
			}
		}
		else
			i  = 1;				
	}
	while ( !i );

	return;
}

FILE *ApriFile( int modo_di_apertura, int azione )
{
	/****************************************************************
	*  MODO DI APERTURA: 1 lo apre in lettura, 2 lo apre in scrittura
	*  AZIONE: 1 continua a chiedere, 2 esce dal programma
	****************************************************************/
	FILE *ingresso;
	char nome_file[200], risposta[2];
	int continua = 1;

	while( continua ) {
		printf( "inserisci il nome del file da elaborare: " );
		scanf( "%s", nome_file );
		
		ingresso = fopen( nome_file, "r" );
		
		if ( ingresso == NULL ) {
			if ( modo_di_apertura == 1 )
				fprintf( stderr, "Attenzione! Non posso aprire il file %s.\n", nome_file );
			else {
				ingresso = fopen( nome_file, "w" );
				if( ingresso == NULL )
					fprintf( stderr, "Attenzione! Non posso creare il file %s.\n", nome_file );
				else
					printf( "File creato.\n" );
			}
		}
		else {
			if( modo_di_apertura == 1 )
				printf( "File aperto in lettura.\n" );
			else {
				fclose( ingresso );
				ingresso = NULL;
				printf( "Attenzione! Esiste già un file con quel nome si vuole sovrascriverlo? [s/N] " );
				scanf( "%s", risposta );
				if ( ( strcmp ( risposta, "s" ) == 0 ) || ( strcmp( risposta, "S" ) == 0 )) {
					ingresso = fopen( nome_file, "w" );
					if( ingresso == NULL )
						fprintf( stderr, "Attenzione! Non posso sovrascrivere il file.\n" );
					else
						printf( "File %s sovrascritto.\n", nome_file );
				}
			}
		}
		if( ( ingresso == NULL ) && ( azione == 1 ) ) 
			continua = 1;
		else 
			continua = 0;
	}
	if( ingresso == NULL )
		exit( 1 );
	
	return ( ingresso );
}

void StampaLista ( LIST * L )
{
	FILE * f;
	PAZIENTE * P;
	DATI * D;
	int i = 0, j = 0;

	P = L -> head;
	D = P -> dati;

	f = ApriFile ( 2, 1 );

	while ( !i ) {
		fprintf ( f, "%s\n", P -> nome );
		while ( !j ) {
			fprintf ( f, "%5d%5d\n", D -> data, D -> temp_int );
			if ( ( D = D -> next ) == NULL )
				j = 1;
		}
		fprintf ( f, "\n" );
		if ( ( P = P -> next ) == NULL )
			i = 1;
	}
	
	fclose ( f );

	return;
}


Concettualmente non è complesso, tuttavia non capisco perché non funziona.
Aiuto!!
Ultima modifica di Feanaro il martedì 4 settembre 2007, 13:02, modificato 1 volta in totale.
Avatar utente
SatorArepoTenetOperaRotas
Prode Principiante
Messaggi: 20
Iscrizione: venerdì 11 maggio 2007, 19:25

Re: Problema con liste in C

Messaggio da SatorArepoTenetOperaRotas »

cosa non ti funziona di preciso?
hai errori di compilazione?
feof restituisce 0 quando si è giunti alla fine del file per cui il ciclo lo puoi impostare così

Codice: Seleziona tutto

while(!feof(filepointer)){
    ...
}
oppure con un do while, che gestisce sempre meglio la lettura e scrittura
Feanaro
Prode Principiante
Messaggi: 76
Iscrizione: venerdì 2 marzo 2007, 16:47

Re: Problema con liste in C

Messaggio da Feanaro »

Mi sono accorto che nella funzione Alloca avevo commesso un errore logico: un'assegnazione piuttosto che un controllo:
if ( i = 1 ) {      // dati;
while ( T -> next != NULL )
T = T -> next;
...
Ora già funziona qualcosina in maniera più accettabile però non è ancora assolutamente soddisfacente...  >:(
Non ho nessun errore di compilazione né warning di alcun genere, però c'è sicuramente qualche erore subdolo che non trovo nella funzione Alloca che fa si che a nessun paziente oltre al primo della lista vengano associati dati...
In pratica è una semplice lista di lista dove la struttura LIST fa da testa per la lista di strutture PAZIENTE che deve avere ognuna una lista di strutture DATI.
Feanaro
Prode Principiante
Messaggi: 76
Iscrizione: venerdì 2 marzo 2007, 16:47

Re: Problema con liste in C

Messaggio da Feanaro »

Ok ho corretto il codice ed ora il programma funziona!!  (good)

Ecco il codice sorgente corretto:

Codice: Seleziona tutto

# include <stdio.h>

# include <stdlib.h>

# include <string.h>

# include <ctype.h>

# include <math.h>

# define MAX_NOME 20



/********************************************************

*  Strutture dati

********************************************************/



typedef struct _PAZIENTE {

	char nome [ 20 ];
	struct _DATI * dati;
	struct _PAZIENTE * next;

} PAZIENTE;

typedef struct _DATI {
	int data;
	int temp_int;
	float temp_fraz;
	struct _DATI * next;
} DATI;

typedef struct _LIST {
	PAZIENTE * head;
} LIST;



/********************************************************

*  Prototipi

********************************************************/



void Initialize ( void );
void Muovi ( int X, int Y );
void Abbassa_penna ( void );
void Alza_penna ( void );
LIST * CreaLista ( FILE * file );
void LeggiFile ( FILE * file, LIST * L );
void Alloca ( int data, int t_i, int t_f, char * nome, LIST * L );
LIST * NewList ( void );
void GestisciPlotter ( LIST * L );
FILE *ApriFile( int modo_di_apertura, int azione );
void StampaLista ( LIST * L );



/********************************************************

*  Algoritmo

********************************************************/

int main ( void )
{
	FILE * file;
	LIST * ListaPazienti;

	file = ApriFile ( 1, 1);

	ListaPazienti = CreaLista ( file );

	fclose ( file );

//	StampaLista( ListaPazienti );

	GestisciPlotter ( ListaPazienti );

	printf ( "\nFine del Programma.\n" );

	return 0;
}

void Initialize ( void )
{
	printf ( "Posizione ( 0, 0), penna su.\n" );

	return;
}

void Muovi ( int X, int Y )
{
	printf ( "Penna spostata alla posizione ( %2d, %2d).\n", X, Y );

	return;
}

void Abbassa_penna ( void )
{
	printf ( "Abbassa la penna.\n" );

	return;
}

void Alza_penna ( void )
{
	printf ( "Alza la penna.\n" );

	return;
}

LIST * CreaLista ( FILE * file )
{
	LIST * L;

	L = NewList ();

	LeggiFile ( file, L );

	return L;
}

void LeggiFile ( FILE * file, LIST * L )
{
	PAZIENTE * P;
	DATI * D;
	float tempF;
	int data, tempI, i = 0;
	char nome [ MAX_NOME ];

	while ( !i ) {
		if ( fscanf ( file, "%d", &data ) == EOF )
			i = 1;
		else {
			fscanf ( file, "%d%f%s", &tempI, &tempF, nome );
			Alloca ( data, tempI, tempF, nome, L );
		}
	}
}

void Alloca ( int data, int t_i, int t_f, char * nome, LIST * L )
{
	PAZIENTE * P, * S;
	DATI * D, * T;
	int i = 0;

	S = L -> head;

	if ( S == NULL ) {
		if (	( P = ( PAZIENTE * ) malloc ( sizeof ( PAZIENTE ) ) ) != NULL &&
			( D = ( DATI * ) malloc ( sizeof ( DATI ) ) ) != NULL ) {

			L -> head = P;
			strncpy ( P -> nome, nome, strlen ( nome ) + 1 );
			P -> next = NULL;
			P -> dati = D;
			D -> data = data;
			D -> temp_int = t_i;
			D -> temp_fraz = t_f;
			D -> next = NULL;
		}
		else
			exit ( fprintf ( stderr, "Yeuch!\n" ) );
	}
	else {
		while ( !i ) {
			if ( strcmp ( S -> nome, nome ) == 0 )
				i = 1;
			else {
				if ( S -> next != NULL )
					S = S -> next;
				else
					i = 2;
			}
		}

		if ( i == 1 ) {
			if ( ( D = ( DATI * ) malloc ( sizeof ( DATI ) ) ) != NULL ) {
				T = S -> dati;
				while ( T -> next != NULL )
					T = T -> next;
				T -> next = D;
				D -> data = data;
				D -> temp_int = t_i;
				D -> temp_fraz = t_f;
				D -> next = NULL;
			}
			else
				exit ( fprintf ( stderr, "Yeuch!\n" ) );
		}
		else {
			if ( 	( P = ( PAZIENTE * ) malloc ( sizeof ( PAZIENTE ) ) ) != NULL &&
				( D = ( DATI * ) malloc ( sizeof ( DATI ) ) ) != NULL ) {

				S -> next = P;
				P -> next = NULL;
				strncpy ( P -> nome, nome, strlen ( nome ) + 1 );
				P -> dati = D;
				D -> data = data;
				D -> temp_int = t_i;
				D -> temp_fraz = t_f;
				D -> next = NULL;
			}
			else
				exit ( fprintf ( stderr, "Yeuch!\n" ) );
		}
	}

	return;
}

LIST * NewList ( void )
{
	LIST * L;

	if ( ( L = ( LIST * ) malloc ( sizeof ( LIST ) ) ) != NULL )
		L -> head = NULL;
	else
		exit ( fprintf ( stderr, "Yeuch!\n" ) );

	return L;
}

void GestisciPlotter ( LIST * L )
{
	PAZIENTE * P;
	DATI * D;
	char richiesta [ MAX_NOME ];
	int i = 0, cmp = 1;

	do {
		printf ( "Inserire nome paziente e premere < ENTER >, < Ctrl + C > per uscire: " );

		if ( !feof ( stdin ) ) {

			scanf ( "%s", richiesta );

			P = L -> head;

			while ( ( cmp = strcmp ( P -> nome, richiesta ) ) != 0 && P -> next != NULL )
				P = P -> next;
			if ( cmp != 0 )
				printf ( "Nome non corretto.\n" );	
			else {
				Initialize ();
				D = P -> dati;
				Muovi ( D -> data, D -> temp_int );
				Abbassa_penna ();
				if ( D -> next == NULL )
					Alza_penna ();
				else {
					do {
						if ( D -> next -> data == ( ( D -> data ) + 1 ) ) {
							D = D -> next;
							Muovi ( D -> data, D -> temp_int );
						}
						else {
							Alza_penna ();
							D = D -> next;
							Muovi ( D -> data, D -> temp_int );
							Abbassa_penna ();
						}
					}
					while ( D -> next != NULL );
				}
			}
		}
		else
			i  = 1;				
	}
	while ( !i );

	return;
}

FILE *ApriFile( int modo_di_apertura, int azione )
{
	/****************************************************************
	*  MODO DI APERTURA: 1 lo apre in lettura, 2 lo apre in scrittura
	*  AZIONE: 1 continua a chiedere, 2 esce dal programma
	****************************************************************/
	FILE *ingresso;
	char nome_file[200], risposta[2];
	int continua = 1;

	while( continua ) {
		printf( "Inserisci il nome del file da elaborare: " );
		scanf( "%s", nome_file );
		
		ingresso = fopen( nome_file, "r" );
		
		if ( ingresso == NULL ) {
			if ( modo_di_apertura == 1 )
				fprintf( stderr, "Attenzione! Non posso aprire il file %s.\n", nome_file );
			else {
				ingresso = fopen( nome_file, "w" );
				if( ingresso == NULL )
					fprintf( stderr, "Attenzione! Non posso creare il file %s.\n", nome_file );
				else
					printf( "File creato.\n" );
			}
		}
		else {
			if( modo_di_apertura == 1 )
				printf( "File aperto in lettura.\n" );
			else {
				fclose( ingresso );
				ingresso = NULL;
				printf( "Attenzione! Esiste già un file con quel nome si vuole sovrascriverlo? [s/N] " );
				scanf( "%s", risposta );
				if ( ( strcmp ( risposta, "s" ) == 0 ) || ( strcmp( risposta, "S" ) == 0 )) {
					ingresso = fopen( nome_file, "w" );
					if( ingresso == NULL )
						fprintf( stderr, "Attenzione! Non posso sovrascrivere il file.\n" );
					else
						printf( "File %s sovrascritto.\n", nome_file );
				}
			}
		}
		if( ( ingresso == NULL ) && ( azione == 1 ) ) 
			continua = 1;
		else 
			continua = 0;
	}
	if( ingresso == NULL )
		exit( 1 );
	
	return ( ingresso );
}

Mi rimane solo un problema: gestire l'EOF.

Ovvero devo fare in modo che il programma chieda il nome del paziente finché non si introduca l'EOF:
Il programma deve accettare da tastiera il nome del paziente di cui si devono visualizzare i dati, poi
disegnare con il plotter l'andamento della temperatura del paziente, inviando al plotter (simulato) gli
opportuni comandi. Si visualizzi solo la parte intera della temperatura. Il ciclo di richieste continua
fino all'introduzione di EOF (S.O. Windows: Ctrl+Z; S.O. UNIX/Linux Ctrl+C).


Devo usare quindi l'EOF come flag per uscire da un ciclo e non direttamente dal programma come invece fa il mio programma...  ???
Qualche consiglio?? 

Grazie per l'attenzione...  ;)
Avatar utente
SatorArepoTenetOperaRotas
Prode Principiante
Messaggi: 20
Iscrizione: venerdì 11 maggio 2007, 19:25

Re: Problema con liste in C

Messaggio da SatorArepoTenetOperaRotas »

puoi fare

Codice: Seleziona tutto

while(!feof(stdin)){
//leggi dallo standard input con scanf, getchar, quello che vuoi ;)

}
oppure come al solito con un do-while
se vuoi puoi usare una fflush(stdin) per pulire lo stream dopo la scanf ;)
Avatar utente
SatorArepoTenetOperaRotas
Prode Principiante
Messaggi: 20
Iscrizione: venerdì 11 maggio 2007, 19:25

Re: Problema con liste in C

Messaggio da SatorArepoTenetOperaRotas »

ah comunque se non erro in unix EOF è control-D, mentre su mac os x è qualcosa tipo control-D control-Q
Feanaro
Prode Principiante
Messaggi: 76
Iscrizione: venerdì 2 marzo 2007, 16:47

Re: [Risolto] Problema con liste in C

Messaggio da Feanaro »

Ah ecco maledizione!!!!  >:(  >:(

Io continuavo a premere e non capivo perché diavolo non funzionasse, infine ho usato un do-while è tutto funziona a meraviglia. Grazie molte a SatorArepoTenetOperaRotas per l'attenzione e il supporto...  (b2b)

Alla prossima!  ;)
Avatar utente
SatorArepoTenetOperaRotas
Prode Principiante
Messaggi: 20
Iscrizione: venerdì 11 maggio 2007, 19:25

Re: [Risolto] Problema con liste in C

Messaggio da SatorArepoTenetOperaRotas »

del poco che ho fatto
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: 0 utenti iscritti e 4 ospiti