AldoBaldo (Member)
Guru
Messaggi: 699
Iscritto: 08/01/2015
|
Questa sera mi andava di buttare giù un po' di codice. Ecco quindi che m'è venuta quest'idea di una singola funzione che generi nella console del C un menù con una quantità libera di voci numerate, senza fare tante storie e assicurando che, con una sola chiamata, in uscita venga SEMPRE restituita una scelta valida (-1 in caso di errori, che possono essere evitati semplicemente stando attenti a passare parametri validi). Ve la propongo...
main.c
Codice sorgente - presumibilmente C++ |
#include <stdio.h> #include "menu_va.h" int main() { int scelta; scelta = menu_va( "PRIMO MENU DI PROVA", 4, "Uscita", "Voce 1", "Voce 2", "Voce 3" ); printf( " Hai scelto %d\n", scelta ); scelta = menu_va( "SECONDO MENU DI PROVA", 3, "Uscita", "Prima voce", "Seconda voce" ); printf( " Hai scelto %d\n\n", scelta ); return 0; }
|
menu_va.h
Codice sorgente - presumibilmente C/C++ |
/*==============================================================================
MENU_VA
v1.0 - 19 dicembre 2020
DESCRIZIONE
Mostra nella console del C un menu' costituito da un titolo (opzionale) seguito
da una riga separatrice e da una serie di altre voci numerate. Si occupa quindi
di assicurare la restituzione di un valore coerente con le caratteristiche del
menu', insistendo nella richiesta di una nuova scelta finche' non si sceglie una
voce di menu' esistente. Ad esempio...
int scelta = menu_va("MENU DI PROVA",4,"Uscita","Voce 1","Voce 2","Voce 3");
La chiamata appena riportata da' come risultato questo menu':
MENU DI PROVA |
================= |
1. Voce 1 | Un menu' di questo tipo, restituisce sempre
2. Voce 2 | un valore compreso tra 0 e 3, a meno che siano
3. Voce 3 | stati mal formattati i parametri.
0. Uscita |
Scegli una voce dal menu: |
==========
PARAMETRI di menu_va()
const char *titolo Una stringa C che viene usata come titolo del menu'.
Dopo il titolo, viene tracciata una riga separatrice
costituita da una serie di caratteri '='.
Se questo parametro e' NULL, il menu' viene presentato senza
un titolo, e la riga separatrice non viene tracciata.
int qVoci Un valore intero >=1 che indica la quantita' delle voci
complessivamente presenti nel menu' (inclusa quella di
uscita).
const char* ... Una serie di puntatori a stringhe C, in quantita' pari al
valore indicato in qVoci.
La prima stringa viene usata come etichetta per la voce di
uscita dal menu', e collocata in coda al menu' stesso,
numerandola con 0.
Ciascuna delle stringhe successive viene usata come
etichetta delle altre voci, numerandole a partire da 1,
secondo il loro ordine di successione tra i parametri.
Nessuno dei puntatori puo' essere NULL.
VALORE DI RITORNO
int Un valore numerico intero che e' 0 se e' stata scelta la
voce riservata all'uscita, maggiore di 0 se e' stata scelta
un'altra voce, sempre compresa entro quelle definite tramite
il secondo parametro e quelli successivi.
Il valore di errore -1 viene restituito solo se il secondo
parametro e' <1 o anche uno solo tra i parametri successivi
e' NULL.
==============================================================================*/
#ifndef MENU_VA_H_INCLUDED
#define MENU_VA_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
int menu_va( const char *titolo, int qVoci, ... );
#ifdef __cplusplus
}
#endif
#endif // MENU_VA_H_INCLUDED
|
menu_va.c
Codice sorgente - presumibilmente C++ |
#include "menu_va.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <stdarg.h> int menu_va( const char *titolo, int qVoci, ... ) { const char *aux, *pUscita, *pVoce; int i, l, scelta = -1; va_list va; if( qVoci>0 ) { if( titolo ) { int lRigaSep = 0; // la lunghezza della riga separatrice va_start( va, qVoci ); // ricava un'ipotesi di lunghezza // della riga separatrice del titolo for( i=0; i<qVoci; ++i ) { pVoce = va_arg( va, const char* ); if( !pVoce ) { va_end(va); return scelta; } l = strlen( pVoce ); lRigaSep = l>lRigaSep ? l : lRigaSep; } va_end( va ); lRigaSep += 7; // aggiunge lo spazio per i numeri ecc. // visualizza il titolo for( l=0; titolo[l]!='\0'; ++l ); lRigaSep = l+4>lRigaSep ? l+4 : lRigaSep; printf( "\n %s\n ", titolo ); for( i=0; i<lRigaSep; ++i ) printf( "=" ); // riga separatrice } va_start( va, qVoci ); // memorizza l'etichetta della voce di uscita pUscita = va_arg( va, const char* ); if( !pUscita ) { va_end(va); return scelta; } // visualizza tutte le voci (TRANNE, quella d'uscita) for( i=1; i<qVoci; ++i ) { pVoce = va_arg( va, const char* ); if( !pVoce ) { va_end(va); return scelta; } printf( "\n %2d. %s", i, pVoce ); } va_end( va ); // ORA visualizza l'opzione di uscita (sempre in fondo) printf( "\n %2d. %s\n\n", 0, pUscita ); printf( " Scegli una voce dal menu: " ); // il ciclo che segue insiste nel chiedere di // scegliere una voce del menu, fino a quando // non viene effettuata una scelta valida while( scelta<0 || scelta>=qVoci ) { char buff[8]; if( fgets(buff,8,stdin) && (l=strlen(buff))>0 ) { int numero_valido = 0; if( buff[l-1] != '\n' ) { while( '\n' != getchar() ); // "svuota" stdin printf( " Troppi caratteri, riprova: " ); continue; } else buff[--l] = '\0'; // elimina il new line a fine riga if( '\0'!=*buff ) { // controlla che buff contenga un numero for( numero_valido=1, aux=buff; 0!=*aux; ++aux ) if( !isdigit(*aux) ) { numero_valido = 0; break; } if( !numero_valido ) { printf( " Caratteri non validi, riprova: " ); continue; } } scelta = atoi( buff ); if( scelta>=0 && scelta<qVoci ) break; else printf( " Scelta non valida, riprova: " ); } } puts(""); } return scelta; }
|
ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti. |