Torna indietro   Hardware Upgrade Forum > Software > Programmazione

PC Specialist Lafité 14 AI AMD: assemblato come vuoi tu
PC Specialist Lafité 14 AI AMD: assemblato come vuoi tu
Il modello "build to order" di PCSpecialist permette di selezionare una struttura base per un sistema, personalizzandolo in base alle specifiche esigenze con una notevole flessibilità di scelta tra i componenti. Il modello Lafité 14 AI AMD è un classico notebook clamshell compatto e potente, capace di assicurare una elevata autonomia di funzionamento anche lontano dalla presa di corrente
Recensione Nothing Phone 4(a): sempre iconico ma ora più concreto
Recensione Nothing Phone 4(a): sempre iconico ma ora più concreto
Nothing con il suo nuovo Phone 4(a) conferma la sua identità visiva puntando su una costruzione che nobilita il policarbonato. La trasparenza resta l'elemento cardine, arricchita da una simmetria interna curata nei minimi dettagli. Il sistema Glyph si evolve, riducendosi nelle dimensioni ma aumentando l'utilità quotidiana grazie a nuove funzioni software integrate e notifiche visive. Ecco tutti i dettagli nella recensione completa
Corsair Vanguard Air 99 Wireless: non si era mai vista una tastiera gaming così professionale
Corsair Vanguard Air 99 Wireless: non si era mai vista una tastiera gaming così professionale
Nelle ultime settimane abbiamo provato la Corsair Vanguard Air 99 Wireless, una tastiera tecnicamente da gaming, ma che in realtà offre un ampio ventaglio di possibilità anche al di fuori delle sessioni di gioco. Flessibilità e funzionalità sono le parole d'ordine di una periferica che si rivolge a chi cerca un prodotto capace di adattarsi a ogni esigenza e ogni piattaforma
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 28-01-2009, 23:31   #1
na-kun
Junior Member
 
Iscritto dal: Jan 2009
Messaggi: 8
[C] feof() nella guardia del while!

Allora... Io per un progetto devo creare una rubrica tramite l'uso delle Hash Table... tutto perfetto, se non per un piccolo problema...

ho gestito tutti gli errori ed il programma è a prova di niubbo ma che niubbo non si può!! ora spiego meglio:

la rubrica deve appoggiarsi ad un file, prelevare le informazioni dal file e, dare l'opportunità all'utente di, salvarle sempre sul file... bene ok... ora il punto è che devo prelevare i dati dal file ed inserirli nella Hash Table (costruita come array di strutture record)... e per fare questo ho usato un while e nella guardia ho usato la condizione !feof(file)

ora il punto qual'è... il punto è che se il file è completamente vuoto, allora mi viene restituito un errore nella funzione substring(char *, int) che è quella funzione che mi permette di estrapolare, riga per riga, i dati dal file... questo significa che il ciclo while viene eseguito almeno una volta!

ma io mi chiedo... com'è possibile che il ciclo venga eseguito comunque almeno una volta?! come posso ovviare a questo problema? davvero, ho il progetto pronto, la relazione idem...programma a prova di utente alla "Mr. Been" eppure non posso presentare il progetto solo perché se il file è vuoto, restituisce un errore nella funziona substring(char *, int), come è giusto che sia, perché il file è vuoto!

vi ringrazio per eventuali suggerimenti... non so dove sbatterci la testa...

Questo è il codice della funzione t_build() che ha il compito di prelevare i dati da file ed inserire in hash table...
Codice:
void t_build()
{
	char temp[(MAX_LENGTH * 2) + 1];
	char *name, *email;
	unsigned int entry, collision = 0;

	while(!feof(file))
	{
		// leggo una riga dal file
        fgets(temp, (MAX_LENGTH * 2) + 1, file);

		// estrapolo le informazioni dalla riga letta e le assegno a name ed email
		name = substring(temp, -1);
		email = substring(temp, (strlen(substring(temp, -1)) + 1));

		/* popolo la tabella:
		   Fase 1) calcolo l'entry */
		entry = linear(hashing(name), 0, name);

		if(entry != hashing(name))
		{
			collision = 1;
		} else collision = 0;

		/* Fase 2) popolo fisicamente, con name ed email, il record ad indice entry
		   nella hash table */
		ht[entry].key = name;
		ht[entry].value = email;
		ht[entry].collision = collision;
		count = counter(count, 0);
	}
	
	ht[entry].key = NULL;
	ht[entry].value = NULL;
	ht[entry].collision = 0;
	count = counter(count, 1);
}
na-kun è offline   Rispondi citando il messaggio o parte di esso
Old 29-01-2009, 01:09   #2
apocalypsestorm
Bannato
 
Iscritto dal: Nov 2008
Messaggi: 85
sicuro di aver aperto correttamente il file ?
bisognerebbe prima controllare il valore della variabile "file==NULL"
http://www.cplusplus.com/reference/c...tdio/feof.html
apocalypsestorm è offline   Rispondi citando il messaggio o parte di esso
Old 29-01-2009, 12:38   #3
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
Io faccio sempre così:

Codice:
while(1)
	{
		// leggo una riga dal file
        fgets(temp, (MAX_LENGTH * 2) + 1, file);
        if(!feof(file)
             break;      

		// estrapolo le informazioni dalla riga letta e le assegno a name ed email
		name = substring(temp, -1);
		email = substring(temp, (strlen(substring(temp, -1)) + 1));

		/* popolo la tabella:
		   Fase 1) calcolo l'entry */
		entry = linear(hashing(name), 0, name);

		if(entry != hashing(name))
		{
			collision = 1;
		} else collision = 0;

		/* Fase 2) popolo fisicamente, con name ed email, il record ad indice entry
		   nella hash table */
		ht[entry].key = name;
		ht[entry].value = email;
		ht[entry].collision = collision;
		count = counter(count, 0);
	}
Oppure in questo caso, visto che fai una sola lettura:
Codice:
while(fgets(temp, (MAX_LENGTH * 2) + 1, file)
{
  ...
}
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 29-01-2009, 14:10   #4
na-kun
Junior Member
 
Iscritto dal: Jan 2009
Messaggi: 8
@ apocalypsestorm allora la rubrica funziona perfettamente... cioè il file lo apre bene... l'unica pecca della rubrica (che mi allontana da una possibile lode) è proprio il fatto che se il file è vuoto, allora mi dà Access Violation (nulla da dire, se il file viene iterato cmq... per come è definita substring(char *, int)... il problema è che non dovrebbe essere iterato in quel caso dato che da quel che ho capito !feof(FILE *) dovrebbe uscire dal ciclo nel momento in cui il puntatore all'interno del file è NULL)...

l'unico problema è quello... certo, l'alternativa è presentare la rubrica con almeno un contatto... ma è poco elegante... XD


@ cionci ora provo a vedere e ti so dire... perché non so dove sbatterci la testa...
na-kun è offline   Rispondi citando il messaggio o parte di esso
Old 29-01-2009, 14:26   #5
na-kun
Junior Member
 
Iscritto dal: Jan 2009
Messaggi: 8
Quote:
Originariamente inviato da cionci Guarda i messaggi
Io faccio sempre così:

Codice:
while(1)
	{
		// leggo una riga dal file
        fgets(temp, (MAX_LENGTH * 2) + 1, file);
        if(!feof(file)
             break;      

		// estrapolo le informazioni dalla riga letta e le assegno a name ed email
		name = substring(temp, -1);
		email = substring(temp, (strlen(substring(temp, -1)) + 1));

		/* popolo la tabella:
		   Fase 1) calcolo l'entry */
		entry = linear(hashing(name), 0, name);

		if(entry != hashing(name))
		{
			collision = 1;
		} else collision = 0;

		/* Fase 2) popolo fisicamente, con name ed email, il record ad indice entry
		   nella hash table */
		ht[entry].key = name;
		ht[entry].value = email;
		ht[entry].collision = collision;
		count = counter(count, 0);
	}
Oppure in questo caso, visto che fai una sola lettura:
Codice:
while(fgets(temp, (MAX_LENGTH * 2) + 1, file)
{
  ...
}
Il secondo mi ha illuminato... non pensavo fosse possibile inserire la funzione fgets(char *, int, FILE *) nella guardia del while... XD funziona perfettamente... inoltre mi hai risolto anche un'altro problema (che si notava dal codice da me proposto... ovvero che l'ultimo contatto nel file veniva inserito due volte... problema che avevo risolto, cancellando l'ultimo contatto inserito in rubrica (in quanto doppione del penultimo)... è come se mi leggeva due volte l'ultima riga!! in questo modo si è risolto anche quel problema...

grazie mille!!!! davvero molto gentile...

dite che 638 righe di codice, per una rubrica, siano troppe?! XD (preciso che la metà delle righe sono commenti, mentre la metà del codice (tolti i commenti) sono tutte le gestioni degli errori... non avrei mai immaginato che un utente niubbo potesse fare così tanti danni, se non gestiti XD)
na-kun è offline   Rispondi citando il messaggio o parte di esso
Old 29-01-2009, 14:57   #6
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
Fammi vedere qualche riga della gestione degli errori.
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 29-01-2009, 18:14   #7
na-kun
Junior Member
 
Iscritto dal: Jan 2009
Messaggi: 8
Quote:
Originariamente inviato da cionci Guarda i messaggi
Fammi vedere qualche riga della gestione degli errori.
Ricerca di un elemento... record ht[DIM_TABLE]; è la mia tabella di hash... ovviamente, gli elementi possono avere un entry compreso fra 0 e 42... quindi nel caso in cui l'entry è settato su DIM_TABLE significa che non è un indice valido: errore = contatto non trovato.

Codice:
//#define DIM_TABLE 43

entry = t_search(name); // t_search(char *) è unsigned int

if(entry == DIM_TABLE)
{ // gestiamo la situazione in cui il contatto cercato non è in rubrica
     system(CLEAN);
     printf("\n ATTENZIONE! Il contatto cercato non è stato trovato.");
     printf("\n\n Premere INVIO per tornare al menu iniziale... ");
}

else
{ /* altrimenti possiamo procedere allo stampo in stdout dell'email
				 del contatto cercato */
     printf("\n Indirizzo e-mail:");
     printf("\n >> %s", ht[entry].value);
     printf("\n\n Premere INVIO per tornare al menu iniziale... ");
}
Aggiunta di un nuovo elemento... per come sono definite le tabelle di hash, non è possibile aggiungere chiavi identiche (altrimenti nella ricerca, verrebbe trovata solo la prima che c'è nel cluster)... quindi devo impedire che l'utente inserisca due volte la stessa chiave... quindi se t_search(char *) dà un entry valido, allora significa che l'elemento è già stato trovato dentro la tabella di hash e dunque non è possibile aggiungerlo... alternativamente, se count = DIM_TABLE (count è un contatore a livello globale che tiene il conto di quanti spazi sono stati occupati in tabella) allora significa che lo spazio è esaurito...

Codice:
entry = t_search(name);

if(entry != DIM_TABLE)
{ /* gestiamo la situazione in cui un contatto con lo stesso nome sia
          già presente in rubrica */
     system(CLEAN);
     printf("\n ATTENZIONE! Nome già esistente.");
     printf("\n Cancellarlo e ripetere l'operazione.");
     printf("\n\n Premere INVIO per tornare al menu iniziale... ");
     while(getchar() != '\n');
}

else if(count == DIM_TABLE)
{ /* gestiamo la situazione in cui la tabella è piena e non permette
              nuovi inserimenti */
     system(CLEAN);
     printf("\n ATTENZIONE! Spazio in rubrica esaurito.");
     printf("\n Cancellare un contatto per fare un ulteriore inserimento.");
     printf("\n\n Premere INVIO per tornare al menu iniziale... ");
     while(getchar() != '\n');
}
quelli sono i più semplici ed intuitivi... però c'è anche tutta la gestione di eventuali violazioni in memoria nella funzione di hash come ad esempio:

Codice:
/*
con j settato su DIM_TABLE;
streq(char *, char *); una mia funzione per confrontare che due stringhe siano esattamente uguali!
*/

while(ht[entry].key != NULL && streq(ht[entry].key, key) && j-- > -1)
{ // ht[entry].key != NULL è necessario per evitare violazioni di memoria
     entry = (entry + 1) % DIM_TABLE;
}

if(j < 0 || ht[entry].key == NULL)
{ 
     entry = DIM_TABLE;
}

Poi ho limitato l'utente a non inserire il '-' (trattino) come carattere... dato che nel file i contatti sono scritti in questo formato:
nome 1-email@1
nome 2-email@2
...
nome n-email@n

quindi per prelevare l'email, devo prendere tutto il contenuto fra il '-' (trattino) ed il '\n' (newline)... quindi per ovvie ragioni ho dovuto impedire all'utente che metta il trattino... ed ho messo un controllo sul nome, che controlla se ci sono evenutali '-' (trattini) ed in tal caso li sostituisco con ' ' (spazi)... questo vale sia in inserimento che in ricerca, così ' ' e '-' sono considerati sempre come ' '... poi, appena consegno la rubrica, magari vi fo vedere il progetto in tutte e le sue 658 (ho ottimizzato alcune cose, quindi son aumentate) righe di codice!

Ultima modifica di na-kun : 29-01-2009 alle 18:21.
na-kun è offline   Rispondi citando il messaggio o parte di esso
Old 29-01-2009, 18:23   #8
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
Puoi gestire tutto tramite una funzione:

Codice:
void print_error(char * what, char * solution) 
{
     system(CLEAN);
     printf("\n ATTENZIONE! %s", what);
     printf("\n %s.", solution);
     printf("\n\n Premere INVIO per tornare al menu iniziale... ");
     while(getchar() != '\n');
}
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 29-01-2009, 18:31   #9
na-kun
Junior Member
 
Iscritto dal: Jan 2009
Messaggi: 8
Quote:
Originariamente inviato da cionci Guarda i messaggi
Puoi gestire tutto tramite una funzione:

Codice:
void print_error(char * what, char * solution) 
{
     system(CLEAN);
     printf("\n ATTENZIONE! %s", what);
     printf("\n %s.", solution);
     printf("\n\n Premere INVIO per tornare al menu iniziale... ");
     while(getchar() != '\n');
}
ci avevo seriamente pensato.... ma, per rendere il codice leggibile, dovrei istanziare in memoria una nuova variabile char *solution nell'header() (funzione contenente il menu iniziale) che memorizza una stringa a seconda del problema riscontrato...

e sebbene di poco, questo va a pesare in memoria... se posso evitare di usare troppe variabili è meglio... effettivamente stavo pensando di togliere la variabile entry ed usare al suo posto la variabile ch (che memorizza la scelta nel menu iniziale) entrambe sono unsigned int... tanto usata una volta, non serve più, fino a quando non si ritorna al menu iniziale...
na-kun è offline   Rispondi citando il messaggio o parte di esso
Old 29-01-2009, 18:36   #10
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
Hai problemi di memoria ???
Comunque non capisco perché ti devi complicare la vita memorizzandoti l'errore.
Codice:
entry = t_search(name);

if(entry != DIM_TABLE)
{ 
    print_error("Nome già esistente", "Cancellarlo e ripetere l'operazione");
}
else if(count == DIM_TABLE)
{
     print_error("Spazio in rubrica esaurito", "Cancellare un contatto per fare un ulteriore inserimento");
}

Ultima modifica di cionci : 29-01-2009 alle 18:39.
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 29-01-2009, 18:40   #11
na-kun
Junior Member
 
Iscritto dal: Jan 2009
Messaggi: 8
Quote:
Originariamente inviato da cionci Guarda i messaggi
Hai problemi di memoria ???
Comunque non capisco perché ti devi complicare la vita memorizzandoti l'errore.

entry = t_search(name);

if(entry != DIM_TABLE)
{
print_error("Nome già esistente", "Cancellarlo e ripetere l'operazione");
}
else if(count == DIM_TABLE)
{
print_error("Spazio in rubrica esaurito", "Cancellare un contatto per fare un ulteriore inserimento");

}
beh se passo tutto ad un'altra funzione, mi conviene memorizzare la stringa così da compattare il tutto... altrimenti mi conviene lasciare così... cmq ci stavo seriamente pensando anche io... vorrei prima parlare con la docente e vedere il suo punto di vista e quanto ci tiene alla massima ottimizzazione della memoria... e poi scelgo il da farsi... attualmente la rubrica è finita... mancano solo le ultime ottimizzazioni come questa e poche altre (tipo suddividere meglio le funzioni e renderle più leggibili staccando le righe di codice)!
na-kun è offline   Rispondi citando il messaggio o parte di esso
Old 29-01-2009, 18:48   #12
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
Imho non ha senso pensare all'ottimizzazione della memoria, ma questo per un'altra questione. Mi è parso di capire che stai facendo un qualche algoritmo di hashing. La gestione degli errori devi farla esterna....mi spiego, io, utilizzatore della tua libreria che fa l'hashing non mi posso permettere che tu mi stampi qualcosa sullo standard output.
Quindi la gestione e stampa degli errori la devi fare dall'esterno.
Ad esempio ritornando un un intero con il tipo dell'errore e/o settando una variabile statica con l'ultimo errore avvenuto.
Sarà l'utente che si dovrà occupare, in caso di errore, di passare una stringa ad un funzione della libreria che verrà riempita con il testo dell'errore.
Una libreria non si dovrà mai occupare di gestire los tandard input e lo standard output.

Se questa gestione degli errori è al di fuori della libreria, allora non ti dovrai preoccupare di risparmiare la memoria.

Ultima modifica di cionci : 29-01-2009 alle 18:56.
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 29-01-2009, 19:08   #13
na-kun
Junior Member
 
Iscritto dal: Jan 2009
Messaggi: 8
Quote:
Originariamente inviato da cionci Guarda i messaggi
Imho non ha senso pensare all'ottimizzazione della memoria, ma questo per un'altra questione. Mi è parso di capire che stai facendo un qualche algoritmo di hashing. La gestione degli errori devi farla esterna....mi spiego, io, utilizzatore della tua libreria che fa l'hashing non mi posso permettere che tu mi stampi qualcosa sullo standard output.
Quindi la gestione e stampa degli errori la devi fare dall'esterno.
Ad esempio ritornando un un intero con il tipo dell'errore e/o settando una variabile statica con l'ultimo errore avvenuto.
Sarà l'utente che si dovrà occupare, in caso di errore, di passare una stringa ad un funzione della libreria che verrà riempita con il testo dell'errore.
Una libreria non si dovrà mai occupare di gestire los tandard input e lo standard output.

Se questa gestione degli errori è al di fuori della libreria, allora non ti dovrai preoccupare di risparmiare la memoria.

ah no forse non hai capito XD... la libreria di hash è pulita... restituisce solo valori (validi in caso che l'algoritmo abbia successo... DIM_TABLE (non valido) se l'algoritmo ha avanzato un errore che dovrà essere gestito)

come venga gestito, dipende da chi usa la libreria... infatti la gestione degli errori (a parte la gestione del caso in cui in lettura/scrittura si incontri una key NULL (nella guardia del while)) il resto è tutta fatta fuori dalla libreria hash.h... ma nel file rubrica.c dove effettivamente implemento le operazioni nella rubrica... in hash.h solo ho creato la hash table e la funzione di hash e la gestione delle collisioni con il linear probing...

l'ottimizzazione che stavo pensando (e che pensavo intendessi anche te) è a livello di progettazione software non di libreria hash.h...
na-kun è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


PC Specialist Lafité 14 AI AMD: assemblato come vuoi tu PC Specialist Lafité 14 AI AMD: assemblat...
Recensione Nothing Phone 4(a): sempre iconico ma ora più concreto Recensione Nothing Phone 4(a): sempre iconico ma...
Corsair Vanguard Air 99 Wireless: non si era mai vista una tastiera gaming così professionale Corsair Vanguard Air 99 Wireless: non si era mai...
Ecovacs DEEBOT T90 PRO OMNI: ora il rullo di lavaggio è ampio Ecovacs DEEBOT T90 PRO OMNI: ora il rullo di lav...
Recensione Samsung Galaxy S26 Ultra: finalmente qualcosa di nuovo Recensione Samsung Galaxy S26 Ultra: finalmente ...
Riceve il reso di una RTX 5090 da 4.000 ...
Gli utenti con GPU Intel non possono gio...
Un agente AI visita 5.000 siti dove un u...
IA, virtualizzazione e cyber resilienza:...
AMD aggiorna FSR alla versione 4.1. Migl...
Nuovi suffissi internet 2026: per la sec...
Claudy Day: tre vulnerabilità in ...
Record di efficienza per i pannelli sola...
SteamOS 3.8 è disponibile in ante...
Opel in Formula E dalla Stagione 13: con...
Windows 11 26H1: ecco le scadenze esatte...
Arriva HiSecEngine USG6000G, la nuova ga...
Xiaomi SU7 2026 ufficiale con 902 km di ...
Il tuo vecchio iPhone potrebbe essere gi...
Già disponibile un primo aggiorna...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 23:21.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v