I'm making a shift cipher that reads in text from a file and decodes it. The decryption works fine howver i can't figure out how to find the length of the file without hardcoding it into the size of the char array. It also only reads in one line, anything with a newline in corrupts.
Any help would be greatly appreciated, i've left out the main block of code as that deals with the array after it has been read in and seemed a bit long and irrelevant.
string fileName;
cout << "Please enter the locations of your encrypted text (e.g ""encryptedText.txt""): ";
getline( cin, fileName );
char encryptedMessage[446]; //How do i read in the file length and declare the array size as a variable instead of [446]?
char decryptedMessage[446];
ifstream in(fileName);
if(in.get(encryptedMessage, 446))
{
[my decrypting code]
}
else
{
cout << "Couldn't successfully read file.\n";
}
system("pause");
You can use seekg to get the size of an entire file:
#include <iostream>
#include <fstream>
using namespace std;
int main () {
long begin_byte, end_byte;
ifstream in("example.txt");
begin_byte = in.tellg();
in.seekg (0, ios::end);
end_byte = in.tellg();
int total_bytes = end_byte - begin_byte;
in.seekg(0, ios::begin);
char *message = new char[total_bytes + 1];
int index = 0;
while (in) {
message[index++] = in.get();
}
in.close();
cout << "message is: " << message << endl;
delete [] message;
return 0;
}
You can read more about seekg, tellg and files in c++ as a whole here.
However a better solution then using char * is using a std:string and calling push_back on it while in has not ended:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main () {
ifstream in("example.txt");
string message;
while (in) {
message.push_back(in.get());
}
in.close();
cout << "message is: " << message << endl;
return 0;
}
Well, a simple one-liner for reading a whole file into a dynamically sized array (don't use a statically sized array) of chars would be:
#include <vector>
#include <iterator>
std::vector<char> encryptedMessage(std::istreambuf_iterator<char>(in),
std::istreambuf_iterator<char>());
Don't mess with dynamic allocation yourself, just let std::vector
do its job. And due to its optimized growth behaviour you don't really need to bother with checking the file size. Optimize for speed when neccessary or at least not before your files get larger than a few hundred characters. And of course the istreambuf_iterator
(instead of istream_iterator
) doesn't handle whitespace any special, it just takes each character raw from the file one by one.
You may do the same with a std::string
instead of a std::vector<char>
, but I'm not sure about its growth behaviour (maybe it always reallocates the array with one more element). But then again, who cares for speed when the file contains 400 charcters?
You cannot have Variable Length Arrays(VLA) in C++.
Compilers do provide VLA's as extensions but using them would make your code non-portable.
Simplest and Best Solution is to use std::string instead of character arrays.
You might get answers all over which advice you to use to use dynamically allocated arrays but using std::string
is the best choice, so ignore those.
EDIT:
Since somebody downvoted this. I would be very interested in knowing the reasons(provided they are technical) to do so.
You need dynamically allocated memory, and the best way to manage that is with std::vector
.
std::vector<char> encryptedMessage;
encryptedMessage.resize(size_of_file);
in.get(&encryptedMessage[0], encryptedMessage.size());