Anagrammi

nadia891
Ciao,
ho cercato di fare un esercizio dal libro in cuiconfronta due parole e vede se sono anagrammi o no.
é molto elementare per come è fatto ma ho ancora pochi strumenti per poter fare un programma più bello.
comunque non capisco perchè ogni parole che inserisci mi riporta sempre che sono anagrammi:
#include <stdio.h>

int main (void)

{

int a[26] ={0};


int i;
char ch;


printf("inserisci prima parola:");
ch=getchar();
i=0;
while(ch!='\n'){

if (ch='a')
 i=1;
 
if (ch='b')
 i=2;
if (ch='c')
 i=3;
if (ch='d')
 i=4;
if (ch='e')
 i=5;
if(ch='f')
 i=6;
if(ch='g')
 i=7;
if(ch='h')
 i=8;
if(ch='i')
 i=9;
if(ch='j')
 i=10;
if(ch='k')
 i=11;
if(ch='l')
 i=12;
if(ch='m')
 i=13;
if(ch='n')
 i=14;
if(ch='o')
 i=15;
if(ch='p')
 i=16;
if(ch='q')
 i=17;
if(ch='r')
 i=18;
if(ch='s')
 i=19;
if(ch='t')
 i=20;
if(ch='u')
 i=21;
if(ch='v')
 i=22;
if(ch='w')
 i=23;
if(ch='x')
 i=24;
if(ch='y')
 i=25;
if(ch='z')
 i=26; 

a[i]=a[i]+1;
ch=getchar();
}

printf("inserisci secondo numero:");
ch=getchar();

while(ch!='\n'){

if (ch='a')
 i=1;
 
if (ch='b')
 i=2;
if (ch='c')
 i=3;
if (ch='d')
 i=4;
if (ch='e')
 i=5;
if(ch='f')
 i=6;
if(ch='g')
 i=7;
if(ch='h')
 i=8;
if(ch='i')
 i=9;
if(ch='j')
 i=10;
if(ch='k')
 i=11;
if(ch='l')
 i=12;
if(ch='m')
 i=13;
if(ch='n')
 i=14;
if(ch='o')
 i=15;
if(ch='p')
 i=16;
if(ch='q')
 i=17;
if(ch='r')
 i=18;
if(ch='s')
 i=19;
if(ch='t')
 i=20;
if(ch='u')
 i=21;
if(ch='v')
 i=22;
if(ch='w')
 i=23;
if(ch='x')
 i=24;
if(ch='y')
 i=25;
if(ch='z')
 i=26; 

a[i]=a[i]+1;
ch=getchar();
}

i=0;
for (i=0;i<26;i++){
 if(a[i]!=0)
 break ;
 }if(a[i]!=0)
 printf("sono anagrammi");
 else
 printf("sono anagrammi");
 
 return 0;
 }
 
 
 

Risposte
claudio862
Allora, innanzitutto in C puoi trattare i caratteri (char) come se fossero interi. Questo ti risparmia la valanga di if() che hai scritto, perché i caratteri sono ordinati. Il carattere 'a' vale un certo numero X, 'b' vale X+1, 'c' vale X+2... Il reale valore di X dipende dall'implementazione, però se sottrai ad un carattere il valore di 'a' ottieni un numero tra 0 e 25 *.

char ch = getchar();
    while(ch!='\n') {
    a[ch - 'a'] += 1;
    ch = getchar();
}


A questo punto nell'array a ci sono il numero di lettere contenute nella parola inserita. Esempio "babbeo":
a[0] == 1; // Una lettera 'a'
a[1] == 3; // tre lettere 'b'
a[4] == 1; // Una lettera 'e'
a[14] == 1; // Una lettera 'o'

a[altri valori] == 0; // Non ci sono altre lettere.


Ti serviranno 2 array diversi, uno per la prima parola, uno per la seconda. Se sono uguali significa che le due parole contengono le stesse lettere (possibilmente in ordine diverso), quindi sono una l'anagramma dell'altra.

* In realtà c'è differenza tra maiuscole e minuscole. Quindi dovresti prima convertire tutto in minuscolo.


Un'ultima nota, in C gli indici di un array di dimensione N vanno da 0 a N-1. Tu invece hai fatto

int a[26] = {0};

...

if(ch='a')
    i=1; 

...

if(ch='z')
    i=26; 

a[i] = a[i] + 1; // Se i==26 è sbagliato, l'array va da 0 a 25.


Avrebbe dovuto essere

int a[26] = {0};

...

if(ch='a')
    i=0; 

...

if(ch='z')
    i=25; 

a[i] = a[i] + 1; // Ok, ora 0 <= i <= 25

nadia891
nell'ultima parte ho riportato il confronto ma questa volta ottengo che il risultato è sempre non è un anagramma.
[codefor(i=0;i<26;i++){
printf("%d",a);
if (a!=b){
break;

}
if(a!=b)
printf("non e' anagramma");
else
printf(" e' anagramma");

return 0;
}][/code]

claudio862
for(n=0;n<26;n++){
    printf("%d",a[n]);
    if (a[n]!=b[n]) {
        break;
    }
}

if(a[n]!=b[n])
    printf("non e' anagramma");
else
    printf(" e' anagramma");


Dal ciclo for esci in due modi:
- Se per qualche 0 <= n < 26 si ha che a[n] != b[n]
- Se arrivi alla fine del ciclo, con n = 26

Nel primo caso puoi confrontare a[n] con b[n], che saranno diversi.
Nel secondo caso invece non puoi accedere ad a[n] e b[n], perché n >= 26, è oltre la capacità degli array.

Ti conviene usare un'altra variabile a cui assegni false se ci sono lettere diverse o true se sono uguali.

bool anagramma = true;

for(n=0;n<26;n++){
    printf("%d",a[n]);
    if (a[n]!=b[n]) {
        anagramma = false;
        break;
    }
}

if(anagramma)
    printf("e' anagramma");
else
    printf("non e' anagramma");

nadia891
la domanda sarà stupida ma alla fine del ciclo( cioè in caso siano anagrammi e quindi si controntanoTUTTI i valori dei due vettori) n non sarà 25?(va da 0 a 25 quindi ultimo valore confrontato è questo).
Tra l'altro anche come indicato da te mi ritrovo il problema che tutte le parole sono anagrammi...

claudio862
In un ciclo for:

for (n = 0 ; n < 26; n += 1) {
    // Corpo del ciclo.
}


n = 0 è l'inizializzazione, viene eseguita prima di entrare nel ciclo.

n += 1 viene eseguita al termine di ogni iterazione (n++, n = n+1, n = n+4... qualsiasi istruzione).

n < 26 è la condizione di permanenza nel ciclo, viene controllata al termine di ogni iterazione. Quando n < 26 diventa falsa (cioè n >= 26) si esce dal ciclo.

"Srotolando" il ciclo si ottiene qualcosa del genere:

n = 0;

// Corpo del ciclo.
n +=1; // n = 1
if (n >= 26) // falso
    goto fineCiclo;

// Corpo del ciclo.
n += 1; // n = 2
if (n >= 26) // falso
    goto fineCiclo;

// Corpo del ciclo.
n += 1; // n = 3
if (n >= 26) // falso
    goto fineCiclo;

// Corpo del ciclo.
n += 1; // n = 4
if (n >= 26) // falso
    goto fineCiclo;


...


// Corpo del ciclo.
n += 1; // n = 24
if (n >= 26) // falso
    goto fineCiclo;

// Corpo del ciclo.
n += 1; // n = 25
if (n >= 26) // falso
    goto fineCiclo;

// Corpo del ciclo.
n += 1; // n = 26
if (n >= 26) // finalmente vero!
    goto fineCiclo;



fineCiclo:
// Codice successivo.
// Qua n = 26


Quindi una volta usciti dal ciclo n vale 26 (a meno di non uscire prima usando un break).

claudio862
Questa versione dovrebbe funzionare.

#include <stdio.h>

int main (void)
{
    int a[26] = {0};
    int b[26] = {0};
    char ch;

    printf("Inserisci prima parola (solo lettere minuscole): ");
    ch = getchar();
    while(ch != '\n') {
        a[ch - 'a'] += 1;
        ch = getchar();
    }

    printf("Inserisci seconda parola (solo lettere minuscole): ");
    ch = getchar();
    while (ch != '\n') {
        b[ch - 'a'] += 1;
        ch = getchar();
    }

    int anagrammi = 1;
    for (int i = 0; i < 26; i++){
        if(a[i] != b[i]) {
            anagrammi = 0;
            break;
        }
    }

    if (anagrammi)
        printf("sono anagrammi");
    else
        printf("non sono anagrammi");

    return 0;
}

nadia891
si ma se tolgo il break;
con il break esce che tutte le parole sono anagrammi.

claudio862
Il break è irrilevante, serve solo ad uscire dal ciclo non appena ti accorgi che una lettera compare un numero diverso di volte nelle due parole. Se lo togli vengono sempre controllate tutte le lettere, ma il risultato è lo stesso (se le parole fossero molto lunghe sarebbe un po' più lento).

nadia891
si si sono d'accordo con te infatti non capisco il perchè.
se inserisco il codice con il break non ho il risultato se lo tolgo si ma non trovo il senso non capisco il perchè.

claudio862
Dici il programma che ho postato io? Non mi sembra possibile (comunque ho appena provato e funziona uguale con o senza break). Altrimenti posta il codice esatto.

nadia891
infatti neanche a me sembra possibile.se inserisco il break tutte le parole sono anagrammi se lo tolgo no ho l'esecuzione perfetta..è possibile che il mio compilatore non riesca a riconoscere il break?

nadia891
#include <stdio.h>
#include <stdbool.h>
#include<ctype.h>

int main (void)

{

int a[26] ={0};
int b[6]={0};

int i;
char ch;
bool anagramma= false;

printf("inserisci prima parola:");
ch=getchar();
ch=tolower(ch);

i=0;

    while(ch!='\n') {
    a[ch-'a'] =a[ch-'a']+ 1;
    ch = getchar();
	ch=tolower(ch);
}


printf("inserisci seconda parola:");
ch=getchar();


    while(ch!='\n') {
    b[ch-'a'] =b[ch-'a']+1;
    ch = getchar();
ch=tolower(ch);
}

i=0;


 for(i=0;i<26;i++){
  
  if (a[i]!=b[i])
 anagramma=true;
  break;
}
  if (anagramma)
  printf("non e' anagramma");
  else 
 printf("e' anagramma");
  
   
   
   return 0;
   }

cosi escono tutti anagrammi.

claudio862
Innanzitutto hai dichiarato l'array b da 6 elementi, invece di 26. Inoltre è abbastanza fuorviante impostare "anagramma" false se le parole sono anagrammi e true altrimenti. Dovresti invertire i confronti oppure chiamare quella variabile "nonUnAnagramma".

Il problema però è in questo ciclo:

for(i=0;i<26;i++){
  
  if (a[i]!=b[i])
 anagramma=true;
  break;
}

Che con un'indentazione migliore (e la variabile rinominata) diventa:

for (i = 0; i < 26; i++) {
    if (a[i] != b[i])
        nonUnAnagramma = true;
    break;
}

L'istruzione "nonUnAnagramma = true;" viene eseguita solo se la condizione nell'if è vera, il break viene eseguito sempre. Il che significa che viene controllata solo la prima lettera, poi il ciclo termina subito. Quindi tutte le parole che hanno lo stesso numero di 'a' sono considerate anagrammi.

Raggruppa le istruzioni nei rami degli if, for e while tra parentesi graffe, anche quando non è necessario, per evitare questi errori:

for (i = 0; i < 26; i++) {
    if (a[i] != b[i]) {
        nonUnAnagramma = true;
        break;
    }
}

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