Programma Codice Segreto C++

di il
8 risposte

Programma Codice Segreto C++

Salve ragazzi, ho preso un problema dalle olimpiadi del 2005.
Il problema dice:
Chicco e Spillo comunicano con dei messaggi scritti in codice per non essere scoperti. Il loro codice funziona così: ogni vocale è rappresentata con la vocale successiva in ordine alfabetico, e ogni consonante con la consonante successiva. La Y, che è l’ultima vocale, è rappresentata in
codice dalla A, che è la prima vocale. Allo stesso modo, la Z è rappresentata in codice dalla B.
Per le cifre il discorso è simile: ogni cifra è rappresentata dalla successiva, e 9 è rappresentato da 0.
Il codice mantiene la distinzione maiuscole/minuscole. Gli spazi e i segni d’interpunzione (compresi gli accenti) non sono modificati dal codice segreto.
Aiutiamo Chicco e Spillo scrivendo un programma per codificare i loro messaggi!

Dati di input
Il file input.txt contiene un intero N nella prima riga. Le successive N righe contengono del testo in chiaro, con al più 80 caratteri per riga.

Dati di output
Il programma, leggendo il file di input, deve scrivere in output N righe contenenti il corrispondente testo in codice.

Assunzioni
- Il testo in input è composto soltanto da lettere, cifre e segni d'interpunzione. Non ci sono caratteri accentati al posto degli accenti, si usano gli apostrofi.
- Ogni riga di testo contiene al più 80 caratteri in formato ASCII.
- L'alfabeto è quello esteso a 26 lettere. Le vocali sono A E I O U Y.

Ho fatto quindi questo programma:

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <ctype.h>
using namespace std;

char codice[26]={
	'E', //A
	'C', //B
	'D', //C
	'F', //D
	'I', //E
	'G', //F
	'H', //G
	'J', //H
	'O', //I
	'K', //J
	'L', //K
	'M', //L
	'N', //M
	'P', //N
	'U', //O
	'Q', //P
	'R', //Q
	'S', //R
 	'T', //S
	'V', //T
	'Y', //U
	'W', //V
	'X', //W
	'Z', //X
	'A', //Y
	'B', //Z
};

int main(int argc, char** argv) {
	int s;
	char c;
	fstream inp,outp;
	inp.open("input.txt",ios::in);
	outp.open("output.txt",ios::out);
	
	if(!inp){
		cout<<"File non trovato!\n";
	}
	
	while(!inp.eof()){
		s=0;
		inp.get(c);
		
		if(isalpha(c)){
			if(islower(c)){
				s=32;
			}
			c=codice[toupper(c)-'A']+s;
		}
		
		else if(isdigit(c)){
			if(c<57){
				c++;
			}
			else{
				c='0';
			}
		}
		
		outp<<c;
	}
	
	inp.close();
	outp.close();
	
	return 0;
}

Il problema me lo dà all'ultimo carattere: se la frase è "Ciao", in output ho "Doeuy".
Se notate, la o viene prima correttamente convertita in u, ma a quanto pare la stessa u viene in seguito presa e convertita in y. Secondo voi dov'è il problema?

8 Risposte

  • Re: Programma Codice Segreto C++

    Ciao, ho provato il tuo codice ma a me funziona correttamente. Nel file input.txt ho inserito solo la parola "Ciao" (senza virgolette) e nel file output.txt ho trovato
    
    Doeu
    
    
    con una riga bianca alla fine del file, però nessuna 'y'. Sicuro che a te presenti quel comportamento?

    Comunque, per divertimento, ho provato a riscrivere il programma in un modo che utilizza più funzioni. Se ti va puoi dare un'occhiata e provare a vedere se ti è chiaro...
    
    #include <iostream>
    #include <fstream>
    #include <cstdlib>
    #include <ctype.h>
    using namespace std;
    
    bool isVocale(char c);
    char cifraCarattere(char c);
    char cifraConsonante(char c);
    char cifraVocale(char c);
    char cifraNumero(char c);
    
    
    char consonanti[]={'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'z'};
    char vocali[]={'a', 'e', 'i', 'o', 'u', 'y'};
    char numeri[]={'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
    
    int main(int argc, char** argv)
    {
       char c;
       bool maiuscolo;
       fstream inp,outp;
       inp.open("input.txt",ios::in);
       outp.open("output.txt",ios::out);
       
       if(!inp)
       {
          cout<<"File non trovato!\n";
       }
       
       while(!inp.eof())
       {
          inp.get(c);
          
          if(isalnum(c))
          {
          	if(isupper(c)) maiuscolo = true;
          	else maiuscolo = false;
          
          	c = tolower(c);
            c=cifraCarattere(c);
            if(maiuscolo) c = toupper(c);
          }
          
          outp<<c;
       }
       
       inp.close();
       outp.close();
       
       return 0;
    }
    
    
    bool isVocale(char c)
    {
    	if(c=='a' || c=='e' || c=='i' || c=='o' || c=='u' || c=='y') return true;
    	return false;
    }
    
    
    char cifraCarattere(char c)
    {
    	if(isVocale(c)) return cifraVocale(c);
    	else if(isdigit(c)) return cifraNumero(c);
    	return cifraConsonante(c);
    }
    
    
    char cifraConsonante(char c)
    {
    	for(int i=0; i<20; i++)
    	{
    		if(consonanti[i] == c)
    		{
    			if(i<19) return consonanti[i+1];
    			return consonanti[0];
    		}
    	}
    	return '0';		/* inutile: elimina un warning */
    }
    
    
    char cifraVocale(char c)
    {
    	for(int i=0; i<6; i++)
    	{
    		if(vocali[i] == c)
    		{
    			if(i<6) return vocali[i+1];
    			return vocali[0];
    		}
    	}
    	return '0';		/* inutile: elimina un warning */
    }
    
    
    char cifraNumero(char c)
    {
    	for(int i=0; i<10; i++)
    	{
    		if(numeri[i] == c)
    		{
    			if(i<10) return numeri[i+1];
    			return numeri[0];
    		}
    	}
    	return '0';		/* inutile: elimina un warning */
    }
    
  • Re: Programma Codice Segreto C++

    Ciao, sì a me dà proprio "doeuy"...
    Comunque ho guardato il tuo codice, praticamente è una versione più complessa, mi è tutto chiaro.. Il problema è che dà doeuy pure col tuo A sto punto non è più un problema di codice
  • Re: Programma Codice Segreto C++

    Molto strano! A me funziona correttamente, come puoi vedere dall'immagine:



    Sicuro che il file di input contenga solo "Ciao", senza linee vuote o altro? Prova a cancellare anche output.txt e a rifare tutto.
  • Re: Programma Codice Segreto C++

    Fatto, non c'è verso..
  • Re: Programma Codice Segreto C++

    Il problema è nel get ed il carattere di fine riga, devi verificare dopo la lettura che sia un valore valido. Prova così:
    #include <iostream>
    #include <fstream>
    #include <cstdlib>
    #include <ctype.h>
    using namespace std;
    
    char codice[26] = {
    	'E', //A
    	'C', //B
    	'D', //C
    	'F', //D
    	'I', //E
    	'G', //F
    	'H', //G
    	'J', //H
    	'O', //I
    	'K', //J
    	'L', //K
    	'M', //L
    	'N', //M
    	'P', //N
    	'U', //O
    	'Q', //P
    	'R', //Q
    	'S', //R
    	'T', //S
    	'V', //T
    	'Y', //U
    	'W', //V
    	'X', //W
    	'Z', //X
    	'A', //Y
    	'B', //Z
    };
    
    int main(int argc, char** argv) {
    	int s;
    	char c;
    	fstream inp,outp;
    	inp.open("input.txt",ios::in);
    	outp.open("output.txt",ios::out);
       
    	if(!inp) {
          cout<<"File non trovato!\n";
          return 0;
    	}
       
    	while(inp.good()){
    		s = 0;
    		inp.get(c);
          
    		if (inp.good()) {
    			if(isalpha(c)){
    				if(islower(c))
    					s=32;
    				c = codice[toupper(c)-'A']+s;
    			}
          
    			else if(isdigit(c)) {
    				if(c<57)
    					c++;
    				else
    					c='0';
    			}
          
    			outp<<c;
    		}
    	}   
    	
    	inp.close();
    	outp.close();
       
       return 0;
    }
  • Re: Programma Codice Segreto C++

    Ciao, ho provato e funziona.. Però potresti spiegarmi come mai serve inp.good()? Credevo che bastasse il controllo !inp.eof() all'inizio della while
  • Re: Programma Codice Segreto C++

    Anche con eof() funziona, cambiandolo sia nel while che nel if.

    La differenza tra i due comandi è nel controllo dello stato del file, l'eof() in caso di errori di lettura/scrittura o qualsiasi altro continuerebbe, magari portandoti in un ciclo continuo, con il good() hai la certezza che si ferma appena c'è un'errore
  • Re: Programma Codice Segreto C++

    Capito, grazie!
Devi accedere o registrarti per scrivere nel forum
8 risposte