我想在屏幕上显示文本文件内容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 :(得分: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)
以下是建议的实施方案。如果不清楚,请随时询问有关工作原理的问题。
主要功能之一
使用类来封装数据和方法
#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;
}