Reputation: 517
I want to show the content of text file 20 lines on screen. User press 'n' to show next 20 lines and 'p' to show previous 20 lines. I don't know why its not working.
Here is my code:
#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);
}
}
}
Upvotes: 0
Views: 1006
Reputation: 7939
Here is a suggested implementation. Feel free to ask questions about how it works, if that is not clear.
Among the main features
Uses a class to encapsulate the data and methods
#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;
}
Upvotes: 0
Reputation: 917
I wouldn't do it so complex. Just read the file to a vector at program start and catch keyboard input (not tested):
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;
//...
Upvotes: 0
Reputation: 17248
First, s
is uninitialized, so f.getline(s,100)
is undefined behavior (it's writing to some arbitrary location in memory).
Next, your for
loop counts to 25, not 20. I assume this is a simple typo either in the code or the question/comment.
Finally, your seek logic is incorrect. You're rereading pos
each time you read a line of text, so you're only going to seek back one line, not 20/25 lines. Moreover the argument to seekg()
is an absolute position, so you shouldn't negate it.
EDIT: You should also initialize pos
to zero, so that if the first key the user presses is p
you seek to the beginning of the file. Otherwise if p
is the first keypress the behavior is undefined since you're seeking to an uninitialized offset.
You should also check for EOF each time you try to read a line, so that your program behaves correctly when the end of the file is reached.
Upvotes: 1