come ti inverto la stringa

salve gente
una domanda al volo
che sappiate esiste una funzione di libreria (o almeno una cosa standard) che mi permette di invertire al volo una stringa (array di caratteri teminati da 0)?
io non ho trovato nulla, sembra essere un esercizio standard per le scuole, ma niente di libreria

beh, un po' ho cercato, ma dopo aver visto cose che voi umani........
ho deciso di scrivermela, e di mettermela nella mia libreria di "piccole funzioni utili"

char * invertistringa(char * stringa)
{
    //inverte una stringa
    byte i = 0;
    byte j = strlen(stringa) - 1;
    char c = 0;

    while (i < j)
    {
        c = stringa[i];
        stringa[i++] = stringa[j];
        stringa[j--] = c;
    }

    return stringa;
}

formalmente restituisce un puntatore a carattere, ma in realtà punta alla stessa stringa di ingresso
volevo provare a fare lo swap senza una variabile temporanea, ma ho pensato che non ne vale la pena
come al solito, se ci vedete dei bacherozzi segnalatemelo, grazie
prossima idea: convertire dei float in stringhe in formato scientifico (esempio 1.234E3 significa 1234)
adesso ci apro un post

Standardoil:
ho deciso di scrivermela, e di mettermela nella mia libreria di "piccole funzioni utili"

Praticamente identica a come la avevo pensata (però io mi sono divertito a provarla in asm Z80, algoritmo identico anche se ovviamente a puntatori).
L'unica perplessità è il valore di ritorno, visto che comunque avviene una modifica in-place della stringa originale, a cosa serve un doppione del suo puntatore?

Lo swap senza variabile di appoggio però mi sembra meno efficiente, soprattutto se si usano indici invece di puntatori.

stringReverse(char * stringa)
{
    char * i = stringa;
    char * j = i + strlen(stringa) - 1;
    while (i < j)
    {
        *i ^= *j;
        *j ^= *i;
        *i ^= *j;
        i++;
        j--;
    }
}
MAIN        LD   HL,STRINGA
            CALL REVERSE
            RET

REVERSE     PUSH HL
            XOR  A          ; A = 0
            LD   BC,0
            CPIR            ; CERCA LO 0
            EX   DE,HL
            DEC  DE 
            DEC  DE         ; DE PUNTA ULTIMO BYTE
            POP  HL         ; HL PUNTA PRIMO BYTE

LOOP        LD   B,H
            LD   C,L
            AND  A          ; CARRY = 0
            SBC  HL,DE
            RET  NC         ; FINE SE DE <= HL
            LD   H,B
            LD   L,C

            LD   B,(HL)     ; SWAP
            LD   A,(DE)
            LD   (HL),A
            LD   A,B
            LD   (DE),A

            INC  HL
            DEC  DE
            JP   LOOP

Azz.... l'una e venti, sono stato colpito anche oggi dalla fascia delle bermuda....

Guardando implementazioni di funzioni stringa una volta sono stato colpito da una strreverse, che scorreva la stringa per metà, se il numero caratteri della stringa è pardi, diviso due fa due parti uguali, se i caratteri sono dispari si fa una divisione tra interi che restituisce solo la parte intera.

Un implementazione diversa che fa la stessa cosa. Esistono tante implementazioni quanti sono i programmatori :slight_smile:

void inverti(char *s){
 
 /* Questa funzione si basa che se il numero caratteri della stringa
    sono pari diviso due fa due parti uguali, se i caratteri sono 
    dispari si tratta di una divisione tra interi per cui restituisce
    solo la parte intera, e il carattere centrale della stringa non viene
    modificato. Il vantaggio che cicla per metà della lunghezza della stringa. */
     int len=strlen(s); 
     int i=0;
     char tmp;
     for(i=0;i<len/2;i++){// Cicla per metà caratteri della stringa
 
         tmp=s[i];
         s[i]=s[len-1-i];
         s[len-1-i]=tmp;
     }//end for

}// end function

Grazie a tutti e due,
per Claudio_ff
purtroppo io no asm, magari... ma non ho mai avuto occasione
bella la fascia oraria.. non la conoscevo
invece la ragione per la quale "restituisco" un puntatore a carattere è molto banale
per fare

Serial.print(invertistringa(s));

invece che

invertistringa(s);
Serial.print(s);

Sì, lo so: è una menata mia....
ma per me l'altra forma sarebbe un obbrobrio, non riucirei a scriverla, mi darebbe un fastidio fisico la tastiera sotto le dita
per lo swap senza variabile ausiliaria: intendevo truccare:

char * invertistringa(char * stringa)
{
    //inverte una stringa

    byte i = 0;
    byte j = strlen(stringa) - 1;
    byte l = j + 1; // riga aggiunta
    // char c = 0;  riga tolta

    while (i < j)
    {
        stringa[l] = stringa[i]; // falsa variabile
        stringa[i++] = stringa[j];
        stringa[j--] = stringa[l]; // falsa variabile
    }
    stringa[l]=0;
    return stringa;
}

per torn24
non ci avevo pensato al for dopo divisione
o forse lo avevo visto ma non ci avevo badato
in effetti mi fermo anch'io al centro della stringa, ma non faccio divisione, ma test esplicito
adesso non saprei quale sia piu' "rapida", magari qualcuno più bravo di me puo' indicarmelo

di nuovo grazie a tutti e due

Claudio_FF:

stringReverse(char * stringa)

{
    char * i = stringa;
    char * j = i + strlen(stringa) - 1;
    while (i < j)
    {
        *i ^= *j;
        *j ^= *i;
        *i ^= *j;
        i++;
        j--;
    }
}

No vabbè ma che figata! Sembra elegantissima ma ti giuro sto anche facendo delle prove e non capisco come funzioni la sostituzione dei caratteri all'interno del while!
Cioè ho capito che sostituisci l'ultimo col primo e così via, ma non capisco come faccia questa operazione a funzionare con lo xor :o

Io lo intuisco, ma non riesco a spiegarlo..

Reversibilità dello XOR (trucchi assembly PIC per risparmiare righe/memoria/registri):

                VAR_A     VAR_B
                 -----------------
                    A         B

VAR_A ^= VAR_B     A^B        B

VAR_B ^= VAR_A     A^B        A  <--- B ^ A^B = A

VAR_A ^= VAR_B      B         A

                    ^
                    | 
     A^B ^ A = B ---'

invece la ragione per la quale "restituisco" un puntatore a carattere è molto banale

Ah, ok, per usarla in modo funzionale... approvato 8)

Standardoil:
invece la ragione per la quale "restituisco" un puntatore a carattere è molto banale

Non vorrei dire una caxxata, ma anche molte funzioni di libreria, anche se modificano la stringa di un parametro, comunque ne fanno anche il ritorno con return. Mi pare.

...azz... la magia dello XOR !!
65 e 71 65 xor 71 = 6 71 xor 6 = 65 65 xor 6 = 71 !!

Claudio_FF:
Reversibilità dello XOR (trucchi assembly PIC per risparmiare righe/memoria/registri):

                VAR_A     VAR_B

-----------------
                    A        B

VAR_A ^= VAR_B    A^B        B

VAR_B ^= VAR_A    A^B        A  <--- B ^ A^B = A

VAR_A ^= VAR_B      B        A

^
                    |
    A^B ^ A = B ---'

Fantastico, grazie mille :wink: :wink:

Grazie anche da parte mia
Intuivo, prima
Adesso è chiaro