Fermare la lettura di FSCANF

di il
18 risposte

Fermare la lettura di FSCANF

Buongiorno,
volevo sapere se è possibile leggere una stringa per un certo numero di caratteri, successivamente ignorare i successivi caratteri della stringa in questo e andare alla riga di input successiva.
Io uso fscanf(file, "%s", stringa) e so che è possibile fare fscanf(file, "%25s", stringa) per limitarne la lunghezza, ma la mia domanda riguarda valori di lunghezza variabile.

Esempio:
ricevo in input un numero x che rappresenta il massimo numero di caratteri, alloco un array di lunghezza x+1, esuccessivamente vorrei leggere la stringa e metterla nell'array leggendo al massimo x caratteri.

NB Non voglio usare il %ms.
Grazie in anticipo

18 Risposte

  • Re: Fermare la lettura di FSCANF

    Se capisco bene cosa vuoi fare ovviamente no.
    devi scrivere la tua funzione
  • Re: Fermare la lettura di FSCANF

    Una cosa tipo questa?
    #include <stdio.h>
    #include <stdlib.h>
    
    #define MAX_DIM 25
    
    int main() {
        char buff[MAX_DIM];
        size_t l;
    
        fgets( buff, MAX_DIM, stdin );
    
        l = strlen( buff );
        if( '\n' == buff[l-1] )          // se '\n' e' in coda a buff
            buff[--l] = '\0';            // scarta il '\n' in coda a buff
        else while( '\n' != getchar() ); // scarta ogni carattere fino
                                         // all'inizio della riga successiva
    
        return 0;
    }
    
  • Re: Fermare la lettura di FSCANF

    E se volessi usare il tasto backspace?
  • Re: Fermare la lettura di FSCANF

    AldoBaldo ha scritto:


    Una cosa tipo questa?
    #include <stdio.h>
    #include <stdlib.h>
    
    #define MAX_DIM 25
    
    int main() {
        char buff[MAX_DIM];
        size_t l;
    
        fgets( buff, MAX_DIM, stdin );
    
        l = strlen( buff );
        if( '\n' == buff[l-1] )          // se '\n' e' in coda a buff
            buff[--l] = '\0';            // scarta il '\n' in coda a buff
        else while( '\n' != getchar() ); // scarta ogni carattere fino
                                         // all'inizio della riga successiva
    
        return 0;
    }
    

    Tipo, però il buffer dovrei allocarlo dinamicamente perchè la dimensione massima non la so a priori, mi viene data come input prima della stringa. In più la stringa potrebbe anche essere più corta, quindi dovrei controllare dall'inizio la presenta del \n.
    Io volevo evitare di dover allocare tutta la stringa quando me ne servono solo i primi n caratteri, altrimenti semplicemente faccio una scanf con %ms, poi mi prendo i primi n caratteri e poi dealloco la prima.

    Il mio problema sorge da fatto che ero convinta che la funziona fscanf mi leggesse solo caratteri tanti quanti occupano o spazio in cui gli dico di scivere.
  • Re: Fermare la lettura di FSCANF

    Ma che ti frega? La macchina più piccola ha memoria in gigabyte mentre a te ne interessano una manciata
  • Re: Fermare la lettura di FSCANF

    M2: "E se volessi usare il tasto backspace?"

    Cosa intendi dire? Cioè, so cos'è il tasto backspace, ma non capisco la ragione di questa domanda.
  • Re: Fermare la lettura di FSCANF

    Cosa è la f di fgets?
  • Re: Fermare la lettura di FSCANF

    La f... ? Non farmi scrivere sconcerie, dai.
    Questo gusto di rispondere per indovinelli proprio non lo capisco.
    Ciò detto, immagino (non avendolo mai trovato scritto da nessuna parte) che "get"+"s" stia per "ricava"+"stringa", mentre "f" potrebbe stare per "file" (visti parametri richiesti), o per "function", o essere una forma contratta per "freemandelafreevalpredaetuttiglialtrimafreeanchemiocuggino". Quindi?
  • Re: Fermare la lettura di FSCANF

    AldoBaldo ha scritto:


    La f... ? Non farmi scrivere sconcerie, dai.
    Questo gusto di rispondere per indovinelli proprio non lo capisco.
    Ciò detto, immagino (non avendolo mai trovato scritto da nessuna parte) che "get"+"s" stia per "ricava"+"stringa", mentre "f" potrebbe stare per "file" (visti parametri richiesti), o per "function", o essere una forma contratta per "freemandelafreevalpredaetuttiglialtrimafreeanchemiocuggino". Quindi?
    ti stai avvicinando (per la f). oggi si chiama "per stream" (anche se per la verità nasce "per file").
    ma cos'è uno stream?

    non sono indovinelli, è il metodo maieutico by Socrate.
  • Re: Fermare la lettura di FSCANF

    La catena degli indovinelli si allunga! E vai!
    Dunque, risalgo alla lettura dell'Ulisse di Joyce (ai tempi del liceo - che mattone!) per ricordare lo stream of consciousness, ovvero il flusso della consapevolezza, del pensiero cosciente. Stream = Flusso. Tsè, che sfoggio di cultura!
    Ripensando a Joyce e al suo insostenibile tomo, preferivo la mia ipotesi iniziale, sai, quella della fi-gets()...
  • Re: Fermare la lettura di FSCANF

    AldoBaldo ha scritto:


    La catena degli indovinelli si allunga! E vai!
    Dunque, risalgo alla lettura dell'Ulisse di Joyce (ai tempi del liceo - che mattone!) per ricordare lo stream of consciousness, ovvero il flusso della consapevolezza, del pensiero cosciente. Stream = Flusso. Tsè, che sfoggio di cultura!
    Ripensando a Joyce e al suo insostenibile tomo, preferivo la mia ipotesi iniziale, sai, quella della fi-gets()...
    Acqua.
    Tra l'altro l'ho scritto sopra.
    Bene, facendo finta di volersi un pochino elevare dal livello medio forummistico, bisognerebbe avere una vaga idea di cosa fanno le funzioni in generale.
    A sostituire fscanf è stata consigliata fgets.
    Normalmente si saprebbe benissimo cos'è fscanf, cos'è fgets eccetera.

    Non è questo il caso.
    Allora mi chiedo: cosa sarà mai la "f" della funzione?
    "anticamente" stava per file (non f..a), "oggi" sta per stream (che grosso modo è la stessa cosa, ma fa più fico).
    Ebbene, cos'è uno stream (o un file) ?
    Bisognerebbe saperlo.
    Ma perchè?

    Perchè in questo caso vuoi usare una funzione per STREAM per gestire la CONSOLE.
    Non c'è nulla di male in questo, ma uno STREAM non è una CONSOLE (non per videogiochi).
    Ebbene ti sei mai chiesto cosa sia il mitico stdin ?
    E, soprattutto, [prima domanda che ho posto] cosa succede se premi il tasto BACKSPACE sulla CONSOLE e con fgets ?

    Risposte possibili
    - non mi interessa, tanto programmare è facile
    - non mi interessa, tanto sembra funzionare
    - non mi interessa, tanto sono un dilettante
    - boh, provo a vedere e mi dumpo un carattere alla volta la stringa
    - boh, leggo la documentazione
    - boh, leggo la documentazione e provo comunque a vedere come funziona
    - boh, sono un fanatico e mi vado a leggere il sorgente dell'implementazione della funzione, poi leggo la documentazione, provo comunque a vedere cosa succede
    - niente di tutto questo, tanto programmare è facile.
  • Re: Fermare la lettura di FSCANF

    Mmm... Va bene, visto lo spirito enigmistico che ha preso questo filone di discussione oggi pomeriggio farò qualche esperimento per poi tornare qui. Con un impegno da parte tua, però: se non trovo la risposta me la dai tu. In caso contrario...

    A dopo!
  • Re: Fermare la lettura di FSCANF

    AldoBaldo ha scritto:


    Mmm... Va bene, visto lo spirito enigmistico che ha preso questo filone di discussione oggi pomeriggio farò qualche esperimento per poi tornare qui. Con un impegno da parte tua, però: se non trovo la risposta me la dai tu. In caso contrario...

    A dopo!
    Vabbè visto che ho posto la domanda, la risposta sarà ovviamente e ontologicamente interessante.
    La risposta è : uno STREAM (un file) è di derivazione *nix, ed è composto da un FLUSSO di caratteri (parlo sempre della versione per forummmm).

    Il FLUSSO dei caratteri premuti sulla CONSOLE non è, necessariamente, quello MOSTRATO dalla console.
    Quando premi il backspace il CARATTERE corrispondente viene AGGIUNTO al flusso (cioè allo stream, cioè al file) e quindi DENTRO IL PROGRAMMA ti troverai, con la fgets, il carattere DENTRO la stringa ritornata.

    Ciò accade anche per altri casi (meno frequenti).
    Comunque il sunto è: mentre la CONSOLE fa tante belle cose (il cursore si sposta, i caratteri si cancellano eccetera), se usi funzioni PER STREAM otterrai tutto quanto, compresa la "spazzatura", nella stringa risultante.

    Questo perchè il FLUSSO è ovviamente monotonicamente crescente, non è che "torna indietro" (* qui risparmio pipponi e spiegoni di ogni genere relativi a certe eccezioni che sono state sviluppate proprio per aiutare i programmatori niubbi).

    Nessuna battutaccia sul ciclo femminile

    Se fossi curioso di parlerei dell'autenticazione stile POP3 o SMTP e cosa accade lì, e perchè e percome.
    ---
    La versione molto breve è : se usi una funzione, cerca di capire cosa effettivamente ritornerà, e perchè.

    Bene, col mio "pipponcello" non hai imparato nulla, ma almeno con zero fatica.
    Io vado a magnà, sperando che si capisca che l'apparente banalità "leggo qualcosa dalla console" non è per nulla banale.

    Anzi.

    Ma, d'altronde, programmare è facile.
    Meglio: programmare è facile.
    Programmare bene no.
  • Re: Fermare la lettura di FSCANF

    Tra un attimo mi rileggo con calma quel che hai scritto. Dico "tra un attimo" perché mi ero collegato per inviarti quel che ho scritto io e solo a quel punto ho visto che mi hai anticipato. Copio e incollo comunque qui la mia risposta, caso mai ti interessasse leggerla anche solo per svago.
    Allora PER QUEL POCO CHE NE SO (INTUITO dalle letture di un passato non recentissimo) uno stream è una serie di dati ai quali accedi in lettura e/o in scrittura tramite funzioni che fanno affidamento su un "segnaposizione", un indice. Da cui funzioni come fseek() (che permette di posizionare l'indice secondo necessità), ftell() (che dice in che posizione si trova correntemente l'indice), eof() (che dice se l'indice è "in fondo" ai dati effettivamente presenti nello stream), rewind() (che riporta l'indice in testa ai dati), fgetpos() e fsetpos() (più o meno versioni "specializzate" di ftell() e fseek()), ecc.

    Se interpreto correttamente, CREDO CHE "stdin" stia per "standard input", ed è uno stream, tanto quanto "stderr" e "stdout". La console, sempre per quel che ne so, è un'interfaccia che elabora i suoi dati facendo affidamento su stream, diciamo "collocandoli" in stream che gestisce con meccanismi suoi, interni, "opachi" a chi la usa e accessibili con le funzioni della libreria standard.

    In questo contesto, CREDO CHE backspace porti la console ad arretrare l'indice di una posizione nello stream. Anche il nome assegnato al tasto parrebbe suggerire questa ipotesi. Così pure l'esistenza di funzioni quali ungetc(), che permette di inserire caratteri oltre la posizione dell'indice (purché entro la capacità dello stream).

    Continuo nella mia catena di ipotesi.
    Scrivo in console, che so... "pippo". Ad ogni pressione del tasto (?) nello stream vengono immessi nell'ordine i caratteri "p", "i", "p", "p" e "o", portando avanti ogni volta l'indice di una posizione.
    Premo una volta backspace. Posso pensare che l'indice venga fatto arretrare, non necessariamente "togliendo" dallo stream l'ultimo carattere immesso.
    Premo "i". La "i" viene immessa nello stream, nella posizione nella quale prima si trovava la "o", sovrascrivendola se era tutt'ora lì come "residuo" dell'operazione precedente, aggiungendola in una locazione "vuota" se l'uso del backspace aveva portato in qualche modo alla sua eliminazione.
    A questo punto, nello stream c'è "pippi".
    Se premo "invio", viene aggiunto nello stream il carattere di new line e fgets() restituisce quel che c'è nello stream.

    Fin qui le ipotesi.

    Sul versante delle prove, che io usi o non usi backspace prima di chiamare fgets() non cambia nulla, quel che viene collocato nel buffer (se lo spazio è sufficiente) è comunque la serie dei caratteri immessi, meno quelli cancellati con backspace, e il carattere di new line.
    EDIT: dopo sette fette ho capito che era polenta e ho realizzato il senso della tua esortazione a non fare riferimenti al ciclo femminile... quella battuta, lasciatelo dire, è una vera MESTRUOSITA'!
Devi accedere o registrarti per scrivere nel forum
18 risposte