Visualizzazione dei risultati da 1 a 10 su 10

Discussione: [C]Lettura stringhe

  1. #1
    Utente di HTML.it
    Registrato dal
    Oct 2010
    Messaggi
    185

    [C]Lettura stringhe

    Ciao a tutti, in un esercizio mi si chiede di scrivere un programma che legge continuamente dallo standard input righe di testo terminate da \n, e far terminare il programma quando inserisco una riga vuota.

    Cercando informazioni ho trovato che per leggere righe di testo posso usare la funzione
    codice:
    fgets(destinazione, dimensione, stdin)
    che mi sembra di aver capito legge stringhe digitate da tastiera della dimensione massima di "dimensione" e la salva in "destinazione" terminando ogni stringa con \n.

    Quello che non mi è chiaro è come far riconoscere la stringa vuota e quindi far terminare il programma.
    Quello che ho provato a scrivere è questo:
    codice:
    #include <stdio.h>
    
    #define BUFFER_LENGTH 255
    
    int main(int argc, char *argv[]) {
        char buffer[BUFFER_LENGTH];
        while(buffer!=NULL){
            fgets(buffer, BUFFER_LENGTH, stdin);
        }
        return 0;
    }
    ma sia con NULL che con "" non esce dal while.
    Mi potreste dare una mano?
    Grazie mille

  2. #2
    codice:
    while ( *(fgets(buffer,BUFFER_LENGTH, stdin)) != '\n')
    {
    ...
    }
    o in alternativa:

    codice:
    do 
    {
        fgets(buffer, BUFFER_LENGTH, stdin);
    }while ( buffer[0] != '\n');

  3. #3
    Utente di HTML.it
    Registrato dal
    Oct 2010
    Messaggi
    185
    soluzione abbastanza semplice alla fine.
    Ma se io non sapessi a priori la lunghezza della stringa che vado ad inserire? Esiste un modo di fare la fgets senza dire a priori la lunghezza della stringa?

  4. #4
    Utente bannato
    Registrato dal
    May 2014
    Messaggi
    7
    Il problema è che la fgets() scrive la stringa che viene presa in input nel buffer. Per forza di cose devi "dirgli" una dimensione massima entro la quale non si sfora la lunghezza del buffer.
    L' alternativa sarebbe quella di leggere la stringa carattere per carattere con la getchar(), allocando un carattere alla volta (oppure raddoppiando la dimensione del buffer ogni volta che serve più spazio), però se chiami troppe volte la realloc() può essere inefficiente.

  5. #5
    Utente di HTML.it L'avatar di Scara95
    Registrato dal
    Jul 2009
    residenza
    Zimella (VR)
    Messaggi
    2,590
    Quote Originariamente inviata da SEGFAULT Visualizza il messaggio
    Il problema è che la fgets() scrive la stringa che viene presa in input nel buffer. Per forza di cose devi "dirgli" una dimensione massima entro la quale non si sfora la lunghezza del buffer.
    L' alternativa sarebbe quella di leggere la stringa carattere per carattere con la getchar(), allocando un carattere alla volta (oppure raddoppiando la dimensione del buffer ogni volta che serve più spazio), però se chiami troppe volte la realloc() può essere inefficiente.
    In realtà puoi benissimo usare fgets alla base:
    codice:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define N 128
    
    static int cpy(char **line, size_t *n, int l, char *BUFFER, int tmp_l) {
      if(((*n)-l) < (tmp_l+1)) {
        *n =  l+tmp_l+1;
        char *tmp = (char *)realloc(*line, sizeof(char)*(*n));
        if(tmp == NULL) {
          return -2;
        }
        *line = tmp;
      }
      strcpy((*line)+l, BUFFER);
      return 0;
    }
    
    int get_line(char **line, size_t *n, FILE *f) {
      char BUFFER[N];
      int l = 0, tmp_l;
      while(1) {
        if(fgets(BUFFER, N, f) == NULL) {
          return -1;
        }
        tmp_l = strlen(BUFFER);
        if(BUFFER[tmp_l-1] == '\n') {
          BUFFER[--tmp_l] = '\0';
          break;
        }
        if(feof(f)) {
          break;
        }
        if(cpy(line, n, l, BUFFER, tmp_l)) {
          return -2;
        }
        l += tmp_l;
      }
      if(cpy(line, n, l, BUFFER, tmp_l)) {
        return -2;
      }
      return l+tmp_l;
    }
    
    int main(void) {
      char *l = NULL;
      size_t n = 0;
      while(get_line(&l, &n, stdin) >= 0) {
        printf("%s", l);
      }
      return 0;
    }
    A parte che se stai usando un compilatore tipo gcc puoi usare getline (funzione di libreria, che non è pienamente compatibile con la funzione presentata sopra).

    Edit 15:47 corretto errore di svista: BUFFER[--tmp_l] == '\0'; -> BUFFER[--tmp_l] = '\0';
    Ultima modifica di Scara95; 23-05-2014 a 15:49
    "Quid enim est, quod contra vim sine vi fieri possit?" - Cicerone, Ad Familiares

  6. #6
    Utente di HTML.it L'avatar di Scara95
    Registrato dal
    Jul 2009
    residenza
    Zimella (VR)
    Messaggi
    2,590
    Quote Originariamente inviata da vbextreme Visualizza il messaggio
    codice:
    while ( *(fgets(buffer,BUFFER_LENGTH, stdin)) != '\n')
    {
    ...
    }
    o in alternativa:

    codice:
    do 
    {
        fgets(buffer, BUFFER_LENGTH, stdin);
    }while ( buffer[0] != '\n');
    Questo codice è totalmente insicuro in ogni caso...
    "Quid enim est, quod contra vim sine vi fieri possit?" - Cicerone, Ad Familiares

  7. #7
    Utente bannato
    Registrato dal
    May 2014
    Messaggi
    7
    @Scara95: Così deve comunque specificare la lunghezza massima della stringa, che è N nel tuo caso.

  8. #8
    Utente di HTML.it L'avatar di Scara95
    Registrato dal
    Jul 2009
    residenza
    Zimella (VR)
    Messaggi
    2,590
    Quote Originariamente inviata da SEGFAULT Visualizza il messaggio
    @Scara95: Così deve comunque specificare la lunghezza massima della stringa, che è N nel tuo caso.
    Guarda bene -.-"'
    Cambia il 128 in un numero basso, ad esempio 5, compila e scrivi una frase di 20 caratteri.
    "Quid enim est, quod contra vim sine vi fieri possit?" - Cicerone, Ad Familiares

  9. #9
    Quando si legge una stringa è sempre poco efficente una lettura "dimanica" della stessa.
    Sempre meglio quindi allocare un buffer di dimensioni "esagerate" in modo da non doverlo poi inutilmente ritoccare sucessivamente.

    Questo codice è totalmente insicuro in ogni caso...
    ???
    Ultima modifica di vbextreme; 26-05-2014 a 08:48

  10. #10
    Utente di HTML.it L'avatar di Scara95
    Registrato dal
    Jul 2009
    residenza
    Zimella (VR)
    Messaggi
    2,590
    Quote Originariamente inviata da vbextreme Visualizza il messaggio
    Quando si legge una stringa è sempre poco efficente una lettura "dimanica" della stessa.
    Sempre meglio quindi allocare un buffer di dimensioni "esagerate" in modo da non doverlo poi inutilmente ritoccare sucessivamente.
    Puoi benissimo sovra-allocare anche con getline o con la funzione che ti ho presentato io: basta che allochi precedentemente la memoria e passi come parametri il puntatore al blocco di memoria e il numero di bytes allocati.

    ???
    Puoi rischiare di perdere dati, nel caso di EOF non preceduto da ritorno a capo non da una soluzione coerente.
    Insomma, puoi benissimo usarlo, ma a condizione che alcuni casi non si presentono CERTAMENTE mai in input.
    "Quid enim est, quod contra vim sine vi fieri possit?" - Cicerone, Ad Familiares

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.