Как я могу прочитать весь файл .txt различной длины в массив с помощью C ++? - PullRequest
2 голосов
/ 18 января 2012

Я делаю шифр сдвига, который читает текст из файла и декодирует его.Расшифровка прекрасно работает, однако я не могу понять, как найти длину файла без жесткого кодирования в размер массива char.Он также читает только в одну строку, что-нибудь с новой строкой в ​​повреждениях.

Любая помощь будет принята с благодарностью, я оставил основной блок кода, так как он работает с массивом после его чтения ви казалось немного длинным и неактуальным.

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

Ответы [ 4 ]

4 голосов
/ 18 января 2012

Ну, простой однострочный текст для чтения всего файла в динамически изменяемый массив (без использования статически изменяемого массива) символов будет:

#include <vector>
#include <iterator>

std::vector<char> encryptedMessage(std::istreambuf_iterator<char>(in),
                                   std::istreambuf_iterator<char>());

Не связывайтесь с динамическимиВыделите себя, просто позвольте std::vector сделать свое дело.А благодаря оптимизированному поведению при росте вам не нужно беспокоиться о проверке размера файла.Оптимизируйте для скорости, когда это необходимо или, по крайней мере, не раньше, чем ваши файлы станут больше, чем несколько сотен символов.И, конечно же, istreambuf_iterator (вместо istream_iterator) не обрабатывает какие-либо специальные пробелы, он просто извлекает каждый символ из файла один за другим.

Вы можете сделать то же самое с std::string вместо std::vector<char>, но я не уверен в его поведении при росте (возможно, он всегда перераспределяет массив с еще одним элементом).Но опять же, кого волнует скорость, когда файл содержит 400 символов?

2 голосов
/ 18 января 2012

Вы можете использовать seekg, чтобы получить размер всего файла:

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

Вы можете узнать больше о seekg, tellg и файлах в c ++ в целом здесь .

Однако лучшее решение, чем использование char *, - это использовать std: string и вызывать push_back для нее, пока еще не завершено:

#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;
}
1 голос
/ 18 января 2012

У вас не может быть массивов переменной длины (VLA) в C ++.
Компиляторы предоставляют VLA как расширения, но их использование сделает ваш код непереносимым.

Самое простое и лучшее решение - использовать std :: string вместо символьных массивов.

Вы можете получить ответы на все вопросы, какие советы использовать для использования динамически распределенных массивов, но использование std::string - лучший выбор, поэтому игнорируйте их.

EDIT:
Так как кто-то отрицал это. Мне было бы очень интересно узнать причины (если они носят технический характер).

0 голосов
/ 18 января 2012

Вам нужна динамически распределяемая память, и лучший способ управлять этим с помощью std::vector.

std::vector<char> encryptedMessage;

encryptedMessage.resize(size_of_file);
in.get(&encryptedMessage[0], encryptedMessage.size());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...