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
Libreria STRCONS - stringa_console.c

stringa_console.c

Caricato da: AldoBaldo
Scarica il programma completo

  1. /// =========================== LIBRERIA STRCONS =========================== ///
  2. ///                            di Aldo Carpanelli                            ///
  3. ///                          v1.1,  13/11-6/12 2016                          ///
  4. /// ======================================================================== ///
  5.  
  6.  
  7. #include "stringa_console.h"
  8.  
  9.  
  10. /// ===> variabili statiche <=============================================== ///
  11.  
  12. static char *STRCONS_buffer = NULL;
  13. static size_t STRCONS_capacita = 0;
  14. static size_t STRCONS_lunghezza = 0;
  15.  
  16.  
  17. /// ===> gestione degli errori <============================================ ///
  18.  
  19. // Una stringa descrittiva per ciascuno dei
  20. // codici d'errore enumerati in stringa_console.h
  21. const char *STRCONSErr_d[STRCONSErr_MaxIndStrErr] = {
  22.     "l'input e' una stringa vuota",
  23.     "buffer insufficiente, input troncato",
  24.     "nessun errore",
  25.     "memoria non allocata",
  26.     "e' stato richiesto un buffer di 4GB o piu'",
  27.     "errore in fgets()",
  28.     "la stringa non rappresenta un numero"
  29. };
  30.  
  31. const char *STRCONSErr_Descrizione( int codice ) {
  32.     if( codice >= STRCONSErr_no_str &&
  33.         codice < STRCONSErr_MaxIndStrErr )
  34.         return STRCONSErr_d[codice+2];
  35.     else return "errore non previsto";
  36. }
  37.  
  38.  
  39. /// ===> inizializzazione e dismissione <=================================== ///
  40.  
  41. /*==============================================================================
  42. Inizializza la libreria, allocando un buffer che puo' contenere un massimo di
  43. dim caratteri (il buffer finisce quindi per avere dimensioni pari a dim+1
  44. bytes). Al momento dell'allocazione, il buffer contiene una serie di '\0'.
  45. La libreria viene inizializzata in modo che il buffer abbia una dimensione
  46. minima di 31 caratteri.
  47. Qualora l'allocazione della memoria necessaria non fosse possibile,
  48. l'inizializzazione fallirebbe e verrebbe restituito un codice di errore.
  49. ==============================================================================*/
  50.  
  51. int STRCONS_Inizializza( size_t dim ) {
  52.     dim = dim>1 ? dim : 2;
  53.     return STRCONS_Dimensiona( dim );
  54. }
  55.  
  56. /*==============================================================================
  57. Si occupa di liberare la memoria allocata per il buffer abbinato alla libreria.
  58. ==============================================================================*/
  59.  
  60. void STRCONS_Dismetti( void ) {
  61.     if( STRCONS_buffer ) {
  62.         free( STRCONS_buffer );
  63.         STRCONS_buffer = NULL;
  64.     }
  65.  
  66.     STRCONS_capacita = STRCONS_lunghezza = 0;
  67. }
  68.  
  69.  
  70. /// ===> modifica dello stato della libreria <============================== ///
  71.  
  72. /*==============================================================================
  73. Cambia le dimensioni del buffer, prevedendo lo spazio per il terminatore '\0'
  74. (dunque, vengono allocati dim+1 byte di memoria).
  75. Se il buffer contiene gia' dei dati, i dati gia' presenti vengono conservati
  76. (nei limiti del possibile).
  77. Se non e' possibile modificare le dimensioni del buffer, il vecchio buffer viene
  78. conservato, cosi' come il suo contenuto.
  79. In caso d'insuccesso restituisce un codice di errore che puo' essere usato per
  80. ricavare informazioni sul tipo di problema riscontrato. Il codice di errore puo'
  81. essere...
  82.  
  83. STRCONSErr_enorme   e' stata richiesta l’allocazione di un buffer dalle
  84.                     dimensioni uguali o superiori a 4GB, il che e' un'assurdita'
  85. STRCONSErr_no_mem   l'allocazione della memoria e' fallita; il buffer non e'
  86.                     stato ridimensionato, ma il suo contenuto originale e'
  87.                     rimasto intatto
  88. STRCONSErr_no_err       tutto bene, il buffer e' stato ridimensionato e le parti
  89.                     conservabili del suo contenuto sono state conservate
  90. ==============================================================================*/
  91.  
  92. int STRCONS_Dimensiona( size_t dim ) {
  93.     if( dim >= 0xFFFFFFFF ) return STRCONSErr_enorme; // buffer insensato (2)
  94.  
  95.     dim = dim>1 ? dim : 2;
  96.  
  97.     char *tmp = (char*) calloc( dim+1, sizeof(char) );
  98.     if( tmp == NULL ) return STRCONSErr_no_mem; // memoria insufficiente (1)
  99.  
  100.     size_t i, usati = dim<STRCONS_lunghezza ? dim : STRCONS_lunghezza;
  101.  
  102.     if( STRCONS_buffer != NULL ) {
  103.         for( i=0; i<usati; ++i )
  104.             tmp[i] = STRCONS_buffer[i];
  105.         free( STRCONS_buffer );
  106.     }
  107.  
  108.     STRCONS_buffer    = tmp;
  109.     STRCONS_capacita  = dim;
  110.     STRCONS_lunghezza = usati;
  111.  
  112.     return STRCONSErr_no_err; // tutto bene (0)
  113. }
  114.  
  115. /*==============================================================================
  116. Chiede tramite console di inserire un testo. Il testo viene letto fino a un
  117. massimo di caratteri corrispondenti all'attuale capacita' massima del buffer
  118. (impostata tramite STRCONS_Inizializza() oppure STRCONS_Dimensiona()).
  119. Al termine dell'immissione svuota gli eventuali caratteri "pendenti" nello
  120. stdin, "consumandoli" per mezzo di ripetute chiamate a fgets() con un buffer
  121. ausiliario di 2 byte.
  122. In caso d'insuccesso restituisce un codice di errore che puo' essere usato per
  123. ricavare informazioni sul tipo di problema riscontrato. Il codice di errore puo'
  124. essere...
  125.  
  126. STRCONSErr_no_str   l'utente ha premuto invio senza immettere alcun testo; il
  127.                     buffer contiene solo il carattere terminatore (cioe' una
  128.                     stringa vuota e niente piu')
  129. STRCONSErr_troncato la stringa immessa in console e' parzialmente presente nel
  130.                     buffer, terminata da '\0'; la parte eccedente le dimensioni
  131.                     del buffer e' andata persa
  132. STRCONSErr_no_err   tutto bene, la stringa immessa in console e' presente nel
  133.                     buffer (senza il carattere finale '\n'), terminata da '\0'
  134. STRCONSErr_no_fgets c'e' stato un errore non meglio precisato nella chiamata
  135.                     allafunzione standard fgets(); il buffer e' nella sua
  136.                     condizione antecedente alla chiamata al metodo chiedi()
  137. ==============================================================================*/
  138.  
  139. int STRCONS_Chiedi( void ) {
  140.     if( fgets(STRCONS_buffer,STRCONS_capacita+1,stdin) != NULL ) {
  141.         size_t lung = strlen( STRCONS_buffer );
  142.  
  143.         if( STRCONS_buffer[lung-1]=='\n' ) {
  144.             // il buffer contiene tutto l'input
  145.             STRCONS_lunghezza = STRCONS_EliminaNewline( STRCONS_buffer, lung );
  146.  
  147.             if( STRCONS_lunghezza > 0 )
  148.                 return STRCONSErr_no_err; // TUTTO BENE (0)
  149.             else return STRCONSErr_no_str; // stringa vuota (-2)
  150.         }
  151.         else { // il buffer potrebbe contenere solo parte dell'input
  152.             STRCONS_lunghezza = lung;
  153.  
  154.             if( STRCONS_SvuotaStdin() == 0 )
  155.                 // eccedeva solo '\n', l'input c'e' tutto
  156.                 return STRCONSErr_no_err; // TUTTO BENE (0)
  157.             else // buffer insufficiente, input valido ma troncato
  158.                 return STRCONSErr_troncato; // valore negativo (-1)
  159.         }
  160.     }
  161.     else {
  162.         return STRCONSErr_no_fgets;  // errore in fgets() (3)
  163.     }
  164. }
  165.  
  166.  
  167. /// ===> informazioni sullo stato della libreria <========================== ///
  168.  
  169. /*==============================================================================
  170. Fornisce informazioni sulla capacità massima del buffer della libreria (intesa
  171. come numero di caratteri effettivamente ricevibili, escluso dunque il carattere
  172. terminatore della stringa C).
  173. ==============================================================================*/
  174.  
  175. size_t STRCONS_Capacita( void ) {
  176.     return STRCONS_capacita;
  177. }
  178.  
  179. /*==============================================================================
  180. Fornisce informazioni sulla lunghezza della stringa C correntemente contenuta
  181. nel buffer della libreria  (sempre minore o uguale al valore restituito dal
  182. metodo STRCONS _Capacita()).
  183. ==============================================================================*/
  184.  
  185. size_t STRCONS_Lunghezza( void ) {
  186.     return STRCONS_lunghezza;
  187. }
  188.  
  189. /*==============================================================================
  190. Fornisce un puntatore allo spazio di memoria riservato al buffer della libreria,
  191. il che equivale a fornire l'indirizzo della stringa C in esso contenuta e
  192. immessa dall'utente in console.
  193. NOTA: e' essenziale che la memoria abbinata al puntatore restituito da questo
  194. metodo non venga mai liberata direttamente - si usi sempre STRCONS_Dismetti().
  195. ==============================================================================*/
  196.  
  197. char *STRCONS_PStr( void ) {
  198.     return STRCONS_buffer;
  199. }
  200.  
  201. /*==============================================================================
  202. Converte la stringa contenuta nel buffer in un valore numerico, secondo la
  203. notazione indicata tramite il parametro base.
  204. Immette il risultato della conversione all'indirizzo passato come parametro in
  205. l. Restituisce un codice di errore che puo' essere STRCONSErr_no_err (tutto
  206. bene) oppure STRCONSErr_no_num (conversione non effettuata).
  207. ==============================================================================*/
  208.  
  209. int STRCONS_Long( long *l, int base ) {
  210.     char *p = STRCONS_buffer;
  211.     long tmp = strtol( STRCONS_buffer, &p, base );
  212.     if( p != STRCONS_buffer ) *l = tmp;
  213.     return p!=STRCONS_buffer ? STRCONSErr_no_err : STRCONSErr_no_num;
  214. }
  215.  
  216. /*==============================================================================
  217. Converte la stringa contenuta nel buffer in un valore numerico, secondo la
  218. notazione indicata tramite il parametro base.
  219. Immette il risultato della conversione all'indirizzo passato come parametro in
  220. ul. Restituisce un codice di errore che puo' essere STRCONSErr_no_err (tutto
  221. bene) oppure STRCONSErr_no_num (conversione non effettuata).
  222. ==============================================================================*/
  223.  
  224. int STRCONS_UnsignedLong( unsigned long *ul, int base ) {
  225.     char *p = STRCONS_buffer;
  226.     unsigned long tmp = strtoul( STRCONS_buffer, &p, base );
  227.     if( p != STRCONS_buffer ) *ul = tmp;
  228.     return p!=STRCONS_buffer ? STRCONSErr_no_err : STRCONSErr_no_num;
  229. }
  230.  
  231. /*==============================================================================
  232. Converte la stringa contenuta nel buffer in un valore numerico.
  233. Immette il risultato della conversione all'indirizzo passato come parametro in
  234. d. Restituisce un codice di errore che puo' essere STRCONSErr_no_err (tutto
  235. bene) oppure STRCONSErr_no_num (conversione non effettuata).
  236. ==============================================================================*/
  237.  
  238. int STRCONS_Double( double *d ) {
  239.     char *p = STRCONS_buffer;
  240.     double tmp = strtod( STRCONS_buffer, &p );
  241.     if( p != STRCONS_buffer ) *d = tmp;
  242.     return p!=STRCONS_buffer ? STRCONSErr_no_err : STRCONSErr_no_num;
  243. }
  244.  
  245.  
  246. /// ===> funzioni accessorie <============================================== ///
  247.  
  248. /*==============================================================================
  249. Elimina un carattere '\n' eventualmente presente in coda alla stringa puntata da
  250. str. Restituisce la quantita' di caratteri presenti nella stringa dopo
  251. l'elaborazione.
  252. ==============================================================================*/
  253.  
  254. size_t STRCONS_EliminaNewline( char *str, size_t lung ) {
  255.     if( str != NULL && lung > 0 )
  256.         str[--lung] = '\0'; // elimina il '\n'
  257.     return lung;
  258. }
  259.  
  260. /*==============================================================================
  261. Elimina gli eventuali caratteri "pendenti" nello stream stdin. In uscita,
  262. restituisce la quantita' dei caratteri eliminati dallo stream (ad esclusione del
  263. carattere '\n', che non viene conteggiato).
  264. ==============================================================================*/
  265.  
  266. size_t STRCONS_SvuotaStdin() {
  267.     char b2[2] = { '\0', '\0' };
  268.     size_t eliminati = 0;
  269.  
  270.     while( *b2 != '\n' ) { // svuota lo stream di input
  271.         fgets( b2, 2, stdin );
  272.         eliminati += *b2 != '\n';
  273.     }
  274.  
  275.     return eliminati;
  276. }
  277.  
  278. /*==============================================================================
  279. Sostituisce nel buffer ogni occorrenza dei caratteri ',' e '.' con il carattere
  280. impostato come carattere decimale nella localizzazione corrente, rilevato
  281. tramite la funzione standard localeconv().
  282. ==============================================================================*/
  283.  
  284. void STRCONS_AdattaPuntoDecimale( void ) {
  285.     char *p = STRCONS_buffer;
  286.     char v = *(localeconv()->decimal_point);
  287.     while( *p ) { *p=*p=='.'||*p==','?v:*p; ++p; }
  288. }