Phronux Temat założony przez niniejszego użytkownika |
[C++] Czytanie pliku od początku i pomijanie białych znaków » 2014-05-23 10:51:38 Mój pierwszy post, więc witam wszystkich! Mam mały problem z dociągnięciem do końca programu używającego szyfru Vigenere'a. Całość jest już praktycznie ukończona, ale od wczoraj zmagam się z dwoma małymi problemami, których za nic nie mogę naprawić. Najpierw kod:
#include <iostream> #include <fstream> #include <string> #include <cctype>
#define EXIT_SUCCES 0;
bool is_empt( std::ifstream & ); void show_menu(); void szyfrowanie(); void deszyfrowanie();
bool is_empt( std::ifstream & pFile ) { return pFile.peek() == std::ifstream::traits_type::eof(); }
void szyfrowanie() { using namespace std; string filename_toCipher; ifstream inFile; cout << "Podaj nazwe pliku z tekstem jawnym: "; cin.clear(); cin.ignore( numeric_limits < streamsize >::max(), '\n' ); getline( cin, filename_toCipher ); inFile.open( filename_toCipher ); if( !inFile.is_open() ) { cout << endl << "Otwarcie pliku nie powiodlo sie. Powrot do menu glownego." << endl; show_menu(); } else if( is_empt( inFile ) ) { cout << endl << "Plik jest pusty. Powrot do menu glownego." << endl; show_menu(); } string filename_pass; ifstream fin; cout << "Podaj nazwe pliku z haslem: "; getline( cin, filename_pass ); fin.open( filename_pass ); if( !fin.is_open() ) { cout << "Otwarcie pliku nie powiodlo sie. Powrot do menu glownego." << endl; show_menu(); } ofstream outFile; outFile.open( "encrypted.txt" ); char znak, znak_haslo; while( !inFile.eof() ) { inFile >> znak; if( islower( znak ) ) znak = toupper( znak ); fin >> znak_haslo; if( islower( znak_haslo ) ) znak_haslo = toupper( znak_haslo ); znak =( znak + znak_haslo ) % 26 + 'A'; outFile << znak; } cout << "Tekst zostal pomyslnie zaszyfrowany!\nWynik szyfrowania znajduje sie w pliku encrypted.txt" << endl << endl; outFile.close(); show_menu(); }
void deszyfrowanie() { using namespace std; string filename_toDeCipher; ifstream inFile; cout << "Podaj nazwe pliku z tekstem zaszyfrowanym: "; cin.clear(); cin.ignore( numeric_limits < streamsize >::max(), '\n' ); getline( cin, filename_toDeCipher ); inFile.open( filename_toDeCipher ); if( !inFile.is_open() ) { cout << endl << "Otwarcie pliku nie powiodlo sie. Powrot do menu glownego." << endl; show_menu(); } else if( is_empt( inFile ) ) { cout << endl << "Plik jest pusty. Powrot do menu glownego." << endl; show_menu(); } string filename_pass; ifstream fin; cout << "Podaj nazwe pliku z haslem: "; getline( cin, filename_pass ); fin.open( filename_pass ); if( !fin.is_open() ) { cout << "Otwarcie pliku nie powiodlo sie. Powrot do menu glownego." << endl; show_menu(); } ofstream outFile; outFile.open( "decrypted.txt" ); char znak, znak_haslo; do { inFile >> znak; if( islower( znak ) ) znak = toupper( znak ); fin >> znak_haslo; if( islower( znak_haslo ) ) znak_haslo = toupper( znak_haslo ); znak -= 65; znak_haslo =( 26 - znak_haslo ) % 26 + 65; znak =( znak + znak_haslo ) % 26 + 'A'; outFile << znak; } while( !inFile.eof() ); cout << "Tekst zostal pomyslnie rozszyfrowany!\nWynik szyfrowania znajduje sie w pliku decrypted.txt" << endl << endl; outFile.close(); show_menu(); }
void show_menu() { std::cout << "[1] Szyfrowanie" << std::endl; std::cout << "[2] Deszyfrowanie" << std::endl; std::cout << "[3] Wyjscie z programu" << std::endl; std::cout << "Wybor: _\b"; int * wybor = new int; std::cin >> * wybor; switch( * wybor ) { case 1: { std::cout << "Wybrano funkcje szyfrujaca." << std::endl; szyfrowanie(); break; } case 2: { std::cout << "Wybrano funkcje deszyfrujaca." << std::endl; deszyfrowanie(); break; } case 3: { std::exit( EXIT_SUCCESS ); } default: { std::cout << "Dokonano blednego wyboru. Prosze wybrac odpowiednia opcje." << std::endl; show_menu(); } } delete wybor; }
int main() { using namespace std; cout << "Witaj w programie obslugujacym szyfr Vigenere\'a." << endl; show_menu(); return EXIT_SUCCES; }
1) Jeśli hasło jest dłuższe od kodu szyfrowanego to powinno być wczytywane od początku. I nie mogę dojść do tego jak to zrobić. Próbowałem takie wstawienie do pętli: if( fin.eof() ) { fin.clear(); fin.seekg( 0, ios_base::beg ); }
Ale nie działa. 2) Możliwe, że pierwszy problem jest pośrednio związany z drugim. Otóż, chciałbym aby w pliku z tekstem do zaszyfrowania (bądź odszyfrowania) pomijane były białe znaki. Próbowałem: inFile >> skipws >> znak;
oraz Ale obie opcje nie poskutkowały. 3) A, jeszcze jedna sprawa, choć najkrótsza i pewnie związana z pytaniem drugim. Pętla wczytuje (i szyfruje bądź deszyfruje) o jeden znak więcej niż jest w tekście. Jest to jakiś losowy znak, nie do końca wiem skąd się bierze. Więc jak szyfruje słowo TEKST hasłem TAJNY to powstaje mi METFRP zamiast METFR. Za pomoc serdecznie dziękuję! |
|
pekfos |
» 2014-05-23 12:47:05 1. Wczytaj hasło raz. 2. isspace()3. Nie sprawdzasz, czy plik się skończył. Tu średnika nie może być. I dlaczego nie użyjesz samego 0, albo EXIT_SUCCESS..? |
|
Phronux Temat założony przez niniejszego użytkownika |
» 2014-05-23 18:05:02 O dziwo, wszystko udało mi się naprawić, poza jednym... Wczytuję teraz od razu cały tekst i całe hasło do odpowiednich stringów, by to na nich operować. Robię to w następujący sposób: string caly_tekst { }; while( getline( inFile, caly_tekst ) ) { } caly_tekst.erase( std::_Remove_if( caly_tekst.begin(), caly_tekst.end(), isspace ), caly_tekst.end() );
Jednakowoż, nie wiedzieć dlaczego, wczytuje cały plik POZA pierwszym znakiem. Wiecie dlaczego? // Poprawka, nie wczytuje całego pliku, a tylko ostatni wiersz, ale wciąż bez pierwszego znaku. Swoją drogą, te EXIT_SUCCESS robię tylko i wyłącznie by później w innym IDE to działało i dla własnej wygody, bo tak lubię. ;) |
|
Monika90 |
» 2014-05-23 18:23:16 std::_Remove_if? W C++ nie ma czegoś takiego. while( getline( inFile, caly_tekst ) ) { }
moim zdaniem jeżeli plik konćzy się znakiem '\n', to po wyjsciu z tej pętli caly_tekst jest pusty |
|
Phronux Temat założony przez niniejszego użytkownika |
» 2014-05-23 18:34:45 Albo: std::remove_if Nawet lepiej, choć dla mojego kompilatora (VS13) to żadna różnica. Swoją drogą, udało mi się w końcu, lepiej było użyć np. inFile.get(); Tylko teraz jakoś źle wczytuje hasło w szyfrowaniu... muszę jeszcze posiedzieć. |
|
Phronux Temat założony przez niniejszego użytkownika |
» 2014-05-23 20:51:14 Nie wiem czy kogoś to może zainteresować, ale dla ludzi szukających w Googlu szyfru Vigenere'a w C++ wstawiam tutaj ostateczny, działający kod. Temat jednocześnie zamykam.
#include <iostream> #include <fstream> #include <string> #include <cctype> #include <algorithm>
#define EXIT_SUCCESS 0
bool is_empt( std::ifstream & ); void encryption(); void decipherment(); void show_menu();
bool is_empt( std::ifstream & pFile ) { return pFile.peek() == std::ifstream::traits_type::eof(); }
void encryption() { using std::cout; using std::string; using std::ifstream; using std::cin; using std::endl; using std::getline; using std::ofstream; string filename_toCipher; ifstream inFile; cout << "Podaj nazwe pliku z tekstem jawnym: "; cin.clear(); cin.ignore( std::numeric_limits < std::streamsize >::max(), '\n' ); getline( cin, filename_toCipher ); inFile.open( filename_toCipher ); if( !inFile.is_open() ) { cout << endl << "Otwarcie pliku nie powiodlo sie. Powrot do menu glownego." << endl << endl; show_menu(); } else if( is_empt( inFile ) ) { cout << endl << "Plik jest pusty. Powrot do menu glownego." << endl << endl; show_menu(); } string filename_pass; ifstream fin; cout << "Podaj nazwe pliku z haslem: "; getline( cin, filename_pass ); fin.open( filename_pass ); if( !fin.is_open() ) { cout << "Otwarcie pliku nie powiodlo sie. Powrot do menu glownego." << endl << endl; show_menu(); } else if( is_empt( fin ) ) { cout << endl << "Plik jest pusty. Powrot do menu glownego." << endl << endl; show_menu(); } ofstream outFile; outFile.open( "encrypted.txt" ); string whole_text { }; char c; inFile.get( c ); do { whole_text += c; inFile.get( c ); } while( !inFile.eof() ); whole_text.erase( std::remove_if( whole_text.begin(), whole_text.end(), isspace ), whole_text.end() ); string whole_pass { }; fin.get( c ); do { whole_pass += c; fin.get( c ); } while( !fin.eof() ); whole_pass.erase( std::remove_if( whole_pass.begin(), whole_pass.end(), isspace ), whole_pass.end() ); unsigned int j = 0, i = 0; char single_sign, single_pass_sign; while( j != whole_text.size() ) { single_sign = whole_text[ j ]; if( islower( single_sign ) ) single_sign = toupper( single_sign ); if( i == whole_pass.size() ) i = 0; single_pass_sign = whole_pass[ i ]; if( islower( single_pass_sign ) ) single_pass_sign = toupper( single_pass_sign ); single_sign =( single_sign + single_pass_sign ) % 26 + 'A'; outFile << single_sign; ++j; ++i; } cout << endl << "Tekst zostal pomyslnie zaszyfrowany!\nWynik szyfrowania znajduje sie w pliku encrypted.txt" << endl << endl; outFile.close(); show_menu(); }
void decipherment() { using std::cout; using std::string; using std::ifstream; using std::cin; using std::endl; using std::getline; using std::ofstream; string filename_toDeCipher; ifstream inFile; cout << "Podaj nazwe pliku z tekstem zaszyfrowanym: "; cin.clear(); cin.ignore( std::numeric_limits < std::streamsize >::max(), '\n' ); getline( cin, filename_toDeCipher ); inFile.open( filename_toDeCipher ); if( !inFile.is_open() ) { cout << endl << "Otwarcie pliku nie powiodlo sie. Powrot do menu glownego." << endl << endl; show_menu(); } else if( is_empt( inFile ) ) { cout << endl << "Plik jest pusty. Powrot do menu glownego." << endl << endl; show_menu(); } string filename_pass; ifstream fin; cout << "Podaj nazwe pliku z haslem: "; getline( cin, filename_pass ); fin.open( filename_pass ); if( !fin.is_open() ) { cout << "Otwarcie pliku nie powiodlo sie. Powrot do menu glownego." << endl << endl;; show_menu(); } ofstream outFile; outFile.open( "decrypted.txt" ); string whole_text { }; char c; inFile.get( c ); do { whole_text += c; inFile.get( c ); } while( !inFile.eof() ); whole_text.erase( std::remove_if( whole_text.begin(), whole_text.end(), isspace ), whole_text.end() ); string whole_pass { }; fin.get( c ); do { whole_pass += c; fin.get( c ); } while( !fin.eof() ); whole_pass.erase( std::remove_if( whole_pass.begin(), whole_pass.end(), isspace ), whole_pass.end() ); char single_sign, single_pass_sign; int j = 0, i = 0; while( j != whole_text.size() ) { single_sign = whole_text[ j ]; if( islower( single_sign ) ) single_sign = toupper( single_sign ); if( i == whole_pass.size() ) i = 0; single_pass_sign = whole_pass[ i ]; if( islower( single_pass_sign ) ) single_pass_sign = toupper( single_pass_sign ); single_sign -= 65; single_pass_sign =( 26 - single_pass_sign ) % 26 + 65; single_sign =( single_sign + single_pass_sign ) % 26 + 'A'; outFile << single_sign; ++j; ++i; } cout << endl << "Tekst zostal pomyslnie rozszyfrowany!\nWynik rozszyfrowania znajduje sie w pliku decrypted.txt" << endl << endl; outFile.close(); show_menu(); }
void show_menu() { std::cout << "[1] Szyfrowanie" << std::endl; std::cout << "[2] Deszyfrowanie" << std::endl; std::cout << "[3] Wyjscie z programu" << std::endl; std::cout << "Wybor: _\b"; int * wybor = new int; int i = 0; while( i < 1 ) { std::cin.clear(); std::cin.sync(); std::cin >> * wybor; if( std::cin.fail() ) { std::cout << "Wybrano zly rodzaj znaku wyboru. Prosze wpisac liczbe w przedziale 1-3 w celu wybrania odpowiedniej opcji." << std::endl << std::endl; show_menu(); continue; } else { ++i; } } switch( * wybor ) { case 1: { std::cout << std::endl << "Wybrano funkcje szyfrujaca." << std::endl; encryption(); break; } case 2: { std::cout << std::endl << "Wybrano funkcje deszyfrujaca." << std::endl; decipherment(); break; } case 3: { std::exit( EXIT_SUCCESS ); break; } default: { std::cout << std::endl << "Dokonano blednego wyboru. Prosze wybrac odpowiednia opcje." << std::endl; show_menu(); } } delete wybor; }
int main() { using namespace std; cout << "Witaj w programie obslugujacym szyfr Vigenere\'a." << endl; show_menu(); return EXIT_SUCCESS; }
|
|
« 1 » |