Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - Menu rapido con quantita' di voci variabile
Forum - C/C++ - Menu rapido con quantita' di voci variabile

Avatar
AldoBaldo (Member)
Guru


Messaggi: 699
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 22:22
Sabato, 19/12/2020
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++

  1. #include <stdio.h>
  2. #include "menu_va.h"
  3.  
  4. int main() {
  5.     int scelta;
  6.  
  7.     scelta = menu_va( "PRIMO MENU DI PROVA", 4,
  8.                       "Uscita",
  9.                       "Voce 1",
  10.                       "Voce 2",
  11.                       "Voce 3" );
  12.  
  13.     printf( " Hai scelto %d\n", scelta );
  14.  
  15.     scelta = menu_va( "SECONDO MENU DI PROVA", 3,
  16.                       "Uscita",
  17.                       "Prima voce",
  18.                       "Seconda voce" );
  19.  
  20.     printf( " Hai scelto %d\n\n", scelta );
  21.  
  22.     return 0;
  23. }



menu_va.h

Codice sorgente - presumibilmente C/C++

  1. /*==============================================================================
  2.                                     MENU_VA
  3.                             v1.0 - 19 dicembre 2020
  4.  
  5. DESCRIZIONE
  6.  
  7. Mostra nella console del C un menu' costituito da un titolo (opzionale) seguito
  8. da una riga separatrice e da una serie di altre voci numerate. Si occupa quindi
  9. di assicurare la restituzione di un valore coerente con le caratteristiche del
  10. menu', insistendo nella richiesta di una nuova scelta finche' non si sceglie una
  11. voce di menu' esistente. Ad esempio...
  12.  
  13.   int scelta = menu_va("MENU DI PROVA",4,"Uscita","Voce 1","Voce 2","Voce 3");
  14.  
  15. La chiamata appena riportata da' come risultato questo menu':
  16.  
  17.     MENU DI PROVA               |
  18.   =================             |
  19.     1. Voce 1                   | Un menu' di questo tipo, restituisce sempre
  20.     2. Voce 2                   | un valore compreso tra 0 e 3, a meno che siano
  21.     3. Voce 3                   | stati mal formattati i parametri.
  22.     0. Uscita                   |
  23.   Scegli una voce dal menu:     |
  24.  
  25. ==========
  26.  
  27. PARAMETRI di menu_va()
  28.  
  29. const char *titolo  Una stringa C che viene usata come titolo del menu'.
  30.                     Dopo il titolo, viene tracciata una riga separatrice
  31.                     costituita da una serie di caratteri '='.
  32.                     Se questo parametro e' NULL, il menu' viene presentato senza
  33.                     un titolo, e la riga separatrice non viene tracciata.
  34.  
  35. int qVoci           Un valore intero >=1 che indica la quantita' delle voci
  36.                     complessivamente presenti nel menu' (inclusa quella di
  37.                     uscita).
  38.  
  39. const char* ...     Una serie di puntatori a stringhe C, in quantita' pari al
  40.                     valore indicato in qVoci.
  41.                     La prima stringa viene usata come etichetta per la voce di
  42.                     uscita dal menu', e collocata in coda al menu' stesso,
  43.                     numerandola con 0.
  44.                     Ciascuna delle stringhe successive viene usata come
  45.                     etichetta delle altre voci, numerandole a partire da 1,
  46.                     secondo il loro ordine di successione tra i parametri.
  47.                     Nessuno dei puntatori puo' essere NULL.
  48.  
  49. VALORE DI RITORNO
  50.  
  51. int                 Un valore numerico intero che e' 0 se e' stata scelta la
  52.                     voce riservata all'uscita, maggiore di 0 se e' stata scelta
  53.                     un'altra voce, sempre compresa entro quelle definite tramite
  54.                     il secondo parametro e quelli successivi.
  55.                     Il valore di errore -1 viene restituito solo se il secondo
  56.                     parametro e' <1 o anche uno solo tra i parametri successivi
  57.                     e' NULL.
  58.  
  59. ==============================================================================*/
  60.  
  61. #ifndef MENU_VA_H_INCLUDED
  62. #define MENU_VA_H_INCLUDED
  63.  
  64. #ifdef __cplusplus
  65. extern "C" {
  66. #endif
  67.  
  68. int menu_va( const char *titolo, int qVoci, ... );
  69.  
  70. #ifdef __cplusplus
  71. }
  72. #endif
  73.  
  74. #endif // MENU_VA_H_INCLUDED



menu_va.c

Codice sorgente - presumibilmente C++

  1. #include "menu_va.h"
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <ctype.h>
  7. #include <stdarg.h>
  8.  
  9. int menu_va( const char *titolo, int qVoci, ... ) {
  10.     const char *aux, *pUscita, *pVoce;
  11.     int i, l, scelta = -1;
  12.     va_list va;
  13.  
  14.     if( qVoci>0 ) {
  15.         if( titolo ) {
  16.             int lRigaSep = 0; // la lunghezza della riga separatrice
  17.  
  18.             va_start( va, qVoci );
  19.  
  20.             // ricava un'ipotesi di lunghezza
  21.             // della riga separatrice del titolo
  22.             for( i=0; i<qVoci; ++i ) {
  23.                 pVoce = va_arg( va, const char* );
  24.                 if( !pVoce ) { va_end(va); return scelta; }
  25.  
  26.                 l = strlen( pVoce );
  27.                 lRigaSep = l>lRigaSep ? l : lRigaSep;
  28.             }
  29.  
  30.             va_end( va );
  31.  
  32.             lRigaSep += 7; // aggiunge lo spazio per i numeri ecc.
  33.  
  34.             // visualizza il titolo
  35.             for( l=0; titolo[l]!='\0'; ++l );
  36.             lRigaSep = l+4>lRigaSep ? l+4 : lRigaSep;
  37.             printf( "\n   %s\n ", titolo );
  38.             for( i=0; i<lRigaSep; ++i ) printf( "=" ); // riga separatrice
  39.         }
  40.  
  41.         va_start( va, qVoci );
  42.  
  43.         // memorizza l'etichetta della voce di uscita
  44.         pUscita = va_arg( va, const char* );
  45.         if( !pUscita ) { va_end(va); return scelta; }
  46.  
  47.         // visualizza tutte le voci (TRANNE, quella d'uscita)
  48.         for( i=1; i<qVoci; ++i ) {
  49.             pVoce = va_arg( va, const char* );
  50.             if( !pVoce ) { va_end(va); return scelta; }
  51.             printf( "\n  %2d. %s", i, pVoce );
  52.         }
  53.  
  54.         va_end( va );
  55.  
  56.         // ORA visualizza l'opzione di uscita (sempre in fondo)
  57.         printf( "\n  %2d. %s\n\n", 0, pUscita );
  58.  
  59.         printf( " Scegli una voce dal menu: " );
  60.  
  61.         // il ciclo che segue insiste nel chiedere di
  62.         // scegliere una voce del menu, fino a quando
  63.         // non viene effettuata una scelta valida
  64.  
  65.         while( scelta<0 || scelta>=qVoci ) {
  66.             char buff[8];
  67.  
  68.             if( fgets(buff,8,stdin) && (l=strlen(buff))>0 ) {
  69.                 int numero_valido = 0;
  70.  
  71.                 if( buff[l-1] != '\n' ) {
  72.                     while( '\n' != getchar() ); // "svuota" stdin
  73.                     printf( " Troppi caratteri, riprova: " );
  74.                     continue;
  75.                 } else buff[--l] = '\0'; // elimina il new line a fine riga
  76.  
  77.                 if( '\0'!=*buff ) { // controlla che buff contenga un numero
  78.                     for( numero_valido=1, aux=buff; 0!=*aux; ++aux )
  79.                         if( !isdigit(*aux) ) { numero_valido = 0; break; }
  80.  
  81.                     if( !numero_valido ) {
  82.                         printf( " Caratteri non validi, riprova: " );
  83.                         continue;
  84.                     }
  85.                 }
  86.  
  87.                 scelta = atoi( buff );
  88.  
  89.                 if( scelta>=0 && scelta<qVoci )
  90.                     break;
  91.                 else printf( " Scelta non valida, riprova: " );
  92.             }
  93.         }
  94.  
  95.         puts("");
  96.     }
  97.  
  98.     return scelta;
  99. }



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