[C] inverti stringa con puntatori

Messaggioda 19stellare92 » 08/12/2018, 11:31

Ciao a tutti, sono alle prese con i puntatori e penso che mi sfugga qualcosa perchè non riesco ad invertire i caratteri (primo con ultimo e cosi via)
facendo dei controlli sul codice (printf) mi stampa il valore nullo. cosa sbaglio?
Non linciatemi perchè non sono riuscito a scrivere il codice secondo regolamento, sono nuovo e ancora non ho capito come si fa,spero che mi rispondiate.

Codice:
#include<stdio.h>
#define DIM 100

main(){

int i,j,count,aux;
char str[DIM];   
char *s;
s=str;

printf("Inserisci una stringa: ");
gets(str);
//conta start
while(*s++!='\0')
i++;   
printf("\nLa stringa è lunga %d",i);   
//conta end
//scambia
for(j=0;j<i/2;j++)
{aux=*(s+j);
*(s+j)=*(s-j+i);
*(s-j+i)=aux;
}
printf("\nStringa reverse %s",str);
}
Ultima modifica di stan il 08/12/2018, 12:14, modificato 1 volta in totale.
Motivazione: Formattato codice sorgente tramite BBCode.
19stellare92
Starting Member
Starting Member
 
Messaggio: 1 di 7
Iscritto il: 08/12/2018, 11:00

Re: [C] inverti stringa con puntatori

Messaggioda Anacleto13 » 08/12/2018, 12:45

Mamma che casino, non so se ti è stato dato come esercizio di contare tutti i caratteri ma esiste il metodo strlen che è più comodo e meno orrendo da vedere, poi usa le funzioni se le hai già fatte, un metodo classico per "ribaltare" le stringhe in genere è così:

Codice:
char *reverseString(char *vecchiaString, char *nuovaString){
    int len = strlen(src);
    for (int i = 0; i<len; i++)
        nuovaString[i] = vecchiaString[len - i - 1];
    nuovaString[len]='\0';
    return nuovaString;
}
Avatar utente
Anacleto13
Junior Member
Junior Member
 
Messaggio: 254 di 257
Iscritto il: 20/03/2017, 19:20

Re: [C] inverti stringa con puntatori

Messaggioda 19stellare92 » 08/12/2018, 13:04

Grazie per la risposta.
Si conosco la funzione strlen non l'ho usata perchè stavo facendo degli esercizi a catena sui puntatori e quello prima di questo era di contare i caratteri senza usare strlen.
Potresti spiegarmi cosa ho sbagliato utilizzando la tecnica di scambio con la variabile di appoggio e soprattutto perchè l'ultima printf mi restituisce la stringa vuota?
Immagino che il tuo metodo sia ottimizzato ma attualmente non mi interessa questo aspetto ma solo imparare ad usare i puntatori.
Non è possibile realizzare questo algoritmo utilizzando solo una variabile stringa,devo per forza usarne due?
19stellare92
Starting Member
Starting Member
 
Messaggio: 2 di 7
Iscritto il: 08/12/2018, 11:00

Re: [C] inverti stringa con puntatori

Messaggioda Obidream » 08/12/2018, 16:21

Anacleto13 ha scritto:Mamma che casino, non so se ti è stato dato come esercizio di contare tutti i caratteri ma esiste il metodo strlen che è più comodo e meno orrendo da vedere, poi usa le funzioni se le hai già fatte, un metodo classico per "ribaltare" le stringhe in genere è così:

Codice:
char *reverseString(char *vecchiaString, char *nuovaString){
    int len = strlen(src);
    for (int i = 0; i<len; i++)
        nuovaString[i] = vecchiaString[len - i - 1];
    nuovaString[len]='\0';
    return nuovaString;
}

A parte le considerazioni sul casino e sulla scelta legittima dell'OP di provare ad implementare una versione "naive" della strlen in realtà quello mostrato non è il metodo classico, invertire una stringa è un'operazione che si può fare senza dover iterare lungo tutta la stringa, basta farlo sino alla metà... Detto questo, una versione coi soli puntatori non dovrebbe richiedere anche l'utilizzo degli indici come, immaginavo più qualcosa del genere:

Codice:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static void swap_ch(char *a, char *b)
{
    char tmp = *a;
    *a = *b;
    *b = tmp;
}

static char *reverse_string(char *s, size_t len)
{
    size_t i;

    for(i = 0; i < (len >> 1) - 1; ++i) {
        swap_ch(&s[i], &s[len - i - 1]);
    }

    return s;
}

static char *reverse_string_ptr(char *s, size_t len)
{
    char *src = s;
    char *end = src + len - 1;
   
    while (end > src) {
        swap_ch(end--, src++);
    }
   
    return s;
}



int main(void)
{
    char s[] = "questa e' una stringa";
   
    size_t len = strlen(s);
   
    puts(s);
    puts(reverse_string_ptr(s, len));
    puts(reverse_string(s, len));


    return EXIT_SUCCESS;
}


Ed usare gets() per leggere una stringa è proprio sbagliato, è stata addirittura rimossa dal C11 e già deprecata nel C99, ma è una funzione che per motivi ignoti continua ad essere usata.
((v & 0xff) && (v & 0xff00) && (v & 0xff0000) && (v & 0xff000000))
Avatar utente
Obidream
Average Member
Average Member
 
Messaggio: 973 di 978
Iscritto il: 07/02/2012, 20:57

Re: [C] inverti stringa con puntatori

Messaggioda Super Squirrel » 08/12/2018, 17:31

Allora...

- la variabile count è inutilizzata;
- non è un errore, ma non sarebbe meglio dichiarare la variabile aux come char?
- quanto vale inizialmente la variabile i?
- a cosa punta s all'uscita del while?
- per come hai impostato il codice la variabile i all'uscita del while dovrebbe essere pari al numero di elementi della stringa escluso il carattere terminatore di stringa \0. Consideriamo la stringa c a n e \0, essendo i=4, per j=0 sarà
*(str+i-j) = *(str+4) = str[4] = \0 ... per questo non ti stampa nulla!
Super Squirrel
Junior Member
Junior Member
 
Messaggio: 322 di 328
Iscritto il: 16/05/2013, 22:05

Re: [C] inverti stringa con puntatori

Messaggioda 19stellare92 » 08/12/2018, 18:25

Innanzitutto ti ringrazio per la risposta Obidream, ho studiato il tuo codice ed ho scoperto alcune cose interessanti,ad esempio che posso usare nella dichiarazione di funzione le stesse variabili usate per i parametri attuali. Questo comporta qualcosa all'interno della memoria?Non mi è chiaro se vengono generate nuove copie o se vengono usate le stesse dei parametri formali.
Per quanto riguarda il gets() ho trovato questa possibilità leggendo nei forum, tu come faresti a creare una stringa composta da piu parole,usi un ciclo?
Quando ti riferisci al fatto che è incasinato il codice intendi che dovrei seguire di piu il tuo stile e quindi per ogni "attività" che voglio realizzare generare una funzione a parte?
Scusa per tutte le domande ma ci tengo davvero a migliorare e mi piacerebbe correggere i miei errori.

Super Squirrel ha scritto:Allora...

- la variabile count è inutilizzata;
- non è un errore, ma non sarebbe meglio dichiarare la variabile aux come char?
- quanto vale inizialmente la variabile i?
- a cosa punta s all'uscita del while?
- per come hai impostato il codice la variabile i all'uscita del while dovrebbe essere pari al numero di elementi della stringa escluso il carattere terminatore di stringa \0. Consideriamo la stringa c a n e \0, essendo i=4, per j=0 sarà
*(str+i-j) = *(str+4) = str[4] = \0 ... per questo non ti stampa nulla!


Grazie Super Squirrel per avermi chiarito il motivo del mio errore, mi stavo scervellando!
Per quanto riguarda la variabile count l'ho introdotta perchè mi serviva per un altro pezzo del programma, invece per quanto riguarda aux c'hai ragione effettivamente dovevo dichiararla come char.
19stellare92
Starting Member
Starting Member
 
Messaggio: 3 di 7
Iscritto il: 08/12/2018, 11:00

Re: [C] inverti stringa con puntatori

Messaggioda Obidream » 08/12/2018, 21:25

19stellare92 ha scritto:Innanzitutto ti ringrazio per la risposta Obidream, ho studiato il tuo codice ed ho scoperto alcune cose interessanti,ad esempio che posso usare nella dichiarazione di funzione le stesse variabili usate per i parametri attuali. Questo comporta qualcosa all'interno della memoria?Non mi è chiaro se vengono generate nuove copie o se vengono usate le stesse dei parametri formali.
Per quanto riguarda il gets() ho trovato questa possibilità leggendo nei forum, tu come faresti a creare una stringa composta da piu parole,usi un ciclo?
Quando ti riferisci al fatto che è incasinato il codice intendi che dovrei seguire di piu il tuo stile e quindi per ogni "attività" che voglio realizzare generare una funzione a parte?
Scusa per tutte le domande ma ci tengo davvero a migliorare e mi piacerebbe correggere i miei errori.

In C le stringhe sono degli array di caratteri null-terminated ( terminate dal carattere \0) pertanto il passaggio ad una funzione avviene sempre per riferimento e non per copia. Tant'è che la seguente funziona modifica direttamente la stringa che gli passi come parametro:

Codice:
static void reverse_string(char *s, size_t len)
{
    size_t i = 0;

    for(i = 0; i < (len >> 1) - 1; ++i) {
        swap_ch(&s[i], &s[len - i - 1]);
    }
}


Comunque non intendevo dire che il tuo codice è incasinato, non mi permetterei di farlo. Ed il mio modo di scrivere il codice non è necessariamente il migliore, è quello che trovo personalmente più leggibile in base a quella che è la mia seppur ridotta esperienza, ma non mi sento di dirti che ad ogni attività deve corrispondere una funzione.
Sebbene l'argomento sia in realtà non banale, in generale è una buona idea usare le funzioni per rendere il codice più leggibile, anziché scrivere tutto nel main, questo si può dire :lol:

Infine, la gets() ha un problema semplice, così come molte funzioni della libreria standard del C per la gestione delle stringhe: non c'è alcun controllo sulla lunghezza della stringa, se tu ne crei una da 20 caratteri e ne inserisci 25 non hai nessun errore apparentemente. È quello che si chiama buffer overflow in gergo tecnico.
Un'alternativa semplice è quella di usare fgets, che permette di leggere anche dallo stdin. L'unica differenza è che include eventualmente anche il \n di quando premi invio, quindi bisogna tenerne conto.
((v & 0xff) && (v & 0xff00) && (v & 0xff0000) && (v & 0xff000000))
Avatar utente
Obidream
Average Member
Average Member
 
Messaggio: 974 di 978
Iscritto il: 07/02/2012, 20:57


Torna a Informatica

Chi c’è in linea

Visitano il forum: apatriarca, Raptorista, Super Squirrel e 8 ospiti