【问题标题】:print out the last 10 lines of a file打印文件的最后 10 行
【发布时间】:2011-04-26 18:43:08
【问题描述】:

我希望可以选择打印文本文件的最后 10 行。使用这个程序,我已经能够读取整个文本文件,但我不知道如何操作保存文本文件的数组,有什么帮助吗?

// Textfile output
#include<fstream>
#include<iostream>
#include<iomanip>
using namespace std;

int main() {
    int i=1;
    char zeile[250], file[50];
    cout << "filename:" << flush;
    cin.get(file,50);                          ///// (1)
    ifstream eingabe(datei , ios::in);          /////(2)
    if (eingabe.good() ) {                       /////(3)           
       eingabe.seekg(0L,ios::end);               ////(4)
       cout << "file:"<< file << "\t"
            << eingabe.tellg() << " Bytes"       ////(5)
            << endl;
       for (int j=0; j<80;j++)
           cout << "_";
           cout << endl;
       eingabe.seekg(0L, ios::beg);              ////(6)
       while (!eingabe.eof() ){                  ///(7)
             eingabe.getline(zeile,250);         ///(8)
             cout << setw(2) << i++
                  << ":" << zeile << endl;
             }      
           }
    else
        cout <<"dateifehler oder Datei nicht gefunden!"
             << endl;
            
             return 0;
    }

【问题讨论】:

  • 虽然您可能已经知道这一点,但 unix tail 命令完全符合您的要求。
  • @darioo:这个问题听起来像家庭作业。
  • 顺便说一句,如果您寻找到文件的末尾然后向后寻找起点,而不是解析整个文件。

标签: c++ file cout tail


【解决方案1】:

试试这个:

#include <list>
#include <string>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>

// 一个知道如何使用操作符读取一行的类 >>

struct Line
{
    std::string theLine;
    operator std::string const& () const { return theLine; }
    friend std::istream& operator>>(std::istream& stream, Line& l)
    {
        return std::getline(stream, l.theLine);
    }
};

// 只保存最后n行的循环缓冲区。

class Buffer
{
    public:
        Buffer(size_t lc)
            : lineCount(lc)
        {}
        void push_back(std::string const& line)
        {
            buffer.insert(buffer.end(),line);
            if (buffer.size() > lineCount)
            {
                buffer.erase(buffer.begin());
            }
        }
        typedef std::list<std::string>      Cont;
        typedef Cont::const_iterator        const_iterator;
        typedef Cont::const_reference       const_reference;
        const_iterator begin()  const       { return buffer.begin(); }
        const_iterator end()    const       { return buffer.end();}

    private:
        size_t                      lineCount;
        std::list<std::string>      buffer;
};    

// 主要

int main()
{
    std::ifstream   file("Plop");
    Buffer          buffer(10);

    // Copy the file into the special buffer.
    std::copy(std::istream_iterator<Line>(file), std::istream_iterator<Line>(),
            std::back_inserter(buffer));

    // Copy the buffer (which only has the last 10 lines)
    // to std::cout
    std::copy(buffer.begin(), buffer.end(),
            std::ostream_iterator<std::string>(std::cout, "\n"));
}

【讨论】:

    【解决方案2】:

    基本上,您不会将文件内容保存到任何数组中。以下示例将为您提供一个良好的开端:

    #include <iostream>
    #include <vector>
    #include <string>
    
    int main ( int, char ** )
    {
        // Ask user for path to file.
        std::string path;
        std::cout << "filename:";
        std::getline(std::cin, path);
    
        // Open selected file.      
        std::ifstream file(path.c_str());
        if ( !file.is_open() )
        {
            std::cerr << "Failed to open '" << path << "'." << std::endl;
            return EXIT_FAILURE;
        }
    
        // Read lines (note: stores all of it in memory, might not be your best option).
        std::vector<std::string> lines;
        for ( std::string line; std::getline(file,line); )
        {
            lines.push_back(line);
        }
    
        // Print out (up to) last ten lines.
        for ( std::size_t i = std::min(lines.size(), std::size_t(10)); i < lines.size(); ++i )
        {
            std::cout << lines[i] << std::endl;
        }
    }
    

    避免将整个文件存储到内存中可能更明智,因此您可以通过这种方式重写最后两个段:

    // Read up to 10 lines, accumulating.
    std::deque<std::string> lines;
    for ( std::string line; lines.size() < 0 && getline(file,line); )
    {
        lines.push_back(line);
    }
    
    // Read the rest of the file, adding one, dumping one.
    for ( std::string line; getline(file,line); )
    {
        lines.pop_front();
        lines.push_back(line);
    }
    
    // Print out whatever is left (up to 10 lines).
    for ( std::size_t i = 0; i < lines.size(); ++i )
    {
        std::cout << lines[i] << std::endl;
    }
    

    【讨论】:

      【解决方案3】:

      eof() 函数不像你那样做,而且似乎有一百万其他 C++ 新手认为它会做。它不能预测下一次读取是否有效。在 C++ 中与任何其他语言一样,您必须检查每个读取操作的状态,而不是读取之前输入流的状态。所以规范的 C++ 读取行循环是:

      while ( eingabe.getline(zeile,250) ) {
          // do something with zeile
      }
      

      另外,你应该读入std::string,并去掉那个 250 的值。

      【讨论】:

        【解决方案4】:

        做一个有 10 个槽的循环缓冲区,在读取文件行时,将它们放入这个缓冲区。完成 thr 文件后,执行 position++ 以转到第一个元素并将它们全部打印出来。 如果文件少于 10 行,请注意 null 值。

        【讨论】:

          【解决方案5】:
          1. 有一个大小为 10 的字符串数组。
          2. 读取第一行并存储到数组中
          3. 继续阅读,直到数组已满
          4. 一旦数组已满,请删除第一个条目,以便您可以输入新行 重复第 3 步和第 4 步,直到文件读取完毕。

          【讨论】:

            【解决方案6】:

            我在这里调查建议的方法,并在我的博客文章中描述所有内容。有一个更好的解决方案,但你必须跳到最后并坚持所有需要的行:

            std::ifstream hndl(filename, std::ios::in | std::ios::ate);
            // and use handler in function which iterate backward
            void print_last_lines_using_circular_buffer(std::ifstream& stream, int lines)
            {
                circular_buffer<std::string> buffer(lines);
            
                std::copy(std::istream_iterator<line>(stream),
                          std::istream_iterator<line>(),
                          std::back_inserter(buffer));
            
                std::copy(buffer.begin(), buffer.end(),
                        std::ostream_iterator<std::string>(std::cout));
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2022-06-15
              • 2016-01-19
              • 1970-01-01
              • 1970-01-01
              • 2012-10-14
              相关资源
              最近更新 更多