Visualizzazione risultati 1 fino 13 di 13

Discussione: [C]programma su gestione stringhe in segmentation fault

  1. #1
    L'avatar di seneca
    seneca non è connesso Super Moderatore
    Data registrazione
    18-12-2004
    Residenza
    la Città Eterna
    Messaggi
    8,376

    Cool [C]programma su gestione stringhe in segmentation fault

    Questo programma (corretto e funzionante) prende una frase (preimpostata) e restituisce in output la frase senza le s.
    Codice:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    char * cancella(char *str, char c)
    {
       int i, j=0;
       char *app;
       app=(char*) malloc(strlen(str)+1);
       for (i=0; i<= strlen(str); ++i)
          if (str[i]!=c)
             app[j++]=str[i];
       str=(char*) malloc(strlen(app)+1);
       strcpy(str, app);
       free(app);
       return str;
    }
    
    main()
    {  
       char *s="sschissa se ss s sfunzionassssss";
       printf("La frase da esaminare è: %s\n", s);
       printf("%s\n", cancella(s, 's'));
     }


    Qui ho provato a cambiare il main per permettere di personalizzare la frase prendendola in input da tastiera, ma non riesco a trovare il bandolo della matassa perchè va sempre in segmentation fault. Dove sbaglio?
    Codice:
    main()
    {  
       char x[2], y[100];
       char *a="s", *b="n";
       char *s="sschissa se ss s sfunzionassssss";
       printf("La frase da esaminare è: %s\n", s);
       printf("Vuoi cambiare la frase? s/n\n");
       scanf("%s", x);
       if (strcmp(x, b)==0)
          printf("%s\n", cancella(s, 's'));
       else if (strcmp(x, a)==0)
       {
          printf("Scrivi la nuova frase:\n");
          gets(y);
          printf("%s\n", cancella(y, 's'));
       }
       else
          printf("Opzione non valida\n");
    }
    EDIT:
    ho corretto un errore, ma continua a non funzionare...
    Ultima modifica di seneca : 30-08-2007 alle ore 01.48.41 Motivo: correzione piccolo errore, ma continua a non funzionare


    -- Aut Roma Aut Nihil!

  2. #2
    L'avatar di AlexKidd
    AlexKidd non è connesso Altervistiano Junior
    Data registrazione
    09-02-2007
    Messaggi
    516

    Predefinito

    c'è un buffer overflow nel programma piuttosto evidente

    la variabile x può memorizzare una stringa di al più 1 caratteri e questè è sbagliato perchè una stringa in memoria viene memorizzata con il carattere speciale '\0' che ne determina la fine (in questi casi è più naturale valutare un singolo carattere o ancora meglio un numero piuttosto che una stringa)

    nel tuo programma quel '\0' va a sovrascrivere il contenuto puntato dalla variabile che non è più "s", inoltre ti consiglio l'uso di un'altra scanf() al posto della funzione gets() che porta solo problemi

  3. #3
    L'avatar di seneca
    seneca non è connesso Super Moderatore
    Data registrazione
    18-12-2004
    Residenza
    la Città Eterna
    Messaggi
    8,376

    Predefinito

    Hai ragione, ho corretto il codice, ma purtroppo non è quello il problema.
    Dopo aver fatto un'altra correzione, oltre alla tua, ora succede questo:
    1. se decido di non cambiare la frase, il programma termina correttamente;
    2. se decido di personalizzare la frase, non mi permette di immetterla da tastiera, visualizza la frase di "inserisci la nuova frase", poi una riga bianca e termina.

    Non posso usare come dici tu una scanf perchè devo memorizzare una frase contenente anche spazi; cosa posso usare al posto della gets?


    -- Aut Roma Aut Nihil!

  4. #4
    L'avatar di AlexKidd
    AlexKidd non è connesso Altervistiano Junior
    Data registrazione
    09-02-2007
    Messaggi
    516

    Predefinito

    allora usando la gets() devi inviare alla fine della riga il carattere EOF premendo la combinazione CTRL+Z (CTRL+D se sei su linux)

  5. #5
    L'avatar di seneca
    seneca non è connesso Super Moderatore
    Data registrazione
    18-12-2004
    Residenza
    la Città Eterna
    Messaggi
    8,376

    Predefinito

    Forse non mi sono spiegato o forse non ho capito quello che intendi; usando la gets non mi permette di immettere la frase: dico al programma che voglio personalizzare la frase, mi compare la riga "Inserisci la nuova frase" poi invece di farmi scrivere mi inserisce una riga bianca e termina, proponendomi il prompt normale. Sai darmi una spiegazione/soluzione?
    Grazie.


    -- Aut Roma Aut Nihil!

  6. #6
    Guest

    Predefinito

    Non ci manca un getchar(); dopo la gets()?
    Ultima modifica di ngforum : 30-08-2007 alle ore 21.00.40

  7. #7
    L'avatar di seneca
    seneca non è connesso Super Moderatore
    Data registrazione
    18-12-2004
    Residenza
    la Città Eterna
    Messaggi
    8,376

    Predefinito

    Citazione Originalmente inviato da ngforum Visualizza messaggio
    Non ci manca un getchar(); dopo la gets()?
    No; la gets fa tutto da se; la getchar prende un carattere alla volta e allora dovrebbe essere implementata una richiesta iterativa finchè non si incontra il carattere '\0' (infatti ho implementato cosi in quanto segue).

    Purtroppo non sono riuscito a trovare l'inghippo (credo sia nella strcmp ma non ne sono certo, anzi se qualcuno sa dirmi come comparare due stringhe mi fa un piacere!) e ho aggirato il problema.
    Posto il codice commentato ampiamente, se mai dovesse servire a qualcuno in futuro.

    Codice:
    #include <stdio.h>
    #include <string.h> /*necessaria per strlen, strcpy, gets, getchar*/
    #include <stdlib.h> /*necessaria per malloc, free*/
    
    char * cancella(char *str, char c)
    {
       int i, j=0;
       char *app;
       /*con malloc() si riserva uno spazio di memoria necessario per str più 1 e viene
         passato l'indirizzo di inizio ad app; il comando (char*) viene usato per 
         costringere ad avere un puntatore ad un tipo di dato diverso*/
        /*la funzione strlen(s) calcola la lunghezza della stringa s, (inteso come il 
          numero di caratteri dell'array puntato da s) escluso il terminatore '\0'. Il 
          valore di ritorno è il numero di caratteri in s.*/
       app=(char*) malloc(strlen(str)+1);
       /*viene copiato anche il terminatore di stringa*/
       for (i=0; i<= strlen(str); ++i)
          if (str[i]!=c)
             app[j++]=str[i];
       str=(char*) malloc(strlen(app)+1);
       strcpy(str, app);
       /*void free(void *ptr) disalloca lo spazio di memoria puntato da ptr.
         La funzione non ritorna nulla e non riporta errori.*/
       free(app);
       return str;
    }
    
    main()
    {  
       char *s="sschissa se ss s sfunzionassssss";
       printf("La frase da esaminare è: %s\n", s);
       printf("%s\n", cancella(s, 's'));
       
       printf("Prova con una tua nuova frase:\n");
       int i=0;
       char y[100];
       char ch;
       /*getchar ha il compito di leggere un carattere per volta dalla tastiera*/
       while ((ch=getchar())!='\n')
            y[i++]=ch;
            y[i]='\0';
        /*altra versione con la funzione gets che però è sconsigliata per la 
          mancanza di controlli sulla lunghezza della variabile in cui si 
          memorizza il valore
        gets(y);*/
        printf("%s\n", cancella(y, 's'));
    }


    -- Aut Roma Aut Nihil!

  8. #8
    L'avatar di AlexKidd
    AlexKidd non è connesso Altervistiano Junior
    Data registrazione
    09-02-2007
    Messaggi
    516

    Predefinito

    strcmp() va bene le le stringhe da confrontare sono della stessa lunghezza

    non mi sono spiegato bene io, ogni volta che scrivi del testo e premi invio la gets() (e generalmente qualunque chiamata delle librerie standard C che legge dati da input) vede l'input cosi

    "frase\0\n\0"

    la prima gets() legge e restiusce "frase\0" lasciando sullo strem di input "\n\0" letto con un'altra gets() o scanf()

    devi quindi fare una getc() o getchar() come consigliato da ngforum per pulire lo stream

  9. #9
    Guest

    Predefinito

    Seneca hai risolto?

  10. #10
    L'avatar di seneca
    seneca non è connesso Super Moderatore
    Data registrazione
    18-12-2004
    Residenza
    la Città Eterna
    Messaggi
    8,376

    Predefinito

    Citazione Originalmente inviato da ngforum Visualizza messaggio
    Seneca hai risolto?
    No, ieri non ho avuto tempo di provare il vostro suggerimento, spero di farlo nel pomeriggio (dove sono ora non ho linux ).
    Non rispondevo perchè poi sarei stato costretto ad editare e magari non avreste letto.
    Comunque, visto che ci sei, non ho capito di preciso cosa passo alla getchar, come pulisco lo stream (che poi sarebbe y, giusto?)?


    -- Aut Roma Aut Nihil!

  11. #11
    Guest

    Predefinito

    Da quello che mi ricordo basta che metti dopo la gets(stringa);

    getchar();

    senza passargli niente. Potrei sbagliarmi ma io ho sempre fatto così.

  12. #12
    L'avatar di AlexKidd
    AlexKidd non è connesso Altervistiano Junior
    Data registrazione
    09-02-2007
    Messaggi
    516

    Predefinito

    usi linux?

    allora ti avverto che il man è molto chiaro su questo.... gets() è deprecata e spiega cosa usare al posto di quella funzione

  13. #13
    L'avatar di seneca
    seneca non è connesso Super Moderatore
    Data registrazione
    18-12-2004
    Residenza
    la Città Eterna
    Messaggi
    8,376

    Predefinito

    Ho ripreso il programma oggi; grazie ad entrambi per i suggerimenti (hai ragione ngforum per il consiglio sulla getchar) ma dopo varie prove incrociate ho capito che il non corretto funzionamento è dovuto a qualcosa di errato con la strcmp. Ho aggirato il problema e va bene uguale, alla fine non ci voglio perdere troppo tempo...
    Ciao!


    -- Aut Roma Aut Nihil!

Regole di scrittura

  • Non puoi creare nuove discussioni
  • Non puoi rispondere ai messaggi
  • Non puoi inserire allegati.
  • Non puoi modificare i tuoi messaggi
  •