Читайте содержимое текстового файла в строчках с ++

0

Я хочу показать содержимое текстового файла 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);
        }
    }
}
  • 1
    Возможно, вам также следует опубликовать информацию о том, что на самом деле происходит, чтобы людям не приходилось компилировать и запускать программу. И / или любые сообщения об ошибках, которые вы получаете.
  • 0
    о ... я забыл упомянуть, что ... следующие 20 строк отображаются правильно, но предыдущие 20 строк не отображаются, когда я нажимаю 'p', и после этого, когда я нажимаю 'e', программа также не закрывается.
Теги:
file
text
lines

3 ответа

1

Во-первых, s не инициализируется, поэтому f.getline(s,100) является неопределенным поведением (он записывается в произвольное место в памяти).

Затем ваш цикл for равен 25, а не 20. Я предполагаю, что это простая опечатка либо в коде, либо в вопросе/комментарии.

Наконец, ваша логика поиска неверна. Вы перечитываете pos каждый раз, когда вы читаете строку текста, поэтому вы будете искать только одну строку, а не 20/25 строк. Более того, аргумент seekg() является абсолютной позицией, поэтому вы не должны его отрицать.

EDIT: вы также должны инициализировать pos до нуля, так что если первый ключ, который пользователь нажимает, - p вы начинаете поиск в начале файла. В противном случае, если p является первым нажатием клавиши, поведение не определено, так как вы ищете неинициализированное смещение.

Вы также должны проверять EOF каждый раз, когда пытаетесь прочитать строку, чтобы ваша программа вела себя правильно, когда достигнут конец файла.

  • 0
    но я думал, что функция seekg () перемещает указатель файла назад, если я предоставлю -ve значение pos. Итак, наконец, что вы предлагаете?
  • 0
    @ArunSharma Только если вы используете версию с двумя аргументами и задаете ios_base::cur . Версия с 1 аргументом seekg() занимает абсолютную позицию в файле. См. Cplusplus.com/reference/istream/istream/seekg
Показать ещё 1 комментарий
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;
    }
    
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;
//...

Ещё вопросы

Сообщество Overcoder
Наверх
Меню