/*==============================================================================
LIBRERIA STRCONS
di Aldo Carpanelli
v1.1, 13/11 - 6/12 2016
Uno dei compiti piu' tediosi che mi capita di affrontare quando scrivo i miei
programmini amatoriali e' gestire l'immissione dei dati nella console del C. La
parte odiosa sta in tutti quei controlli che tocca fare per assicurarsi di non
incorrere nell'infausto e sempre incombente sfondamento del buffer (a meno di
voler allocare buffer con dimensioni da fantascienza). Una seccatura minore ma
comunque concreta e' la verifica di quell'ingombrante carattere di fine riga
('\n') che a volte viene inserito da fgets(), a volte no. Quando non viene
inserito si ha poi la necessita' di liberare lo stdin dai caratteri "pendenti",
operazione per la quale viene da piu' parti sconsigliato l'uso di flush()
costringendo a inventarsi metodi "fantasiosi".
Che menata! Dunque, mi son detto "e basta!" e ho predisposto una piccola
libreria che mi liberi dall'incomodo.
Le funzioni della libreria STRCONS (nelle intenzioni) esonerano dalla necessita'
di occuparsi dei dettagli appena elencati. Si inizializza la libreria STRCONS
secondo le dimensioni che si ritengono piu' opportune e si usa la funzione
STRCONS_Chiedi(). Punto.
Vediamo com'e' fatta 'sta libreria, va'...
CODICI DI ERRORE
================
Alcune funzioni della libreria restituiscono codici di errore che possono essere
usati per verificare i problemi eventualmente incontrati nel gestire
l'immissione dei dati da parte dell'utente. Eccoli:
enum {
STRCONSErr_no_str = -2, // l'input e' una stringa vuota
STRCONSErr_troncato, // buffer insufficiente (input troncato)
STRCONSErr_no_err, // nessun errore, tutto bene
STRCONSErr_no_mem, // memoria insufficiente
STRCONSErr_enorme, // dimensioni del buffer insensate
STRCONSErr_no_fgets, // errore in fgets()
STRCONSErr_no_num // il buffer non rappresenta un numero
};
E' anche definita una costante che indica la quantita' massima delle stringhe
d'errore disponibili:
#define STRCONSErr_MaxIndStrErr 7
(MaxIndStrErr = indice maximo delle stringhe d'errore)
FUNZIONE INIZIALIZZATRICE
=========================
STRCONS_Inizializza( size_t dim );
Inizializza la libreria allocando un buffer che puo' contenere un massimo di dim
caratteri (il buffer finisce quindi per avere dimensioni pari a dim+1 bytes). Se
anche venisse passato in dim un valore minore, il buffer avra' almeno una
dimensione di 2 byte. Al momento della creazione, il buffer contiene una serie
di '\0'.
Qualora l'allocazione della memoria necessaria non fosse possibile, la funzione
inizializzatrice fallirebbe il suo scopo e restituirebbe un codice d'errore
adeguato, scelto tra quelli gia' elencati.
NOTA: l'allocazione avviene per mezzo della funzione standard del C calloc().
FUNZIONE DI DISMISSIONE
=======================
void STRCONS_Dismetti( void );
La funzione di dismissione si occupa di liberare la memoria allocata per il
buffer abbinato alla libreria.
NOTA: la deallocazione avviene per mezzo della funzione standard del C free().
FUNZIONI DI MODIFICA DELLO STATO DELLA LIBRERIA
===============================================
int STRCONS_Dimensiona( size_t dim );
Cambia le dimensioni del buffer, prevedendo lo spazio per il terminatore '\0'
(dunque, vengono allocati dim+1 byte di memoria).
Se il buffer contiene gia' dei dati, i dati gia' presenti vengono conservati
(nei limiti del possibile).
Se non e' possibile modificare le dimensioni del buffer, il vecchio buffer viene
conservato, cosi' come il suo contenuto.
In caso d'insuccesso restituisce un codice di errore che puo' essere usato per
ricavare informazioni sul tipo di problema riscontrato. Il codice di errore puo'
essere...
STRCONSErr_enorme e' stata richiesta l'allocazione di un buffer dalle
dimensioni uguali o superiori a 4GB, il che e' un'assurdita'
STRCONSErr_no_mem l'allocazione della memoria e' fallita; il buffer non e'
stato ridimensionato, ma il suo contenuto originale e'
rimasto intatto
STRCONSErr_no_err tutto bene, il buffer e' stato ridimensionato e le parti
conservabili del suo contenuto sono state conservate
int STRCONS_Chiedi( void );
Chiede tramite console di inserire un testo. Il testo viene letto fino a un
massimo di caratteri corrispondenti all'attuale capacita' massima del buffer
(impostata tramite STRCONS_Inizializza() oppure STRCONS_Dimensiona()).
Al termine dell'immissione svuota gli eventuali caratteri “pendenti” nello
stdin, “consumandoli” per mezzo della funzione statica STRCONS_SvuotaStdin().
In caso d'insuccesso restituisce un codice di errore che puo' essere usato per
ricavare informazioni sul tipo di problema riscontrato. Il codice di errore puo'
essere...
STRCONSErr_no_str l'utente ha premuto invio senza immettere alcun testo; il
buffer contiene solo il carattere terminatore (cioe' una
stringa vuota e niente piu')
STRCONSErr_troncato la stringa immessa in console e' parzialmente presente nel
buffer, terminata da '\0'; la parte eccedente le
dimensioni del buffer e' andata persa
STRCONSErr_no_err tutto bene, la stringa immessa in console e' presente nel
buffer (senza il carattere finale '\n'), terminata da '\0'
STRCONSErr_no_fgets c'e' stato un errore non meglio precisato nella chiamata
alla funzione standard fgets(); l'oggetto e' nella sua
condizione antecedente alla chiamata alla funzione
STRCONS_Chiedi()
FUNZIONI D'INFORMAZIONE SULLO STATO DELLA LIBRERIA
==================================================
size_t STRCONS_Capacita( void );
Fornisce informazioni sulla capacita' massima del buffer della libreria (intesa
come numero di caratteri effettivamente ricevibili, escluso dunque il carattere
terminatore della stringa C).
size_t STRCONS_Lunghezza( void );
Fornisce informazioni sulla lunghezza della stringa C correntemente contenuta
nel buffer della libreria, sempre minore o uguale al valore restituito dalla
funzione STRCONS _Capacita().
char *STRCONS_PStr( void );
Fornisce un puntatore allo spazio di memoria riservato al buffer della libreria,
il che equivale a fornire l'indirizzo della stringa C in esso contenuta e
immessa dall'utente in console.
NOTA: e' essenziale che la memoria abbinata al puntatore restituito da
questa funzione non venga mai liberata direttamente - si usi sempre
STRCONS_Dismetti().
int STRCONS_Long( long *l, int base );
Converte la stringa contenuta nel buffer in un valore numerico, secondo la
notazione indicata tramite il parametro base.
Immette il risultato della conversione all'indirizzo passato come parametro in
l. Restituisce un codice di errore che puo' essere STRCONSErr_no_err (tutto
bene) oppure STRCONSErr_no_num (conversione non effettuata).
int STRCONS_UnsignedLong( unsigned long *ul, int base );
Converte la stringa contenuta nel buffer in un valore numerico, secondo la
notazione indicata tramite il parametro base.
Immette il risultato della conversione all'indirizzo passato come parametro in
ul. Restituisce un codice di errore che puo' essere STRCONSErr_no_err (tutto
bene) oppure STRCONSErr_no_num (conversione non effettuata).
int STRCONS_Double( double *d );
Converte la stringa contenuta nel buffer in un valore numerico.
Immette il risultato della conversione all'indirizzo passato come parametro in
d. Restituisce un codice di errore che puo' essere STRCONSErr_no_err (tutto
bene) oppure STRCONSErr_no_num (conversione non effettuata).
FUNZIONI ACCESSORIE
===================
size_t STRCONS_EliminaNewline( char *str, size_t lung );
Elimina un carattere '\n' eventualmente presente in coda alla stringa puntata da
str. Restituisce la quantita' dei caratteri presenti nella stringa dopo
l'elaborazione.
size_t STRCONS_SvuotaStdin();
Elimina gli eventuali caratteri “pendenti” nello stream stdin.
In uscita, restituisce la quantita' dei caratteri eliminati dallo stream (ad
esclusione del carattere '\n', che non viene conteggiato).
void STRCONS_AdattaPuntoDecimale( void );
Sostituisce nel buffer ogni occorrenza dei caratteri ',' e '.' con il carattere
impostato come carattere decimale nella localizzazione corrente, rilevato
tramite la funzione standard localeconv().
FUNZIONI DI GESTIONE DEGLI ERRORI
=================================
const char *STRCONSErr_Descrizione( int codice );
Restituisce un puntatore a una stringa che descrive uno dei codici d'errore gia'
elencati e restituibili da alcune delle altre funzioni della libreria. Se viene
passato un codice non compreso tra quelli validi, restituisce la stringa "errore
non previsto".
const char *STRCONSErr_d[STRCONSErr_MaxIndStrErr] = {
"l'input e' una stringa vuota", // -2
"buffer insufficiente, input troncato", // -1
"nessun errore", // 0
"memoria non allocata", // 1
"e' stato richiesto un buffer di 4GB o piu'", // 2
"errore in fgets()", // 3
"la stringa non rappresenta un numero" // 4
};
ESEMPIO D'USO
=============
#include <stdio.h>
#include <stdlib.h>
#include "stringa_console.h"
#define MAX_CARATTERI 7
int main() {
int esito = STRCONS_Inizializza( MAX_CARATTERI );
if( esito == STRCONSErr_no_err ) {
esito = STRCONS_Chiedi();
if( esito <= 0 )
printf( "Ho letto \"%s\"\n\n", STRCONS_PStr() );
printf( "Esito: %s.\n\n", STRCONSErr_Descrizione(esito) );
}
printf( "Premi \"invio\" per lasciare il programma...\n\n" );
getchar();
return 0;
}
==============================================================================*/