Проблемы с форматированием cout, XOR и fileIO в C++

У меня проблемы, которых я никогда раньше не видел, так как я начал возиться с оператором XOR и простым шифрованием с помощью односимвольного ключа. Текст всегда имеет случайный символ ascii в конце после того, как он проходит через программу во второй раз. Другая проблема заключается в том, что тексты «Предзаказ» и «Постзаказ» изменяются поочередно после каждой итерации программы. Я уверен, что большая часть этого просто из-за ошибок новичков, особенно из-за отсутствия опыта работы с вводом-выводом в том, как появляются эти проблемы.

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

int main()
{
    ifstream ifile;
    ofstream ofile;
    string toProc;
    string file;
    char key = ' ';
    cout << "Enter file location: \n";
    cin >> file;
    cout << "Enter key: \n";
    cin >> key;
    ifile.open(file);
    if(ifile.is_open())
    {
        char temp;
        temp = ifile.get();
        toProc.push_back(temp);
        while(ifile.good())
        {
            temp = ifile.get();
            toProc.push_back(temp);
        }

        ifile.close();
    }
    else
    {
        cout << "No file found.\n";
    }
    cout << "Pre action: " << toProc << endl;
    for(int i = 0; i < toProc.size(); i++)
        toProc[i] ^= key;
    cout << "Post action: " << toProc << endl;
    ofile.open(file);
    ofile << toProc;
    ofile.close();
}

person Aer    schedule 30.06.2013    source источник


Ответы (1)


Функция get() функции std::ifstream, которую вы используете для извлечения символов из входного файла, возвращает eof (конец файла), когда достигает конца файла. Вам нужно проверить это (вместо проверки ifile.good() в цикле).

То, как это написано сейчас, принимает eof как символ и добавляет его к строке. Это (т. е. версия с xor'ом) и есть забавный персонаж, который вы получаете на выходе.

Вот простой цикл, который считывает символы из std::cin с помощью get() и выводит их на STDOUT. Он выполняет проверку для eof правильно. Вы можете вписать это в свой код, используя ifile вместо std::cin:

#include <iostream>

int main()
{
  char c;
  while ((c = std::cin.get()) != std::istream::traits_type::eof())
    std::cout.put(c);

  std::cout << std::endl;
  return 0;
}

Я также должен упомянуть, что функция get() читает посимвольно, и для этого нет веских причин. Я бы использовал getline() или read() для чтения больших фрагментов.

person jogojapan    schedule 30.06.2013
comment
Обратите внимание, что getLine() не работает в части расшифровки, так как результат шифрования может включать в себя все виды управляющих символов. Чтобы выполнить значимое шифрование, вы должны использовать явную кодировку символов (но опять же, вы также не должны использовать шифрование с одним символом, в целях тестирования вы должны быть в состоянии сойти с рук). - person Maarten Bodewes; 30.06.2013
comment
@owlstead Ах да, верно. Я почему-то предполагал, что шифрование здесь применяется только к буквенным символам, но вы правы, оно влияет и на окончания строк. - person jogojapan; 30.06.2013
comment
Спасибо! Работал отлично после того, как я проверил eof. Файловый ввод-вывод всегда был для меня проблемой. - person Aer; 30.06.2013