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

Я хочу показать содержимое текстового файла 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);
}
}
}

0

Решение

Первый, s неинициализирован, так f.getline(s,100) является неопределенным поведением (это запись в произвольное место в памяти).

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

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

РЕДАКТИРОВАТЬ: Вы также должны инициализировать pos в ноль, так что если первый ключ, который пользователь нажимает p Вы ищете начало файла. В противном случае, если p это первое нажатие клавиши, поведение которого не определено, так как вы ищете неинициализированное смещение.

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

1

Другие решения

Я бы не стал делать это так сложно. Просто прочитайте файл в векторе при запуске программы и поймайте ввод с клавиатуры (не проверено):

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;
//...
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
По вопросам рекламы [email protected]