Я пытаюсь создать простую программу, которая изменяет значения на 3 (функция шифрования) -> Я хочу, чтобы это напрямую повлияло на файл. Но я не знаю, как это сделать. После того, как он будет зашифрован, я вызову функцию Decrypt (которая работает именно так, как я хочу). Таким образом, вам нужно будет запустить программу для доступа к дневнику. Могу ли я как-нибудь изменить отдельные символы, как в функции дешифрования? Я все время получаю ошибку getline.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
void decrypt_diary(string,string);
void encrpyt_diart(string,string);
int main()
{
string fileName = "Diary.txt";
string line;
decrypt_diary(fileName,line);
return 0;
}
void decrypt_diary(string fileName, string line)
{
ifstream journal;
journal.open(fileName);
if (journal.is_open())
{
while (getline(journal,line))
{
for (int i=0; i<signed(line.length()); i++)
{
line[i] = line[i] + 3;
}
cout << line << endl;
}
}
journal.close();
}
void encrypt_diary(string fileName, string line)
{
ofstream journal;
journal.open(fileName);
if (journal.is_open())
{
while (getline(journal,line))
{
for (int i=0; i<signed(line.length()); i++)
{
line[i] = line[i] - 3;
// journal << line[i];
}
cout << line << endl;
}
}
journal.close();
}
Я не совсем уверен, что вы имеете в виду, говоря о чтении всего файла в память, может быть, вы сможете уточнить. Ах да, именно так я и намеревался написать именно таким первым способом. Я просто не знаю, как это сделать. Я бы предпочел такой банкомат, так как я только узнаю о <fstream>
Откройте файл в режиме чтения / записи и приготовьтесь к оргии чтения / поиска / записи.
Вы имеете в виду ошибку getline?
./main.cpp:41:36: error: no matching function for call to ‘getline(std::ofstream&, std::__cxx11::string&)’ while (getline(journal,line)
Если это так, я считаю, что проблема в том, что нет функции getline (), которая принимает объект из потока, поскольку getline () предназначен для чтения файлов, а ofstream (поток выходного файла) - для записи файлов. Он отлично работает в функции decrypt_diary, поскольку она принимает ifstream (поток входного файла).
Если вы сначала сосредоточитесь на реализации дешифрования или шифрования, вам будет легче решать проблемы компиляции.
Вы можете попробовать закомментировать функцию encrypt_diary (строка имя файла, строка строки), а затем попробовать скомпилировать и запустить программу еще раз.
Я думаю, вы обнаружите, что ваша функция decrypt_diary (строка имя файла, строка строки) работает нормально.
ах, спасибо за объяснение, почему getline () не работает для ofstream, в этом есть большой смысл. И да, я знал, что функция decrypt_diary (string fileName, string line) работает нормально. В настоящее время я работаю над тем, чтобы заставить другую функцию делать то, что я хочу, без необходимости читать файл, поскольку это не то, что делает ofstream. Я отправлю решение, как только соберу его. Еще раз большое спасибо за это объяснение по поводу потокового бизнеса, оно помогло укрепить мои мысли.
В этом есть смысл. Я тогда немного неправильно понял. Если вам нужен поток как для записи, так и для чтения, вы можете попробовать использовать fstream. Как упоминал @Qubit в комментарии к вашему вопросу, чтение всего файла в память (например, строковая переменная), а затем манипулирование этими данными перед записью их обратно в файл, вероятно, является самым простым способом обработки шифрования и дешифрования.
Итак, если я правильно понимаю, что вы хотите, вы хотите просмотреть файл, символ за символом, и заменить его каким-либо другим символом. Я снова скажу, что переход от одного персонажа к другому, вероятно, не лучшая идея, но модификация фрагментов должна быть достаточно простой.
#include <string>
#include <fstream>
#include <iostream>
inline void encrypt_char(char& in) {
in += 3;
}
inline void decrypt_char(char& in) {
in -= 3;
}
int main(int argc, char** argv) {
//These first 2 lines just process the command line argument
if (argc < 2 || (argv[1][0] != 'e' && argv[1][0] != 'd') || argv[1][1] != '\0') return 1;
bool encrypt_mode = (argv[1][0] == 'e' ? true : false);
std::fstream file("Diary.txt", std::ios::in | std::ios::out);
file.seekg(0, std::ios::end);
size_t size = file.tellg(); //This should tell us the file size
char c;
for (size_t i = 0; i < size; i++) {
file.seekg(i, std::ios::beg); //Set read position
file.read(&c, 1); //Read a character
if (encrypt_mode) encrypt_char(c);
else decrypt_char(c);
file.seekp(i, std::ios::beg); //Set write position
file.write(&c, 1); //Write a character
}
file.close();
return 0;
}
Обратите внимание, что мы избегаем использования >>
и <<
, поскольку они отформатированы, пропускаем пробелы по умолчанию (хотя вы можете изменить это) и т.д. Вместо этого мы используем read
и write
, поскольку они просто хранят байты, какими бы они ни были.
Этот подход означает, что мы выполняем множество операций с файлом и, вероятно, не самый быстрый. Вместо этого вы можете читать по частям, эта модификация довольно проста, просто замените символ массивом символов и читайте более 1 байта за раз. Однако, если возможно, проще всего сразу прочитать весь файл.
#include <string>
#include <fstream>
#include <iostream>
inline void encrypt_char(char& in) {
in += 3;
}
inline void decrypt_char(char& in) {
in -= 3;
}
int main(int argc, char** argv) {
//These first 2 lines just process the command line argument
if (argc < 2 || (argv[1][0] != 'e' && argv[1][0] != 'd') || argv[1][1] != '\0') return 1;
bool encrypt_mode = (argv[1][0] == 'e' ? true : false);
std::fstream file("Diary.txt", std::ios::in | std::ios::out);
file.seekg(0, std::ios::end);
size_t size = file.tellg(); //This should tell us the file size
file.seekg(0, std::ios::beg);
char* fileData = new char[size]; //Don't need null-termination
file.read(fileData, size); //Read the whole file
for (size_t i = 0; i < size; i++) { //Process the characters
if (encrypt_mode) encrypt_char(fileData[i]);
else decrypt_char(fileData[i]);
}
file.seekp(0, std::ios::beg); //Find the start of the file
file.write(fileData, size); //Write the whole thing
delete[] fileData;
file.close();
return 0;
}
Вызов программы с помощью ./myProgram e
вызывает ее шифрование, замена e
на d
вызывает ее расшифровку.
Мы не использовали здесь строки, поскольку они нам действительно не нужны, но вы всегда можете это сделать, если предпочитаете строки массивам символов.
Это, конечно, довольно простой пример, вы можете изменять и усложнять его по своему усмотрению. Также обратите внимание, что это, вероятно, не единственный (и, возможно, лучший) способ решения таких проблем.
Спасибо за подробный ответ, это очень помогает !!! Это первый вопрос, который я задал из страха, что веду себя глупо, но, честно говоря, мне все равно после этого. Это сообщество очень умное, и спасибо за то, что помогли мне учиться. У меня была проблема с ./myProgram e, он компилируется, но когда я набираю его, я получаю эту ошибку. ./diary.cpp: строка 5: синтаксическая ошибка возле неожиданного токена (' ./diary.cpp: line 5:
inline void encrypt_char (char & in) {'
Ухх, вы не хотите запускать исходный код, вы хотите запускать исполняемый файл. Я не знаю, используете ли вы Linux или Windows, и не знаю, как вы назвали исполняемый файл? Вы можете просто использовать любые части кода в своем собственном проекте, нет необходимости анализировать аргументы командной строки, если вы не знакомы с этим. Нет причин пытаться изучить слишком много вещей одновременно, сосредоточиться на одном, а затем переходить к другому.
Я просто хотел обновить. Ваш код работал без проблем, это была проблема с моей стороны.
Вы можете использовать
fstream
, прочитать символ, изменить его, записать обратно в ту же позицию, если вы действительно этого хотите. Но я бы сказал, что это должно быть намного быстрее, если вы прочитаете весь файл в память, измените его, а затем запишите все это обратно в файл. Если файл не помещается в памяти, делайте это по частям.