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

davidson

Nuovo Utente
33
5
Codice:
#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
 

Marcus Aseth

Utente Attivo
404
138
OS
Windows 10
Punto 1)
Codice:
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:
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.
 
  • Mi piace
Reazioni: Andretti60

Andretti60

Utente Èlite
6,440
5,091
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.
 
  • Mi piace
Reazioni: Marcus Aseth

davidson

Nuovo Utente
33
5
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.
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
 

davidson

Nuovo Utente
33
5
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
 

Marcus Aseth

Utente Attivo
404
138
OS
Windows 10
Come detto da Andretti sopra, 2 loops.

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)
C++:
while (*next != '\0'){
       *next++ = *(next + 1);
}
 
Ultima modifica:

Andretti60

Utente Èlite
6,440
5,091
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.
 
  • Mi piace
Reazioni: Marcus Aseth

Marcus Aseth

Utente Attivo
404
138
OS
Windows 10
Ben detto, non ci avevo riflettuto su abbastanza :P
Fixed (con l'aggiunta di currentChar-- ):

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;
}
 
  • Mi piace
Reazioni: Andretti60

Marcus Aseth

Utente Attivo
404
138
OS
Windows 10
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)
 
  • Mi piace
Reazioni: Andretti60

Andretti60

Utente Èlite
6,440
5,091
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.
 
  • Mi piace
Reazioni: Marcus Aseth

Andretti60

Utente Èlite
6,440
5,091
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)
Esatto, ecco perche' consigliavo l'uso di un buffer, si usa il doppio della memoria ma fila via molto più liscio.
 
  • Mi piace
Reazioni: Marcus Aseth

Ci sono discussioni simili a riguardo, dai un'occhiata!

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!

Discussioni Simili