Funzione Stringa C

Bazzaz
Salve devo scrivere una funzione che prese due stringhe in ingresso mi restituisce una copia della prima stringa coi caratteri della seconda (se sono presenti) altrimenti sostituisce i caratteri non presenti con spazi bianchi
per esempio se la prima stringa è "dizionario" e la seconda stringa è "din" la stringa risultato dovrebbe essere
"di i n i "

char* elimina_caratteri(char s1[], char s2[]){
	int ls1 = strlen(s1);
	int ls2= strlen(s2);
	char *newStr = (char*) malloc(sizeof(char)*strlen(s1));
	
	for(int i = 0 ; i< ls2; i++){
		
		for(int j = 0; j< ls1; j++){
			//printf("s2[%d] = %c, s1[%d] = %c \n",i,s2[i],j,s1[j]);
			if(s2[j] == s1[i]){
				newStr[i] = s[i];
			}else{
				newStr[i] = ' ';
				}
			}
			
		}
return newStr;
}


ho provato a scrivere il codice sopra scorrendo un carattere alla volta della seonda stringa per poi scorrere la prima stringa e vedere se il carattere c'era in tal caso aggiungerlo alla "nuova stringa" altrimenti aggiungere uno spazio biano,ovviamente non ha funzionato perchè quando sono andato a fare quella printf nel for ho scoperto che :

s2[0] = d, s1[0] = d 
s2[0] = d, s1[1] = i 
s2[0] = d, s1[2] = z 
s2[0] = d, s1[3] = i 
s2[0] = d, s1[4] = o 
s2[0] = d, s1[5] = n 
s2[0] = d, s1[6] = a 
s2[0] = d, s1[7] = r 
s2[0] = d, s1[8] = i 
s2[0] = d, s1[9] = o 
s2[1] = i, s1[0] = d 
s2[1] = i, s1[1] = i 
s2[1] = i, s1[2] = z 
s2[1] = i, s1[3] = i 
s2[1] = i, s1[4] = o 
s2[1] = i, s1[5] = n 
s2[1] = i, s1[6] = a 
s2[1] = i, s1[7] = r 
s2[1] = i, s1[8] = i 
s2[1] = i, s1[9] = o 
s2[2] = n, s1[0] = d 
s2[2] = n, s1[1] = i 
s2[2] = n, s1[2] = z 
s2[2] = n, s1[3] = i 
s2[2] = n, s1[4] = o 
s2[2] = n, s1[5] = n 
s2[2] = n, s1[6] = a 
s2[2] = n, s1[7] = r 
s2[2] = n, s1[8] = i 
s2[2] = n, s1[9] = o

anche se trovavo un carattere continuava a scorrere perciò lo aggiungeva e poi toglieva

ho provato a sbatterci la testa per un po ma non mi è venuto in mente niente, sapete darmi una mano

Risposte
Umby2
newStr[i] = s[i];


questa istruzione, non dovrebbe essere :??

newStr[i] = s1[i];

vict85
Prima di poter dire che non hai trovato un carattere, devi scorrere tutta s2 (o usare metodi più intelligenti per fare le ricerche) e una volta trovato devi fermare la ricerca.

apatriarca
Il problema del tuo ciclo è che scrivi più volte su ogni valore. Devi invece scrivere il valore solo dopo aver visitato la seconda stringa per sapere se il valore è presente o meno. Prova a scrivere la tua funzione facendo invece uso di una funzione di supporto come strchr.

Super Squirrel
Ciao

Innanzitutto ti sei dimenticato di un piccolo dettaglio che rende una stringa diversa da un generico array di caratteri: il carattere terminatore di stringa \0. Occhio quindi anche alla malloc() visto che la funzione strlen() ritorna il numero di caratteri escluso \0.

Per quanto riguarda la parte dei due cicli for innestati mi tocca dirti, oltre al fatto che quell'algoritmo ha poco senso, che hai fatto anche una grandissima confusione con gli indici.

L'esercizio può essere svolto in vari modi, tra cui quello che ti è stato proposto nei precedenti post. In ogni caso volendo conservare la tua impostazione ti basterebbe:
- inizializzare opportunamente newStr;
- rimuovere l'else;
- aggiustare gli indici.

vict85
Come detto esistono molti modi, tutte variazioni del modo in cui si cerca il valore nella seconda. Si può implementare la funzione cerca a mano o usare la versione stardard strchr. Una alternativa, sempre usando lo stardard, è la coppia strscpn e strspn.

Puoi anche salvare i caratteri della seconda stringa in qualche struttura dati (equivalenti ad un insieme). Puoi usare alberi di ricerca, la stringa ordinata (con ricerca binaria) o persino implementare una hash table rudimentale utilizzando un array della dimensione appropriata (a seconda delle ipotesi può essere grande come le lettere a-z oppure come l'intero insieme dei caratteri). Se fosse C++ potresti anche usare le versioni standard di queste strutture dati.

Bazzaz
"vict85":
Prima di poter dire che non hai trovato un carattere, devi scorrere tutta s2 (o usare metodi più intelligenti per fare le ricerche) e una volta trovato devi fermare la ricerca.


Intanto grazie a tutti dei consigli

La frase "trovare modi intelligenti" mi ha dato un' idea

char* elimina_caratteri(char s1[], char s2[]){
	int ls1 = strlen(s1);
	int ls2= strlen(s2);
	char *newStr = (char*) malloc(sizeof(char)*strlen(s1));
	//printf("s2[%c] , s1[%ss]  \n",s2,s1);
	int trovato = 0;
	for(int i = 0 ; i< ls1; i++){
		
		for(int j = 0; j< ls2; j++){
			//printf("s2[%d] = %c, s1[%d] = %c \n",i,s2[i],j,s1[j]);
			if(s1[i] == s2[j]){
			trovato = 1;
			continue;
			}
			}
			if(trovato == 1){
				newStr[i] = s1[i];
				}else{
					newStr[i] =' ';
					}
					trovato = 0;
			
		}
return newStr;
}


Non so se è intelligente o meno ma funziona, praticamente uso una variabile per segnare che ho trovato il carattere che cercavo, se l trovo la inizializzo a uno dopodichè fermo il ciclo più interno con "continue" nel ciclo più esterno faccio le dovute sostituzioni e reinizializzo la variabile trovato a 0 cosi se non trovo il carattere rimarrà a zero quindi andrò ad inserire uno spazio.


che ne pensate? poteva essere fatto in un modo più "bello"?

Super Squirrel
"Bazzaz":

Intanto grazie a tutti dei consigli

Di niente, ma non mi sembra che tu li abbia letti attentamente:
"Super Squirrel":

Innanzitutto ti sei dimenticato di un piccolo dettaglio che rende una stringa diversa da un generico array di caratteri: il carattere terminatore di stringa \0. Occhio quindi anche alla malloc() visto che la funzione strlen() ritorna il numero di caratteri escluso \0.


"Bazzaz":
che ne pensate? poteva essere fatto in un modo più "bello"?

Indentandolo meglio sarebbe sicuramente più carino! :D
Scherzi a parte, l'approccio in questo caso è corretto, ma ti faccio notare che l'istruzione continue non interrompe il ciclo, ma solo l'iterazione corrente, cosa peraltro inutile visto la posizione in cui l'hai inserita. Forse intendevi utilizzare l'istruzione break?!

In ogni caso con
"Super Squirrel":

volendo conservare la tua impostazione ti basterebbe:
- inizializzare opportunamente newStr;
- rimuovere l'else;
- aggiustare gli indici.

intendevo qualcosa del genere:
    ...
    memset(newStr, ' ', ls1);
    for(int i = 0 ; i < ls2; ++i)
    {
        for(int j = 0; j < ls1; ++j)
        {
            if(s1[j] == s2[i])
            {
                newStr[j] = s1[j];
            }
        }
    }
    ...

vict85
Non ti vedo settare con '\0' la fine della stringa (e devi allocare un elemento in più per quello).

Non l'ho provato, ma senza usare le funzioni standard, una implementazione normale è la seguente:
char*
elimina_caratteri( char s1[], char s2[] )
{
    int ls1 = strlen( s1 );
    char* newStr = (char*)malloc( sizeof( char ) * ( ls1 + 1) );
    if ( !newStr )
    {
        return newStr;
    }

    for ( int i = 0; i < ls1; i++ )
    {
        newStr[ i ] = ' ';
        for ( char* s = s2; s != '\0'; s++ )
        {
            if ( *s == s1[ i ] )
            {
                newStr[ i ] = *s;
                break;
            }
        }
    }
    newStr[ ls1 ] = '\0';
    return newStr;
}

e non era quello che intendevo con intelligente.

Con intelligente intendevo qualcosa come questo (non ho provato a compilarlo e lanciarlo):
char*
elimina_caratteri( char s1[], char s2[] )
{
    int set[ CHAR_MAX - CHAR_MIN + 1 ] = { 0 };
    for ( char* s = s2; s != '\0'; s++ )
    {
        set[ *s - CHAR_MIN ]++;
    }

    int ls1 = strlen( s1 );
    char* newStr = (char*)malloc( sizeof( char ) * ( ls1 + 1 ) );
    if ( !newStr )
    {
        return newStr;
    }

    for ( int i = 0; i < ls1; i++ )
    {
        newStr[ i ] = ( set[ s1[ i ] - CHAR_MIN ] != 0 ) ? s1[ i ] : ' ';
    }
    newStr[ ls1 ] = '\0';
    return newStr;
}

Super Squirrel
"vict85":

(non ho provato a compilarlo e lanciarlo)

Nelle condizioni dei cicli for ti sei dimenticato di dereferenziare s.

vict85
"Super Squirrel":
[quote="vict85"]
(non ho provato a compilarlo e lanciarlo)

Nelle condizioni dei cicli for ti sei dimenticato di dereferenziare s.[/quote]

:smt023 Sì, hai ragione.

Bazzaz
Grazie ancora, purtroppo nell'esercizio era richiesto di non usare alcuna funzione del C come strchr, ma di fare tutto a mano, riguardo.

char* newStr = (char*)malloc( sizeof( char ) * ( ls1 + 1) )

per aggiungere l' "\0" alla fine perchè si fa?

Super Squirrel
"Bazzaz":
per aggiungere l' "\0" alla fine perchè si fa?

Come fa secondo te, per esempio, la funzione strlen() a calcolare la lunghezza di una stringa a partire solamente da un puntatore?

Anzi, visto che hai detto di dover fare tutto a mano, perchè non provi ad implementare una tua versione della funzione strlen()?

vict85
I miei codici non usano alcuna funzione standard che tu non abbia usato nel tuo codice. Devi solo applicare la correzione segnalata da Super Squirrel. Detto questo, dovresti riguardarti un po' di teoria: il terminatore di stringa lo devi capire bene se vuoi imparare a fare questo tipo di esercizi.

P.S.: sizeof(char) è sempre uguale a 1.

Bazzaz
"vict85":
I miei codici non usano alcuna funzione standard che tu non abbia usato nel tuo codice. Devi solo applicare la correzione segnalata da Super Squirrel. Detto questo, dovresti riguardarti un po' di teoria: il terminatore di stringa lo devi capire bene se vuoi imparare a fare questo tipo di esercizi.

P.S.: sizeof(char) è sempre uguale a 1.


Eh a scuola faremo il C l'anno prossimo, e lo sto studiando per conto mio, in effetti però sto "saltando" un po la teoria e provando più un approccio pratico facendo quanti più esercizi possibili dove riesco a trovarli infatti sono andato a fare delle ricerche e ho capito i suggerimenti che mi avete dato

vict85
Se questo è il tuo primo linguaggio di programmazione, ti consiglio di non saltare troppo.

Bazzaz
"vict85":
Se questo è il tuo primo linguaggio di programmazione, ti consiglio di non saltare troppo.


No ho già fatto python il primo anno ora stiamo facendo Javascript e PHP l'anno prossimo il C, solo che con python a scuola è stata quasi tutta teoria e quando ci davano un problema un po più "intricato" dove bisognava usare qualche stratagemma per arrivare alla soluzione ci trovavamo sempre in difficoltà perchè non avevamo la manualità diciamo, e degli amici che ho al 5 anno mi hanno consigliato di fare tanta tanta pratica.
(per dire le verifiche ce le fanno fare su carta e poi ce le fanno provare al computer dopo che il prof le ha viste se vanno bene prendi i punti pieni altrimenti niente xD però per fortuna in python era tutto semplice qui la vedo un po più dura perciò sto provando a fare così)

vict85
Certo, fare pratica è importante. Però ci sono differenze importanti tra python e C, e devi esserne consapevole quando sviluppi nei due linguaggi.

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.