【问题标题】:How to copy a .txt file to a char array in c++如何在 C++ 中将 .txt 文件复制到 char 数组
【发布时间】:2013-08-23 08:24:32
【问题描述】:

我试图将整个 .txt 文件复制到 char 数组中。我的代码有效,但它忽略了空格。因此,例如,如果我的 .txt 文件读取“我喜欢派”并将其复制到 myArray,如果我使用 for 循环计算我的数组,我会得到“ILikePie”

这是我的代码

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main () 
{
  int arraysize = 100000;
  char myArray[arraysize];
  char current_char;
  int num_characters = 0;
  int i = 0;

  ifstream myfile ("FileReadExample.cpp");

     if (myfile.is_open())
        {
          while ( !myfile.eof())
          {
                myfile >> myArray[i];
                i++;
                num_characters ++;
          }      

 for (int i = 0; i <= num_characters; i++)
      {

         cout << myArray[i];
      } 

      system("pause");
    }

有什么建议吗? :/

【问题讨论】:

  • arraysize 应该是 const。
  • !myfile.eof() 的使用不正确。即使您想阅读单词,而不是所有字符,您也在使用myfile &gt;&gt; myArray[i] 的结果而没有验证它是否成功,这是不正确的。如果您想阅读所有字符,那么 while ( myfile.get( myArray[i] ) ) ++i; 可以工作(但您仍然需要边界检查)。但 Nemanja 的回答要好得多。

标签: c++ arrays


【解决方案1】:

myfile >> myArray[i]; 

您正在逐字阅读文件,这会导致空格跳过。

您可以将整个文件读入字符串

std::ifstream in("FileReadExample.cpp");
std::string contents((std::istreambuf_iterator<char>(in)), 
    std::istreambuf_iterator<char>());

然后你可以使用contents.c_str()来获取char数组。

这是如何工作的

std::string 具有范围构造函数,它复制范围 [first,last) 中的字符序列注意它不会复制最后一个,以相同的顺序:

template <class InputIterator>
  string  (InputIterator first, InputIterator last);

std::istreambuf_iterator 迭代器是从流缓冲区读取连续元素的输入迭代器。

std::istreambuf_iterator<char>(in)

将为我们的ifstream in(文件开头)创建迭代器,如果您不向构造函数传递任何参数,它将创建流尾迭代器(最后一个位置):

默认构造的 std::istreambuf_iterator 称为 end-of-stream 迭代器。当一个有效的 std::istreambuf_iterator 到达底层流的末尾时,它变得等于流尾迭代器。取消引用或增加它会进一步调用未定义的行为。

因此,这将复制所有字符,从文件中的第一个字符开始,直到下一个字符是流的结尾。

【讨论】:

  • 这当然是正确的答案,但是有两个细节值得指出:首先,如果您想查看文件中的确切字节,您应该以二进制模式打开它,并且确保文件充满"C" 语言环境;否则,可能会出现各种翻译。其次,如果文件包含空字符,contents.c_str() 不是要走的路。更一般地说,在这种情况下,我会使用contents.data()(但我看不出有任何理由不直接在字符串上工作)。
  • @JamesKanze,感谢您的建议。我没有使用二进制模式,我建议c_str,因为我假设 OP 使用的是 ASCII txt 文件。但是,感谢您的评论,因为这是我(和其他人)学习新东西的最佳方式(例如“C”语言环境 - 我不知道它是什么,所以我会查一下)。
  • 我不清楚 OP 是否想要字符串中文件的确切字节,或者他是否想要字符串的文本表示。我的 cmets 指的是他想要确切字节的情况;您的代码,完全按照所写,对于文件中文本的内部表示很好(假设它是文本——但否则,std::vector&lt;char&gt; 将比字符串更有意义。
  • 简单提一下 - 在我记得之前在哪里看到这个之前,我正在输入一个很长的问题:stackoverflow.com/q/1424510/1043529。 'extra' 括号解决了“最麻烦的解析”。
【解决方案2】:

使用以下代码sn-p:

FILE *f = fopen("textfile.txt", "rb");
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);

char *string = (char *)malloc(fsize + 1);
fread(string, fsize, 1, f);
fclose(f);

string[fsize] = 0;

【讨论】:

  • 刚刚修复它,在 fopen() 调用中添加标志 'b'。
  • void* 不能直接转换为 char*(在 malloc 行上)。
【解决方案3】:

如果您一定要使用 char 数组,并且对代码进行最少的修改,这是一个简单的解决方案。下面的 sn-p 将包括所有空格和换行符,直到文件末尾。

      while (!myfile.eof())
      {
            myfile.get(myArray[i]);
            i++;
            num_characters ++;
      }  

【讨论】:

  • 这是性能差的定义。很好的演示,但实用性很差,因为逐字节读取确实会占用磁盘。
  • 感谢您的反馈,能否为以后的读者提供更好的解决方案?
  • 你会说这可能是穷人,还是只是穷人?另外,速度差还是复杂度差?我对硬件层了解不多,但我认为编译器会做一些展开/矢量化,使性能具有可比性(特别是因为数据只是成对依赖的。)作为一般规则,我使用“单线” ' 方法在循环中可用,但如果我担心速度,我也会担心幕后的虚拟方法惩罚等。
【解决方案4】:

更简单的方法是使用 get() 成员函数:

while(!myfile.eof() && i < arraysize)
{
    myfile.get(array[i]); //reading single character from file to array
    i++;
}

【讨论】:

    【解决方案5】:

    这是您需要的代码 sn-p:

    #include <string>
    #include <fstream>
    #include <streambuf>
    #include <iostream>
    
    
    int main()
    {
      std::ifstream file("name.txt");
      std::string str((std::istreambuf_iterator<char>(file)),
                            std::istreambuf_iterator<char>());
    
      str.c_str();
    
      for( unsigned int a = 0; a < sizeof(str)/sizeof(str[0]); a = a + 1 )
      {
        std::cout << str[a] << std::endl;
      }
    
      return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2016-10-02
      • 2015-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-03
      • 1970-01-01
      • 2017-01-20
      相关资源
      最近更新 更多