简体   繁体   中英

How do i read an entire .txt file of varying length into an array using c++?

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");

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 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;
}

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());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM