以c ++方式读取文本文件的内容

时间:2013-12-27 16:31:00

标签: c++ file text lines

我想在屏幕上显示文本文件内容20行。 用户按'n'显示接下来的20行,'p'显示前20行。 我不知道为什么它不起作用。

这是我的代码:

#include<fstream.h>
#include<process.h>
#include<conio.h>
void main()
{
    clrscr();
    char *s,key;
    int pos;
    fstream f;
    f.open("menu.cpp",ios::in);
    while(1)
    {
        key=getch();
        switch(key)
        {
            case 'n':
                    //read more 20 lines
                    clrscr();
                    for(int i=1;i<=25;i++)
                    {
                        f.getline(s,100);
                        pos=f.tellg();
                        cout<<s<<endl;
                    }
                    break;
            case 'p':   //read previous 20 lines
                    clrscr();
                    f.seekg(-pos);
                                        for(int i=1;i<=25;i++)
                    {
                        f.getline(s,100);

                        cout<<s<<endl;
                    }
                                        break;
            case 'e':
                    clrscr();
                    cout<<"exit";
                    exit(0);
        }
    }
}

3 个答案:

答案 0 :(得分:1)

首先,s未初始化,因此f.getline(s,100)是未定义的行为(它写入内存中的某个任意位置)。

接下来,您的for循环计为25,而不是20.我认为这是代码或问题/评论中的简单拼写错误。

最后,您的搜索逻辑不正确。每次阅读一行文字时,你都会重新阅读pos,所以你只需要找回一行,而不是20/25行。此外,seekg()的论证是一个绝对的位置,所以你不应该否定它。

编辑:你还应该将pos初始化为零,这样如果用户按下的第一个键是p,你就会找到文件的开头。否则,如果p是第一个按键,则行为未定义,因为您正在寻找未初始化的偏移量。

每次尝试读取一行时都应检查EOF,以便在到达文件末尾时程序正常运行。

答案 1 :(得分:0)

我不会这么复杂。只需在程序启动时将文件读取到矢量并捕获键盘输入(未测试):

std::vector<std::string> fileContent;
std::string line;
while (std::getline(infile, line))
    fileContent.push_back(line);  // in the end, the file is stored in the STL container

unsigned long lineTracker = 0;  //to make the whole thing buffer-overflow-safe
while(true)
{
    key = getch();
    switch(key)
    {
        case 'n':
            //read more 20 lines
            clrscr();
            for (unsigned i = 0; i < 20 && lineTracker < fileContent.size(); ++i, ++lineTracker)
                std::cout << fileContent[lineTracker];
            break;

        case 'p':
            clrscr();
            lineTracker -= 20;
            for (unsigned i = 0; i < 20 && lineTracker >= 0; ++i, ++lineTracker)
                std::cout << fileContent[lineTracker];
            break;
//...

答案 2 :(得分:0)

以下是建议的实施方案。如果不清楚,请随时询问有关工作原理的问题。

主要功能之一

  • 使用std :: string而不是char *
  • 分为小功能
  • 使用类来封装数据和方法

    #include <string>
    #include <vector>
    #include <iostream>
    #include <fstream>
    #include <conio.h>  // for getch()
    
    class CFileViewer
    {
    public:
        CFileViewer(const std::string &sFileName);
        void Show();
    
    protected:
        void InitFile(const std::string &sFileName);
        void ShowPage();
        bool GetInput();
        static size_t LinesPerPage() { return 25; };
    
    private:
        size_t                 m_nPage;
        std::vector<long long> m_vPos;
        std::ifstream          m_file;
    };
    
    CFileViewer::CFileViewer(const std::string &sFileName)
    : m_nPage(0)
    {
        m_vPos.push_back(0);
        InitFile(sFileName);
    }
    
    void CFileViewer::InitFile(const std::string &sFileName)
    {
        m_file.open(sFileName);
        if (!m_file)
            throw std::runtime_error("cannot open file");
    }
    
    void CFileViewer::ShowPage()
    {
        // clear any previous eof state
        m_file.clear();
    
        // goto required part of file
        m_file.seekg(m_vPos.at(m_nPage));
    
        std::string s;
        for (size_t i=0; i<LinesPerPage(); ++i)
        {
            if (std::getline(m_file, s))
                std::cout << s << std::endl;
            else if (m_file.eof())
                break;
            else
                throw std::runtime_error("error reading file");
        }
        // if we just read a page and it was the last in m_vPos, save
        // current pos as start of next page
        // NB m_nPage will not be incremented if we're at eof.
        if (!m_file.eof() && ++m_nPage == m_vPos.size())
            m_vPos.push_back(m_file.tellg());
    }
    
    bool CFileViewer::GetInput()
    {
        while (1)
        {
            switch (_getch())
            {
                case 'p':
                    if (m_nPage > 1)
                        m_nPage -= 2;
                    else
                        m_nPage = 0;
                    return true;
    
                case 'e':
                    std::cout << "exit\n";
                    return false;
    
                case 'n':
                    if (!m_file.eof())
                        return true;
                    // else
                    std::cout << "at eof\n";
                    // fall through
    
                default:
                    putchar('\a');
            }
        }
    }
    
    void CFileViewer::Show()
    {
        do
        {
            ShowPage();
        }
        while (GetInput());
    }
    
    
    int main()
    {
        try
        {
            CFileViewer fv("menu.txt");
            fv.Show();
        }
        catch (std::exception &e)
        {
            std::cerr << e.what() << std::endl;
        }
        return 0;
    }