如何从文件中读取行并将其切割成碎片?

Posted

技术标签:

【中文标题】如何从文件中读取行并将其切割成碎片?【英文标题】:How can I read lines from file and cut it pieces? 【发布时间】:2013-12-14 17:32:48 【问题描述】:

[编辑]

我指定了我的问题,也许它有更多信息:

我有一个包含很多行的文件,例如“string1 string2 int1 int2”,所以一行包含两个字符串和两个整数。我想逐行读取文件并将这四个数据推送到我的结构的向量中(它具有相同的变量类型和 num )。我的问题是,我该怎么做,因为 >> 运算符无论如何都不起作用。也不是 getline()。

和代码:

void FromFile(string filename)

    ifstream stream;
    stream.open(filename);
    adatok adattemp;
    while(stream.good())
    
        stream >> adattemp.agresszor >> adattemp.vedo >> adattemp.haborukezdete >> adattemp.haboruvege >> ws;
        cout << adattemp.agresszor;
        vektor.push_back(adattemp);
    
    stream.close();

【问题讨论】:

当你说“string string int int”时,每个字符串是一个单词,还是用引号括起来的字符串? 我会使用std::vector 是的,是两个单词和两个数字(4位/数字)。 您还有问题吗?您可以尝试打开流的异常,以便查看发生的任何错误:在打开文件之前输入“stream.exceptions(std::ifstream::failbit | std::ifstream::badbit);”。 【参考方案1】:

假设每个字符串只是一个单词,这应该可行:

#include <vector>
#include <string>
#include <fstream>

struct Entry 
    std::string s1;
    std::string s2;
    int i1;
    int i2;
;

std::vector<Entry> entries;

int main()

    std::ifstream file("yourfile");
    while (file.good()) 
        Entry entry;
        file >> entry.s1 >> entry.s2 >> entry.i1 >> entry.i2 >> std::ws;
        entries.push_back(entry);
    
    return 0;

注意:在阅读每一行的末尾包含&gt;&gt; std::ws 很重要。它占用了额外的空白。否则,您最终会在文件末尾添加一个额外的垃圾条目。

编辑:正如 Simple 在 cmets 中指出的那样,如果在读取文件时发生任何错误,上述代码将在 vector 的末尾存储一个垃圾条目。此代码将通过确保在存储条目之前没有错误来解决此问题:

Entry entry;
while (file >> entry.s1 >> entry.s2 >> entry.i1 >> entry.i2 >> std::ws)

    entries.push_back(entry);

【讨论】:

这不是读取输入的正确循环。它应该更像:Entry entry; while (file &gt;&gt; entry.s1 &gt;&gt; entry.s2 &gt;&gt; entry.i1 &gt;&gt; entry.i2 &gt;&gt; std::ws) entries.push_back(entry); 代码正确。这只是风格问题。优化编译器应该为两种形式生成相同的机器代码。 不,这是不正确的。您的代码会将无效数据插入vector。这不是优化问题。 它不会插入无效数据。为什么会这样?两者之间唯一真正的区别是,在您的版本中,循环条件隐式为while (!file.fail()),而我的是while (file.good())。除此之外,两者在语义上是等价的,并导致相同的行为。 它们完全不同。您的代码首先检查流中是否仍有内容,然后尝试从中读取四个内容,然后将它们插入到向量中而不检查读取是否成功。我的尝试读取这四件事,然后检查这些读取后流是否仍然有效,如果是则插入它们。【参考方案2】:

我会重载&gt;&gt; 并使用std::copy

#include<vector>
#include<algorithm>
//...
struct Reader 

    std::string str1;
    std::string str2;
    int int1;
    int int2;

    friend std::istream& operator << (std::istream& is, Reader &r)
    
       return is >> r.str1 >> r.st2 >> r.int1 >> r.int2 ;

    
;

std::vector<Reader> vec;
std::ifstream  fin("file_name");

std::copy(std::istream_iterator<Reader>(fin),
          std::istream_iterator<Reader>(),
          std::back_inserter(vec)
          ) ;

假设所有字符串和整数都用空格分隔

您也可以重载&gt;&gt; 以类似方式显示内容

【讨论】:

【参考方案3】:

由于您不知道文件大小,因此矢量会更适合 IMO。

while ( myFile >> string1 >> string2 >> myInt1 >> myInt2 ) 
  stringvec1.push_back( string1 );
  stringvec2.push_back( string2 );
  intvec1.push_back( myInt1 );
  intvec2.push_back( myInt2 );

编辑:

如果您正在阅读的 4 个变量对应于一个特定的具有逻辑意义的类,那么您可以拥有一个类/结构向量,其中所有这 4 个作为成员。

类似:

struct myFileVariables 
  std:string m_string1;
  std:string m_string2;
  int m_myInt1;
  int m_myInt2;
  myFileVariables ( string string1, string string2, int myInt1, int myInt2 ) :
                        m_string1( string1 ), m_string2( string2 ), m_myInt1( myInt1 ), 
                        m_myInt2( myInt2 ) 
;

在你的主要功能中:

    while ( myFile >> string1 >> string2 >> myInt1 >> myInt2 ) 
      myFileVariables newEntry( string1, string2, myInt1, myInt2 );
      myVec.push_back( newEntry );
    

【讨论】:

为什么不是适当定义的structs 向量? 数组的大小是多少? 我的意思是矢量,当然。 (但是你也可以在没有向量的情况下使用动态数组,所以没关系——你认为向量如何发挥它们的魔力?)——重点是“为什么不是结构”? 我有一个包含四个变量(两个字符串和整数)的结构,我从这个结构中创建了一个向量。非常感谢您的回答:) 这个循环将每一行都放入向量中(以及如何拆分它)?

以上是关于如何从文件中读取行并将其切割成碎片?的主要内容,如果未能解决你的问题,请参考以下文章

如何编写一个使用图像魔法将图像切割成碎片的bash脚本?

利用IO流把单个文件切割成碎片文件

将 GIF 切割成帧并将其转换为像素的程序占用了太多内存

三剑客之外的神器--cut命令切割行

将wav文件切割成段

cut文本切割工具