【问题标题】:How do i read an entire .txt file of varying length into an array using c++?如何使用 C++ 将不同长度的整个 .txt 文件读入数组?
【发布时间】:2012-01-18 16:09:54
【问题描述】:

我正在制作一个移位密码,它从文件中读取文本并对其进行解码。解密工作正常但是我无法弄清楚如何找到文件的长度而不将其硬编码为 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");

【问题讨论】:

  • 查看previous answer 中的第四个测试用例。将其s4string 更改为vector,它应该已经准备就绪了。

标签: c++ string file-io fstream


【解决方案1】:

嗯,将整个文件读入动态大小的字符数组(不要使用静态大小的数组)的简单单行代码是:

#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&lt;char&gt; 做同样的事情,但我不确定它的增长行为(也许它总是用一个更多的元素重新分配数组)。但话说回来,当文件包含 400 个字符时,谁在乎速度呢?

【讨论】:

    【解决方案2】:

    您可以使用 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;
    }
    

    您可以阅读更多关于 c++ 中 seekg、tellg 和 files 的整体信息here

    但是,使用 char * 更好的解决方案是使用 std:string 并在 in 尚未结束时对其调用 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;
    }
    

    【讨论】:

    • 伙计,逐字符读取文件是个糟糕的主意。你可以一口气读完。
    • 同意。但是再次,您 需要 使用 get 函数之类的东西,因为 decrypted_text 听起来像是具有特殊字符的东西。有更好的函数可以读取给定大小的文件块。不过,我找不到这样一个需要字符串的函数。
    • 对。这就是为什么老学校使用“open/stat/malloc/read”而新学校喜欢ifstreamvector :) 请注意,每次你显示一些代码时 - 新手复制/粘贴它,然后我们有一个新一代程序员……
    • 仍然......你的评论让我思考。有没有办法使用 ifstream 和 string 读取整个文件而不使用 helper char* 缓冲区?想过read方法,但是没有办法将指向字符串数据的指针作为参数传递...
    • @istrandjev:嗯,没有。你可以做一个单行,但不如将该死的文件读入内存那么有效......见stackoverflow.com/questions/2602013/…
    【解决方案3】:

    您不能在 C++ 中使用可变长度数组 (VLA)。
    编译器确实提供了 VLA 作为扩展,但使用它们会使您的代码不可移植。

    最简单和最好的解决方案是使用 std::string 代替字符数组。

    您可能会得到关于使用动态分配数组的建议的答案,但使用 std::string 是最佳选择,因此请忽略这些。

    编辑:
    由于有人对此表示反对。我很想知道这样做的原因(只要它们是技术性的)。

    【讨论】:

    • @VladLazarenko:真的吗?请用 C++ 标准允许 VLA 的参考来启发我们。
    • @Marobri:就像that一样简单
    • @VladLazarenko:重复:请用 C++ 标准允许 VLA 的参考来启发我们。
    • @VladLazarenko: :) 感谢您在忙碌的一天结束时给我一个爽朗的笑声。
    • alloca_ 比 VLA 更便携,请改用它。
    【解决方案4】:

    您需要动态分配的内存,最好的管理方法是使用std::vector

    std::vector<char> encryptedMessage;
    
    encryptedMessage.resize(size_of_file);
    in.get(&encryptedMessage[0], encryptedMessage.size());
    

    【讨论】:

    • 我会四处走动,猜测 OP 不知道如何获取文件的大小,并且可能知道向量。
    猜你喜欢
    • 1970-01-01
    • 2015-11-23
    • 1970-01-01
    • 2021-02-06
    • 2018-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多