Scambiare stringhe in un array

di il
4 risposte

Scambiare stringhe in un array

Buongiorno,

ho un dubbio che spero qualcuno mi possa chiarire: per esercizio devo modificare l'ordine in cui delle stringhe compaiono in un array frastagliato, secondo certi criteri.

Finché ho stringhe di uguale lunghezza tutto ok, nessun problema, ma quando vado a mettere nell'array stringhe di lunghezza diversa giustamente se scambio una stringa con una più lunga questa va a sovrascrivere pezzi di altre stringhe.

La mia domanda è: c'è modo di modificare l'ordine di stringhe di lunghezza diversa senza dover copiare tutto in un altro array? (siccome devo lavorare su stringhe passate da standard input l'array è allocato automaticamente e la funzione realloc non funziona).

I prototipi delle funzioni mi sono dati dall'esercizio e non li posso modificare.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

#define N 100

void treVolte( char *a[], int n ) {
  char **p;
  int conta = 0;

  char *q = malloc(sizeof(a[0]));
  if(q == NULL) {
    printf("Errore");
    return;
  }
  for ( p = a; p < a + n; p++ ) {//conta le stringhe

    int contae = 0;
    char *c;
    c = *p;

    while ( *c ) {//finche il carattere è diverso da \0
      if ( *c == 'e' ) {
        contae++;
      }
      c++;//scorro i caratteri della stringa
    }

    if ( contae >= 3 ) {
      conta++;
    }

    if ( conta == 3 ) {
      strcpy(q, a[0]);
      strcpy(a[0], *p);
      strcpy(*p, q);
      free(q);
      return;
    }
  }
}

int main( int argc, char **argv ) {

  treVolte( argv + 1, argc-1);

  for ( char** p = argv+1; p < argv+argc; p++  )
    printf( "%s ", *p );

  printf( "\n" );
  return 0;
}
Passando per esempio le stringhe:
certamentissimamente signora non vorrei essere scortese posso ripetere le istruzioni

dovrei visualizzare

ripetere signora non vorrei essere scortese posso certamentissimamente le istruzioni

e invece visualizzo

ripetere signora non vorrei essere scortese posso certamentissimamente issimamente imamente
perché giustamente l'array ha ancora in memoria i puntatori vecchi.

Il programma deve scambiare la terza parola con tre 'e' con la prima, come avrete capito.

Grazie

4 Risposte

  • Re: Scambiare stringhe in un array

    E' concettualmente sbagliato il metodo che usi: argv è un array di puntatori ad array di caratteri in sola lettura, non puoi spostare i dati dentro argv.
    Fatti un array di puntatori, ci copi dentro *argv, poi sposti solo i puntatori.
  • Re: Scambiare stringhe in un array

    Andrea Quaglia ha scritto:


    E' concettualmente sbagliato il metodo che usi: argv è un array di puntatori ad array di caratteri in sola lettura, non puoi spostare i dati dentro argv.
    Fatti un array di puntatori, ci copi dentro *argv, poi sposti solo i puntatori.
    Ciao,
    innanzitutto ringrazio per la riposta e mi scuso per il ritardo.

    Ho risolto il problema grazie al tuo suggerimento, nonostante abbia dovuto rifletterci molto per farlo funzionare.

    Inoltre mi resta un dubbio: per far funzionare tutto correttamente ho inizializzato un nuovo puntatore a carattere con una malloc, che poi però non ho potuto liberare proprio perché ho spostato solo il puntatore senza copiare effettivamente i dati (se avessi copiato i dati mi si sarebbe ripresentato il problema di prima).

    E' corretta la cosa?

    NB: Ho provato anche a passare argv stesso alla funzione e va comunque bene, mi puoi spiegare meglio in che senso argv è in sola lettura? E' una convenzione che non vada modificato?
    Più che altro mi sembra che creare un nuovo array di puntatori da passare alla funzione sia un controsenso per l'esercizio stesso, visto che poi la funzione modifica direttamente l'array senza ritornare niente.. magari è impostato male l'esercizio?

    Qui sotto il codice
    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <string.h>
    
    #define N 100
    
    void treVolte( char *a[], int n ) {
      char *q = malloc(sizeof(char*));
      int conta = 0;
      for (int i=0; i<n; i++) {
        int contae = 0;
        char *c;
        c = a[i];
        while ( *c ) {//finche il carattere è diverso da \0
          if ( *c == 'e' ) {
            contae++;
          }
          c++;//scorro i caratteri della stringa
        }
    
        if ( contae >= 3 ) {
          conta++;
        }
    
        if ( conta == 3 ) {
            strcpy(q, a[0]);
            a[0] = a[i];
            a[i] = q;
            return;
        }
      }
    }
    
    int main( int argc, char *argv[] ) {
        int n = argc;
    /*    char *p[n];
    
        for(int i=0; i<n; i++) {
          p[i] = argv[i+1];
        }
    */
        treVolte(argv+1, n);
    
        for ( char** z = argv+1; z < argv+n; z++  )
          printf( "%s ", *z );
    
        printf( "\n" );
    
        return 0;
    }
    
    Grazie
  • Re: Scambiare stringhe in un array

    Sicuro sicuro di aver risolto?

    Comunque ti sei creato dei problemi da solo. Sarebbe bastata una cosa tipo questa:
    
    #include <stdio.h>
    #include <stdlib.h>
    
    char treVolte(char *input){
        char ret = 0;
        while(*input != '\0' && ret < 3){
            if(*input == 'e' || *input == 'E')
                ret++;
            input++;
        }
        return ret;
    }
    
    int main(int argc, char *argv[]){
        if(argc > 1){
            int i, almeno_tre = 0, swap_pos = 1;
            for(i = 1; i < argc; i++){
                if(treVolte(argv[i]) == 3)
                    almeno_tre++;
                if(almeno_tre == 3){
                    swap_pos = i;
                    break;
                }
            }
            printf("%s ", argv[swap_pos]);
            for(i = 2; i < argc; i++)
                if(i == swap_pos)
                    printf("%s ", argv[1]);
                else
                    printf("%s ", argv[i]);                
        }
        return 0;
    }
    
  • Re: Scambiare stringhe in un array

    Weierstrass ha scritto:


    Sicuro sicuro di aver risolto?

    Comunque ti sei creato dei problemi da solo. Sarebbe bastata una cosa tipo questa:
    
    #include <stdio.h>
    #include <stdlib.h>
    
    char treVolte(char *input){
        char ret = 0;
        while(*input != '\0' && ret < 3){
            if(*input == 'e' || *input == 'E')
                ret++;
            input++;
        }
        return ret;
    }
    
    int main(int argc, char *argv[]){
        if(argc > 1){
            int i, almeno_tre = 0, swap_pos = 1;
            for(i = 1; i < argc; i++){
                if(treVolte(argv[i]) == 3)
                    almeno_tre++;
                if(almeno_tre == 3){
                    swap_pos = i;
                    break;
                }
            }
            printf("%s ", argv[swap_pos]);
            for(i = 2; i < argc; i++)
                if(i == swap_pos)
                    printf("%s ", argv[1]);
                else
                    printf("%s ", argv[i]);                
        }
        return 0;
    }
    
    Ciao Weierstrass,

    grazie per la tua risposta:

    La tua soluzione è più bella, tuttavia io il prototipo delle funzioni lo avevo così dall'esercizio e non potevo modificarlo. Inoltre dovevo solo correggere gli errori ma senza stravolgere il programma.

    In ogni caso dalla prova che ho fatto funziona correttamente, anche se mi son rimasti dei dubbi per quanto riguarda il puntatore come dicevo...
Devi accedere o registrarti per scrivere nel forum
4 risposte