[PROBLEMA] rimozione caratteri desiderati di una stringa tramite un array di caratteri

Discussione in 'Programmazione' iniziata da davidson, 6 Dicembre 2017.

  1. davidson

    • Utente Binario

    Dal:
    12 Novembre 2017
    Messaggi:
    24
    Mi Piace Ricevuti:
    4
    Specifiche Hardware
    Codice (Text):
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>

        void rimuovi_caratteri(char *c);


        void rimuovi_caratteri(char *c)
    {
        char ch[10]= ".;][}{()";

        char *chr;

        char *deletech;


        //sto passando a deletech il contenuto di 'c' che sarebbe l'indirizzo di memoria del primo elemento dell'array nel main//

        deletech = c;


    //  passo al puntatore a caratteri l'indirizzo di memoria del primo elemento dell'array ch[10]//
    //
        chr = ch;


        char *b;

    // passo a b il contenuto di c che sarebbe l'indirizzo di memoria del primo elemento dell'array nel main //

        b = c;

        //potevo anche scrivere  while (*c) era la stessa cosa//
       

        while(*c != '\0' && *chr !='\0')
       
        {
            if(*c == *chr)

            {

                c++;
                deletech++;
                chr++;
                *deletech = *c;
               
               
            }




               
                *deletech = *c;
               
                deletech++;
               
                c++;
       
        }

            *deletech = '\0';



    }

                    int main()

                {  
                    char stringa[7] = "c[) iao";

                    int i;

                    int dim;


                    dim = strlen(stringa);

                    for(i=0;i<dim;i++)

                    {

                    printf(" %c",stringa[i]);

                    }
                   
                    printf("\n");

                    printf("la dimensione della stringa %d\n",dim);

                    rimuovi_caratteri(stringa);

                    for(i=0;i<dim;i++)
                    {

                    printf(" %c",stringa[i]);

                    }

                    printf("\n");

                    return 0;
                }
     
    quello che mi servirebbe è eliminare dall'array char stringa nel main i caratteri presenti nell'array ch, l'ho compliato e mi stampa la stessa stringa senza rimuovere i caratteri desiderati
     
  2. Marcus Aseth

    • Utente Binario

    Dal:
    17 Aprile 2010
    Messaggi:
    258
    Mi Piace Ricevuti:
    53
    Specifiche Hardware
    Punto 1)
    Codice (Text):
    void rimuovi_caratteri(char *c);


    void rimuovi_caratteri(char *c)
    {
    La dichiarazione non ti serve se definisci la funzione subito dopo. Scrivere la dichiarazione della funzione in alto si usa solo quando vuoi definire la funzione sotto il blocco di main().

    Punto 2)
    Codice (Text):
    char stringa[7] = "c[) iao";
    ti serve array di dimensione 8 per lo \0 finale.

    Punto 3)
    non stai mai avanzando chr percui stai sempre testando contro il primo elemento, il punto, ed anche se metti un punto nella stringa di prova e lo rileva correttamente, non stai facendo nulla per rimuoverlo.
    Insomma una serie di errori logici. Continua a ragionarci :)

    PS: il modo in cui hai introdotto una serie di variabili uguali ad altre senza motivo apparente è terribile, non aggiunge nulla di utile e rende solo piu difficile ragionare su cosa il tuo codice sta facendo, sia per te che per chi lo legge.
     
    A Andretti60 piace questo elemento.
  3. Andretti60

    • Utente Binario

    Dal:
    1 Febbraio 2011
    Messaggi:
    1.976
    Mi Piace Ricevuti:
    1.462
    Specifiche Hardware
    Hai bisogno di due loop, uno esterno per ogni carattere del vettore in ingresso, e per ognuno di questi caratteri usa un loop interno per tutti i caratteri del vettore contenente i caratteri da eliminare.
    Stai inoltre attento, quando cancelli un carattere o sposti tutti i successivi di una posizione, oppure usa un buffer per memorizzare i caratteri da tenere, e alla fine copia tale buffer nel vettore passato come parametro, oppure lascia tale vettore inalterato e ritorna il puntatore del nuovo vettore. Ci sono vantaggi e svantaggi di entrambi i metodi.
    Ci sono inoltre un sacco di metodi nella libreria string standard che operano su stringhe, tipo trovare l'indizio del primo elemento di un carattere, le puoi usare come alternativa, una volta che hai imparato il metodo "diretto" (ossia non usando nessuna libreria, solo puntatori).
    Ultimo consiglio, impara a usare il debugger, esegui una operazione per volta, o un gruppo di operazioni, e stampa i valori delle stringhe a quel punto, aiuta tantissimo a risolvere casi come questo.

    Piccolo consiglio: chiama le tue variabili in un modo più esplicito, 'c' non vuole dire nulla :) il codice che hai scritto e' illeggibile.
     
    A Marcus Aseth piace questo elemento.
  4. davidson

    • Utente Binario

    Dal:
    12 Novembre 2017
    Messaggi:
    24
    Mi Piace Ricevuti:
    4
    Specifiche Hardware
    Grazie ad entrambi , la prossima volta cercherò di dare un giusto nome alle variabili,
     
  5. Andretti60

    • Utente Binario

    Dal:
    1 Febbraio 2011
    Messaggi:
    1.976
    Mi Piace Ricevuti:
    1.462
    Specifiche Hardware
  6. davidson

    • Utente Binario

    Dal:
    12 Novembre 2017
    Messaggi:
    24
    Mi Piace Ricevuti:
    4
    Specifiche Hardware
    Rivedendo quello che hai scritto non ho capito quello che dovrei fare esattamente ,cioè faccio il while fino al carattere /0 con il puntatore che punta all'indirizzo di memoria del primo elemento dell'array di caratteri che termina con /0 n presente nel main che contiene i caratteri che andrò poi ad eliminare, ho pensato di creare un altro array che contenga questi caratteri da eliminare
    Allora ho pensato di usare un secondo puntatore che punta allo stesso indirizzo di memoria del primo puntatore,
    Poi faccio dentro il primo while fino a /0 uno ciclo for che che va a confrontare l'iesimo elemento dell'array che contiene i caratteri da rimuovere esempio : array[n]="()[]{}" con il primo puntatore deferenziato che accede al contenuto del primo elemento dell'array del main se è uguale incremento il primo puntatore e ,passo al secondo puntatore il contenuto dell'elemento in cui punta il primo puntatore dopo l'incremento, poi incremento il secondo puntatore e dopo di nuovo il primo puntatore poi non so che fare.. prima ho lavorato su carta disegnando i 2 array e i 1 puntatori e vedere cosa succedeva, se dovevo gestire solo un carattere esempio lo spazio non usavo un altro array nel confronto ma nella condizione dopo il while(*arraymain !='\0')
    facevo un if(*arraymain ==' ')
    arraymain++;
    e facevo i vari passaggi con il secondo puntatore che puntava allo stesso elemento del puntatore *arraymain
    Ma ora niente, ho provato di tutto, senza l'utilizzo di funzioni già predisposte non mi viene niente in mente, volevo allenarmi nel ragionamento all'uso minuzioso dei puntatori
     
  7. davidson

    • Utente Binario

    Dal:
    12 Novembre 2017
    Messaggi:
    24
    Mi Piace Ricevuti:
    4
    Specifiche Hardware
    Quando torno casa posto il codice funzionante che rimuove solo il carattere spazio,mi piacerebbe vedere se si può implementare la funzione per un set di caratteri considerati
     
  8. Marcus Aseth

    • Utente Binario

    Dal:
    17 Aprile 2010
    Messaggi:
    258
    Mi Piace Ricevuti:
    53
    Specifiche Hardware
    Come detto da Andretti sopra, 2 loops.

    Codice (C++):
    #include <iostream>
    using namespace std;
    int main()
    {
        char word[] = "Hell.o W@orld";
        char badSymbols[] = ".@[]{}()";

        //controlla ogni caratter
        for (char* currentChar = word; *currentChar != '\0' ; currentChar++)
        {   //controlla contro ogni simbolo
            for (char* symbol = badSymbols; *symbol != '\0'; symbol++)
            {
                //se un carattere indesiderato viene trovato
                if (*currentChar == *symbol) {
                    //rimuovilo
                    char* next = currentChar;
                    while (*next != '\0') {
                        *next = *(next + 1);
                        next++;
                    }
                }
            }
        }

        for (char* ch = word; *ch != '\0'; ch++){
            cout << *ch;
        }

        return 0;
    }
     
    nel codice che rimuove, puoi anche risparmiare una linea scrivendo questo (anzichè next++ in una linea separata)
    Codice (C++):

    while (*next != '\0'){
           *next++ = *(next + 1);
    }
     
    #8 Marcus Aseth, 7 Dicembre 2017 alle 22:13
    Ultima modifica: 7 Dicembre 2017 alle 22:21
  9. Andretti60

    • Utente Binario

    Dal:
    1 Febbraio 2011
    Messaggi:
    1.976
    Mi Piace Ricevuti:
    1.462
    Specifiche Hardware
    ci sei quasi.
    Il problema e' quando rimuovi un carattere quando ritorni nel loop esterno non devi incrementare 'currentChar' perché hai spostato i caratteri all'interno del vettore 'word'. I cicli loop vanno bene quando NON si modificano gli elementi dei vettori, altrimenti sono dolori. Ti consiglio all'inizio di lasciare i vettori iniziali inalterati, e usare un buffer, e' il modo più sicuro altrimenti impazzisci. Altra nota: quando rimuovi un carattere devi forzare l'uscita dal loop interno, inutile continuare.
     
    A Marcus Aseth piace questo elemento.
  10. Marcus Aseth

    • Utente Binario

    Dal:
    17 Aprile 2010
    Messaggi:
    258
    Mi Piace Ricevuti:
    53
    Specifiche Hardware
    Ben detto, non ci avevo riflettuto su abbastanza :P
    Fixed (con l'aggiunta di currentChar-- ):

    Codice (CSS):
    #include <iostream>
    using namespace std;
    int main()
    {
        char word[] = "Hell.o W@orld";
        char badSymbols[] = ".@[]{}()";

        //controlla ogni caratter
        for (char* currentChar = word; *currentChar != '\0' ; currentChar++)
        {   //controlla contro ogni simbolo
            for (char* symbol = badSymbols; *symbol != '\0'; symbol++)
            {
                //se un carattere indesiderato viene trovato
                if (*currentChar == *symbol) {
                    //rimuovilo
                    char* next = currentChar;
                    while (*next != '\0') {
                        *next++ = *(next + 1);
                    }
                    currentChar--;
                    break;
                }
            }
        }

        for (char* ch = word; *ch != '\0'; ch++){
            cout << *ch;
        }

        return 0;
    }
     
     
    A Andretti60 piace questo elemento.
  11. Marcus Aseth

    • Utente Binario

    Dal:
    17 Aprile 2010
    Messaggi:
    258
    Mi Piace Ricevuti:
    53
    Specifiche Hardware
    By the way, ti stavo soltanto mostrando come usare i due for loop, non prendere esempio per il resto xD
    Perchè mi pare abbastanza inefficiente, visto che ogni volta che trova un simbolo sta ricopiando tutto ciò che viene dopo (immagina se ogni volta che trovi un punto in un documento ri-copi tutto il resto decine o centinaia di volte)
     
    A Andretti60 piace questo elemento.
  12. Andretti60

    • Utente Binario

    Dal:
    1 Febbraio 2011
    Messaggi:
    1.976
    Mi Piace Ricevuti:
    1.462
    Specifiche Hardware
    Mi sembra vada bene, anche se di regola non si dovrebbe mai modificare un contatore o un puntatore all'interno di un loop più di una volta, specialmente se lo si fe dentro un inserì loop, il codice diventa illeggibile e poco mantenibile.
    Una piccola nota sulla tua istruzione

    *next++ = *(next + 1);

    e' una cosa che i programmatori C cercano di starne alla larga il più possibile, ossia usare lo stesso contatore all'interno di una istruzione dove quel contatore viene incrementato o decrementato. I risultati sono imprevedibili, in quanto non si sa se il puntatore viene modificato prima o dopo che venga utilizzato le altre volte. E anche se lo sa, si corre il rischio che non funzioni usando un altro compilatore, e mette in crisi un programmatore che legge quel codice. Molto meglio la tua prima soluzione. A volte eliminare una riga di codice non vale la pena.
     
    A Marcus Aseth piace questo elemento.
  13. Andretti60

    • Utente Binario

    Dal:
    1 Febbraio 2011
    Messaggi:
    1.976
    Mi Piace Ricevuti:
    1.462
    Specifiche Hardware
    Esatto, ecco perche' consigliavo l'uso di un buffer, si usa il doppio della memoria ma fila via molto più liscio.
     
    A Marcus Aseth piace questo elemento.
  14. Marcus Aseth

    • Utente Binario

    Dal:
    17 Aprile 2010
    Messaggi:
    258
    Mi Piace Ricevuti:
    53
    Specifiche Hardware
    Concordo, ho citato la cosa più per mostrargli una cosa che suppongo non sappia, ma non piace neppure a me una linea di codice simile xD
     
  15. davidson

    • Utente Binario

    Dal:
    12 Novembre 2017
    Messaggi:
    24
    Mi Piace Ricevuti:
    4
    Specifiche Hardware
    grazie ad entrambi ora ho idee più chiare
     
    A Andretti60 piace questo elemento.

Condividi questa Pagina