PDA

Visualizza la versione completa : [C++] Confronto vector e array di caratteri


robdb
20-09-2011, 10:01
devo scrivere un'applicazione in cui un file di testo viene letto e memorizzato in un vector di stringhe

vector<string> text;
dopo di che devo confrontare ogni carattere del testo caricato dal file con un array di char dal contenuto predefinito

char ARRAY[21] = {... ... ...}
per cui avevo pensato ad una cosa del genere


for(int i = 0; i < text.size(); i++){
for(int j = 0; j < 21; j++){
if(text[i] == ARRAY[j])
index_t[i] = j;
}
}


in fase di compilazione mi compare il seguente errore:
no match for 'operator==' in '(((std::vector<std::string, std::allocator<std::string> >*)
come posso risolverlo? :dh:

oregon
20-09-2011, 10:12
if(text[i][j] == ARRAY[j])

robdb
20-09-2011, 11:02
perch il doppio indice?

oregon
20-09-2011, 11:06
Il primo per identificare un elemento del vettore, l'altro per il carattere dell'elemento scelto

robdb
20-09-2011, 12:58
mi spiego meglio per cercare di essere pi chiaro. devo confrontare ogni carattere di ogni stringa contenuta in text (vector<string>) con l'array di caratteri ARRAY. se il confronto positivo, associo ad una variabile temporanea 'index' il valore dell'indice corrispondente a quella lettera.
per esempio: se una lettera di una stringa di text R, il valore di index deve essere 15 (index = 15) poich ARRAY[15] = 'R'.
come posso iterare il tutto in modo da controllare ogni carattere di ogni stringa di text?

oregon
20-09-2011, 14:13
Come hai fatto con la correzione che ti ho suggerito ... ma devi spiegare a cosa ti serve index_t ...

robdb
20-09-2011, 15:16
sinceramente non ho provato ancora perch nel frattempo abbiamo analizzato un'altra strada. comunque per rendere forse il tutto ancora pi chiaro, ti invio il codice completo cosi si capisce meglio il tutto. l'applicazione implementa l'algoritmo di vigenere utilizzando l'alfabeto italiano: legge quindi un file di testo e carattere per carattere effettua la cifratura. le lettere cifrate verranno scritte su un altro file di testo. non potendo implementare l'algoritmo nel modo classico perch in questo caso l'alfabeto quello italiano, ho pensato di fare in questo modo: ho creato un array ALPH con tutti i caratteri dell'alfabeto italiano


char ALPH[21] = {'A','B','C','D','E','F','G','H','I','L','M','N',' O','P','Q','R','S','T','U','V','Z'};
dopo di che cerco la corrispondenza della lettera della chiave e della corrispondente lettera da cifrare in ALPH in modo da ottenere gli indici, in caso affermativo. Dopo di che calcolo lettera per lettera la cifratura. per esempio:
CHIAVE: ROBERTO
TESTO: PROVA


key[0] = R = ALPH[15] --->index_key = 15;
text[0] = P = ALPH[13] --->index_text = 13;
letteracodificata[0] = ALPH[(15+13)%21] = ALPH[7] = H


il codice completo :


#include <string>
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

class Vigenere
{
public:
string key;
vector<string> text;

Vigenere(string str){
key = str;
key = StringToUpper(key);
if(!key.empty()){
key = EraseChar(key);
}

return;
}

string StringToUpper(string convstr){
for(int i = 0; i < convstr.length(); i++){
convstr[i] = toupper(convstr[i]);
}
return convstr;
}

//load the content of a file into t
void Vigenere::LoadText(string filename){
ifstream f;
string line;

f.open(filename.c_str());
if(!f.is_open()){
cout << "Error opening file: " << filename << " !" << endl;
return;
}

while(getline(f,line)){
line = StringToUpper(line);
if(!line.empty()){
line = EraseChar(line);
text.push_back(line);
}
}

f.close();
}

//deletes all characters not in ALPH
string EraseChar(string str){
char ALPH[21] = {'A','B','C','D','E','F','G','H','I','L','M','N',' O','P','Q','R','S','T','U','V','Z'};
str = StringToUpper(str);
for(int i = 0; i < str.length(); i++){
bool inAlph = false;
for(int j = 0; j < 21; j++){
if(str[i] == ALPH[j]){
inAlph = true;
break; // don't need to keep checking against the rest of ALPH
}
}
if (!inAlph) {
str.erase(i,1);
i--;
}
}
return str;
}

void encode(string plaintext, string encoded_f){
ofstream f;
char ALPH[21] = {'A','B','C','D','E','F','G','H','I','L','M','N',' O','P','Q','R','S','T','U','V','Z'};

TextErase();
LoadText(plaintext);

f.open(encoded_f.c_str());
if(!f.is_open()){
cout << "Error creating file: " << encoded_f << " !" << endl;
return;
}

int index_k[key.length()]; //key indexs array
for(int i = 0; i < key.length(); i++){
for(int j = 0; j < 21; j++){
if(key[i] == ALPH[j])
index_k[i] = j;
}
}

size_t* index_t = new size_t[text.size()]; //text indexs
for (size_t i = 0; i < text.size(); ++i){
size_t pos = text[i].find_first_of(ALPH);

if (pos != std::string::npos){
index_t[i] = pos;
}

char ch = ALPH[(index_k[i%key.length()] + index_t[i])%21];
f << ch;
}
f << "\n";
f.close();
return;
}

void TextErase(){
text.clear();
}
};

int main()
{
string key, encoded, plaintext, decoded;
cout << "Key: ";
cin >> key;

Vigenere cipher(key);

cout << "Input file: ";
cin >> plaintext;
cout << "Output file: ";
cin >> encoded;
cipher.encode(plaintext,encoded);

}


aprendo un file con tre righe di testo, mi restituisce un file con solo tre lettere. come posso risolvere? ormai credo di non riuscire pi nemmeno a pensare, sono incollato qui da pi di 5 ore :dh:

robdb
20-09-2011, 16:57
sono ritornato sull'idea che mi hai dato del doppio indice per scorrere il vector text, modificando leggermente quanto mi avevi suggerito. ti posto il codice completo, la parte riguardante il confronto nella funzione encode


//vigenere algorithm with Italian alphabet

#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include <string.h>

using namespace std;

class Vigenere
{
public:
string key;
vector<string> text;

Vigenere(string str){
key = str;
key = StringToUpper(key);
if(!key.empty()){
key = EraseChar(key);
}

return;
}

//converts every letter to uppercase
string StringToUpper(string convstr){
for(int i = 0; i < convstr.length(); i++){
convstr[i] = toupper(convstr[i]);
}
return convstr;
}

//load the content of a file into text
void Vigenere::LoadText(string filename){
ifstream f;
string line;

f.open(filename.c_str());
if(!f.is_open()){
cout << "Error opening file: " << filename << " !" << endl;
return;
}

while(getline(f,line)){
line = StringToUpper(line);
if(!line.empty()){
line = EraseChar(line);
text.push_back(line);
}
}

f.close();
}

//deletes all characters not in ALPH
string EraseChar(string str){
char ALPH[21] = {'A','B','C','D','E','F','G','H','I','L','M','N',' O','P','Q','R','S','T','U','V','Z'};
str = StringToUpper(str);
for(int i = 0; i < str.length(); i++){
bool inAlph = false;
for(int j = 0; j < 21; j++){
if(str[i] == ALPH[j]){
inAlph = true;
break; // don't need to keep checking against the rest of ALPH
}
}
if (!inAlph) {
str.erase(i,1);
i--;
}
}
return str;
}

void encode(string plaintext, string encoded_f){
ofstream f;
char ALPH[21] = {'A','B','C','D','E','F','G','H','I','L','M','N',' O','P','Q','R','S','T','U','V','Z'};

TextErase();
LoadText(plaintext);

f.open(encoded_f.c_str());
if(!f.is_open()){
cout << "Error creating file: " << encoded_f << " !" << endl;
return;
}

/************************************************** **************************
* each letter in ALPH is associated with an index, so A-->0 B-->1 and so on.
* now it checks every characters of every string of text in order to find
* a correspondance. the same for the key.
* for example:
* key: ROBERT
* text: PRINT
* the first letter in text is P, which corrispond to ALPH[13], so index_t[0]=13
* the first letter in key is R, which corrispond to ALPH[15], so index_k[0]=15
* the first encoded letter is:
* ALPH[(index_t[0]+index_k[0])%21] = ALPH[7] = H
************************************************** **************************/

int passwdcnt = 0;
int* index_t = new int[text.size()];
int* index_k = new int[key.length()];

for(int i = 0; i < text.size(); i++){
for(int j = 0; j < text[i].size(); j++){
char* ptr_k;
char* ptr_t;
if(ptr_t = strchr(ALPH,text[i][j])){
index_t[j] = ptr_t - ALPH;
}
if(ptr_k = strchr(ALPH,key[passwdcnt])){
index_k[j] = ptr_k - ALPH;
}

char ch = ALPH[(index_t[j] + index_k[j])%21];
f << ch;
passwdcnt++;
if(passwdcnt > (key.length()-1))
passwdcnt = 0;
}
f << "\n";
}
f.close();
delete [] index_t;
delete [] index_k;
return;
}

void TextErase(){
text.clear();
}
};

int main()
{
string key, encoded, plaintext, decoded;
cout << "Key: ";
cin >> key;

Vigenere cipher(key);

cout << "Input file: ";
cin >> plaintext;
cout << "Output file: ";
cin >> encoded;
cipher.encode(plaintext,encoded);

}

robdb
20-09-2011, 17:42
la prima versione del codice mi restituisce soltanto alcune lettere contenute nel file e per giunta non crittografate. la seconda produce un file di testo vuoto e crasha durante l'esecuzione.
please help :(

Loading