Oppure

Loading
11/07/17 19:11
Mikelius
Buonasera, come spesso accade, La maggior parte dei programmi richiedono degli input, spesso questi input posso essere dei semplici Si - No, intero positivo minore di 10 o complessi tipo equazioni.

Ho scritto delle funzioni, in teoria generiche, che hanno la funzione di verificare
se il dato immesso sia più o meno lecito
Nel caso di Si-No verificarli è molto semplice. Posto innanzitutto questa funzione (ne ho una per gli interi positivi <10 sulla stessa falsa riga di questa ed un'altra per verificare un range di interi di grandezza variabile (es. 56-9865)

Posto una alla volta per non fare confusione


func.c
#include <stdio.h>
#include <ctype.h>

/* Verifica che l'immissione da tastiera sia tra 2 possibili caratteri
   scelti dal chiamante. I caratteri possono essere minuscoli o MAIUSCOLI.
   Es. [S/N]-[s/n] o [Y/N]-[y/n] */

/* Dato un input da tastiera lo esamino carattere per carattere.
   Ritengo valido l'input composto SOLO ED ESCLUSIVAMENTE dai caratteri in input
   vero e falso. Prendo il primo carattere immesso,
   - se NON E' uno dei caratteri validi finisco la funzione con errore
   - se LO E' , verifico il 2° .
       - se è '\n' vuole dire che è stato immesso solo un carattere ed e' valido
       - altrimenti l'input non è valido.
 Si lascia al chiamante l'opportunità di ripetere la richiesta del carattere 
in caso di esito negativo della 1°  */

int selecTF( int vero, int falso, unsigned char *carattere ){

    int c = 0;         //Inizzializzo per sicurezza
    *carattere = 'Buonasera, come spesso accade, La maggior parte dei programmi richiedono degli input, spesso questi input posso essere dei semplici Si - No, intero positivo minore di 10 o complessi tipo equazioni.


Ho scritto delle funzioni, in teoria generiche, che hanno la funzione di verificare
se il dato immesso sia più o meno lecito
Nel caso di Si-No verificarli è molto semplice. Posto innanzitutto questa funzione (ne ho una per gli interi positivi <10 sulla stessa falsa riga di questa ed un'altra per verificare un range di interi di grandezza variabile (es. 56-9865)

Posto una alla volta per non fare confusione


func.c
#include <stdio.h>
#include <ctype.h>

/* Verifica che l'immissione da tastiera sia tra 2 possibili caratteri
   scelti dal chiamante. I caratteri possono essere minuscoli o MAIUSCOLI.
   Es. [S/N]-[s/n] o [Y/N]-[y/n] */

/* Dato un input da tastiera lo esamino carattere per carattere.
   Ritengo valido l'input composto SOLO ED ESCLUSIVAMENTE dai caratteri in input
   vero e falso. Prendo il primo carattere immesso,
   - se NON E' uno dei caratteri validi finisco la funzione con errore
   - se LO E' , verifico il 2° .
       - se è '\n' vuole dire che è stato immesso solo un carattere ed e' valido
       - altrimenti l'input non è valido.
 Si lascia al chiamante l'opportunità di ripetere la richiesta del carattere 
in caso di esito negativo della 1°  */

int selecTF( int vero, int falso, unsigned char *carattere ){

    int c = 0;         //Inizzializzo per sicurezza
    *carattere = '{parsed_message}'; //Inizzializzo per sicurezza

    // prelevo e testo dal buffer il 1° carattere
    c = getchar();

    if( c == tolower( vero ) || c == toupper( vero )
        ||
        c == tolower( falso ) || c == toupper( falso ) ){

// Lo rendo minuscolo per evitare nella funzione chiamante 2 controlli ulteriori
//  NON ESSENZIALE
        *carattere =(unsigned char)tolower( c );

        // prelevo e testo dal buffer il 2° carattere
        c = getchar();
        if( (c == '\n') ){
         //   printf( "VALORE CORRETTO\n" ); //utile o no?
            return 0;
        }
    }
    while( (getchar() != '\n') );
//Svuoto il  buffer nel caso di richiesta di nuova immissione
    return -1;
}


main.c
#include <stdio.h>

int selecTF( int ch1, int ch2, unsigned char *caracter );


int main( int arcv, char *arcg[] ){

    int value = 0;
    unsigned char letter=' ' ;


    printf( "IMMETTERE [%c/%c] :", 'S', 'N' );
    while(selecTF( 's', 'n',&letter ))
    {
            printf( "%s\n%s [%c/%c]:",
                "IL CARATTERE IMMESSO NON E'CORRETTO",
                "IMMETTERE",
                'S', 'N' );
    }

    printf( "IL carattere scelto e' il: %c\n\n", letter );


    return 0;
}


Pareri? migliorie? meglio che mi do all'ippica XD??

P.S. (ma sono i commenti che rendono il 1° codice non colorato?)'; //Inizzializzo per sicurezza // prelevo e testo dal buffer il 1° carattere c = getchar(); if( c == tolower( vero ) || c == toupper( vero ) || c == tolower( falso ) || c == toupper( falso ) ){ // Lo rendo minuscolo per evitare nella funzione chiamante 2 controlli ulteriori // NON ESSENZIALE *carattere =(unsigned char)tolower( c ); // prelevo e testo dal buffer il 2° carattere c = getchar(); if( (c == '\n') ){ // printf( "VALORE CORRETTO\n" ); //utile o no? return 0; } } while( (getchar() != '\n') ); //Svuoto il buffer nel caso di richiesta di nuova immissione return -1; }


main.c
#include <stdio.h>

int selecTF( int ch1, int ch2, unsigned char *caracter );


int main( int arcv, char *arcg[] ){

    int value = 0;
    unsigned char letter=' ' ;


    printf( "IMMETTERE [%c/%c] :", 'S', 'N' );
    while(selecTF( 's', 'n',&letter ))
    {
            printf( "%s\n%s [%c/%c]:",
                "IL CARATTERE IMMESSO NON E'CORRETTO",
                "IMMETTERE",
                'S', 'N' );
    }

    printf( "IL carattere scelto e' il: %c\n\n", letter );


    return 0;
}


Pareri? migliorie? meglio che mi do all'ippica XD??

P.S. (ma sono i commenti che rendono il 1° codice non colorato?)
Ultima modifica effettuata da Mikelius 11/07/17 19:16
aaa
11/07/17 21:04
AldoBaldo
Tempo fa per affrontare una volta per tutte la stessa situazione avevo escogitato una roba così (le righe che interessano sono 16-38):

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

/*==============================================================================
Presenta all'utente la stringa passata nel parametro "testo", seguita dai
caratteri passati tramite i parametri vero e falso, tra parentesi e separati da
una sbarra diagonale.
Se l'utente digita il carattere corrispondente a vero, la funzione restituisce
1; se digita il carattere corrispondente a falso restituisce 0. Fintanto che
l'utente non inserisce un carattere corrispondente a vero o a falso, la funzione
richiede insistentemente una nuova immissione.
La funzione non fa differenza tra caratteri minuscoli e maiuscoli.
==============================================================================*/

int chiedi_vero_falso (char *testo, char vero, char falso) {
    int esito, primo_passaggio = 1;

    vero  = tolower( vero );  /* internamente, usa sempre lettere minuscole */
    falso = tolower( falso ); /* internamente, usa sempre lettere minuscole */

    do {
        int input; /* riceve il valore di ritorno di getchar() */

        if( !primo_passaggio) /* se e' il caso, riformula la domanda */
            printf( "%s", "Immissione non valida, riprova.\n\n" );
        else primo_passaggio = 0;

        /* pone la domanda coerentemente coi parametri */
        printf( "%s (%c/%c) ", testo, vero, falso );
        input = tolower( getchar() );
        esito = ((input!=vero)&&(input!=falso)) ? -1 : (input==vero?1:0);

        while( '\n' != input ) input = getchar(); /* svuota stdin */
    } while( -1 == esito );

    return esito;
}

/*==============================================================================
Semplice esempio d'uso.
==============================================================================*/

int main() {
    int esito = chiedi_vero_falso( "Ti chiami AldoBaldo?", 's', 'n' );

    if( 1 == esito ) /* 1: vero (in questo caso, si') */
        printf( "Ah, ti chiami AldoBaldo... allora sei figo!\n\n" );
    else printf( "Lo sapevo, AldoBaldo e' piu' figo di te.\n\n" );

    printf( "Premi \"invio\" per lasciare il programma...\n\n" );
    getchar();

    return 0;
}
Ultima modifica effettuata da AldoBaldo 11/07/17 21:05
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.
11/07/17 23:58
Mikelius
Postato originariamente da AldoBaldo:

Tempo fa per affrontare una volta per tutte la stessa situazione avevo escogitato una roba così (le righe che interessano sono 16-38):

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

/*==============================================================================
Presenta all'utente la stringa passata nel parametro "testo", seguita dai
caratteri passati tramite i parametri vero e falso, tra parentesi e separati da
una sbarra diagonale.
Se l'utente digita il carattere corrispondente a vero, la funzione restituisce
1; se digita il carattere corrispondente a falso restituisce 0. Fintanto che
l'utente non inserisce un carattere corrispondente a vero o a falso, la funzione
richiede insistentemente una nuova immissione.
La funzione non fa differenza tra caratteri minuscoli e maiuscoli.
==============================================================================*/

int chiedi_vero_falso (char *testo, char vero, char falso) {
    int esito, primo_passaggio = 1;

    vero  = tolower( vero );  /* internamente, usa sempre lettere minuscole */
    falso = tolower( falso ); /* internamente, usa sempre lettere minuscole */

    do {
        int input; /* riceve il valore di ritorno di getchar() */

        if( !primo_passaggio) /* se e' il caso, riformula la domanda */
            printf( "%s", "Immissione non valida, riprova.\n\n" );
        else primo_passaggio = 0;

        /* pone la domanda coerentemente coi parametri */
        printf( "%s (%c/%c) ", testo, vero, falso );
        input = tolower( getchar() );
        esito = ((input!=vero)&&(input!=falso)) ? -1 : (input==vero?1:0);

        while( '\n' != input ) input = getchar(); /* svuota stdin */
    } while( -1 == esito );

    return esito;
}

/*==============================================================================
Semplice esempio d'uso.
==============================================================================*/

int main() {
    int esito = chiedi_vero_falso( "Ti chiami AldoBaldo?", 's', 'n' );

    if( 1 == esito ) /* 1: vero (in questo caso, si') */
        printf( "Ah, ti chiami AldoBaldo... allora sei figo!\n\n" );
    else printf( "Lo sapevo, AldoBaldo e' piu' figo di te.\n\n" );

    printf( "Premi \"invio\" per lasciare il programma...\n\n" );
    getchar();

    return 0;
}



Ho provato il codice. Riscontro un funzionamento che per me è un bug.. se immetto la stringa tipo
"sn" o "n5464:-???" accetta lo stesso l'input e va avanti
aaa
12/07/17 4:48
AldoBaldo
Non è un malfunzionamento, è una caratteristica. L'unica cosa che verifico è il primo carattere dell'input. Secondo te sarebbe meglio inibire le immissioni che comprendano altri caratteri aggiuntivi rispetto a quello richiesto? In effetti la tua soluzione lo fa. Sai che ti dico? Accetto la tua correzione. Tra un po' mando la versione modificata.
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.
12/07/17 5:12
AldoBaldo
Fatto! La differenza rispetto a prima sta nelle righe dalla 32 alla 34.
Ora se è stato immesso più di un carattere la funzione non accetta l'input e replica la richiesta di immissione.

Giè che c'ero ho anche fatto in modo che nel proporre la richiesta di immissione vengano usati in console gli stessi caratteri passati come parametri, non le loro versioni minuscole. La differenza riguarda solo la visualizzazione, perché poi in effetti vengono accettati come risposta sia il maiuscolo, sia il minuscolo.

Edit: sempre per far l'esagerato, ho previsto anche il caso in cui il parametro testo fosse NULL.

/*==============================================================================
Presenta all'utente la stringa passata nel parametro "testo", seguita dai
caratteri passati tramite i parametri vero e falso, tra parentesi e separati da
una sbarra diagonale.
Se l'utente immette il carattere corrispondente a vero, la funzione restituisce
1; se immette il carattere corrispondente a falso restituisce 0. Fintanto che
l'utente non inserisce uno e un solo carattere corrispondente a vero o a falso,
la funzione richiede insistentemente una nuova immissione.
La funzione non fa differenza tra caratteri minuscoli e maiuscoli.
==============================================================================*/

int chiedi_vero_falso (const char *testo, char vero, char falso) {
    int esito, qCar, primo_passaggio = 1, t = NULL!=testo;
    const char *spz[] = { "", " " }; /* spz: spazio */

    int vMin = tolower( vero );  /* internamente, usa solo lettere minuscole */
    int fMin = tolower( falso ); /* internamente, usa solo lettere minuscole */

    do {
        int input; /* riceve il valore di ritorno di getchar() */

        if( !primo_passaggio) /* se e' il caso, riformula la domanda */
            printf( "%s", "Immissione non valida, riprova.\n\n" );
        else primo_passaggio = 0;

        /* pone la domanda coerentemente coi parametri */
        printf( "%s%s(%c/%c) ", t?testo:spz[0], spz[t], vero, falso );

        input = tolower( getchar() );
        esito = ((input!=vMin)&&(input!=fMin)) ? -1 : (input==vMin?1:0);

        for( qCar=0; '\n' != input; ++qCar )
            input = getchar(); /* svuota stdin e conta i caratteri immessi */
        if( 1 != qCar ) esito = -1; /* accetta input con un solo carattere */
    } while( -1 == esito );

    return esito;
}
Ultima modifica effettuata da AldoBaldo 12/07/17 5:37
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.
12/07/17 7:02
Mikelius
Postato originariamente da AldoBaldo:

Non è un malfunzionamento, è una caratteristica. L'unica cosa che verifico è il primo carattere dell'input. Secondo te sarebbe meglio inibire le immissioni che comprendano altri caratteri aggiuntivi rispetto a quello richiesto? In effetti la tua soluzione lo fa. Sai che ti dico? Accetto la tua correzione. Tra un po' mando la versione modificata.


Non era proprio una correzione, ma io non vorrei svegliarmi la notte ,e chiedermi se l'utente che avesse digitato "sn" era strabico o meno. Non è impensabile che sia la 's' ad essere di troppo XD.

Per quanto riguarda "testo". Io l'ho messo fuori la funzione per renderla minimale.
Chiedo a tutti, come buon stile e più opportuno dentro o fuori la funzione?

Chiedo a te (ed anche a tutti)
            /* pone la domanda coerentemente coi parametri */
            printf( "%s%s(%c/%c) ", testo?testo:" ", "", vero, falso );


cosi eviti una variabile? cioe se testo è NULL può essere considerata 0 e se è con dei valori 1?

            esito = ((input!=vMin)&&(input!=fMin)) ? -1 : (input==vMin?1:0);
//usando invece
            esito = ((input!=tolower( vero ))&&(input!=tolower( falso ))) ? -1 : (input==tolower( vero )?1:0);

Cosi si hanno 2 variabili in meno ma una chiamata a tolower in più?
meglio usare le 2 variabili (utilizzare più memoria) o una chiamata a tolower? (aumentare il tempo di calcolo).

Ultima modifica effettuata da Mikelius 12/07/17 7:03
aaa
12/07/17 7:47
AldoBaldo
Il testo della richiesta l'ho inserito tra i parametri perché in quel modo se l'utente immette qualcosa di inaccettabile è possibile ripetere la richiesta completa e, in un certo senso, "sigillare" il procedimento assicurandosi che il valore ritornato sia per forza o 0 o 1 (eliminando così la necessità di ingombranti verifiche "esterne";).

Sulla questione della variabile in più o in meno e del calo di prestazioni per la chiamata a tolower() in più direi che nel contesto di una funzione del genere è irrilevante. A me, lì per lì, è sembrato più chiaro avere due variabili distinte vMin e fMin, però non credo sia una cosa così importante.
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.
12/07/17 8:45
Mikelius
Postato originariamente da AldoBaldo:

Il testo della richiesta l'ho inserito tra i parametri perché in quel modo se l'utente immette qualcosa di inaccettabile è possibile ripetere la richiesta completa e, in un certo senso, "sigillare" il procedimento assicurandosi che il valore ritornato sia per forza o 0 o 1 (eliminando così la necessità di ingombranti verifiche "esterne";).

Sulla questione della variabile in più o in meno e del calo di prestazioni per la chiamata a tolower() in più direi che nel contesto di una funzione del genere è irrilevante. A me, lì per lì, è sembrato più chiaro avere due variabili distinte vMin e fMin, però non credo sia una cosa così importante.



Dipende da ciò che si vuole fare, nella mia si lascia libero il chiamante di decidere (ad esempio, si voglia concedere solo 3 tentativi di immissione)

Per il resto... in questo caso, con le attuali risorse dei moderni pc, non credo cambi molto. in ambienti con poca memoria meglio la chiamata in più, in ambienti per alte prestazioni meglio le 2 variabili.
La mia era una domanda generica: Essendo liberi, e con risorse illimitate, cosa sarebbe più opportuno? risparmio di memoria o alte prestazioni?
aaa