C++ 到达文件末尾后从文件中读取
我有一个名为C++ 到达文件末尾后从文件中读取,c++,visual-studio-2012,eof,seekg,C++,Visual Studio 2012,Eof,Seekg,我有一个名为readNextString(ifstream&file,char*&pBuffer)的函数,它从文件中提取下一个字符串,直到到达,“或”\n',删除字符串开头和结尾的空格,将其余字符串保存在pBuffer中,如果一切正常,则返回true,否则返回false。在到达文件末尾之前,一切都正常工作。设置eof标志时,我无法移动get指针。 我试过这个: if(file.eof()) { file.clear(); file.seekg(0 , ios::end) } …然后
readNextString(ifstream&file,char*&pBuffer)
的函数,它从文件中提取下一个字符串,直到到达,“
或”\n'
,删除字符串开头和结尾的空格,将其余字符串保存在pBuffer中,如果一切正常,则返回true,否则返回false。在到达文件末尾之前,一切都正常工作。设置eof
标志时,我无法移动get指针。
我试过这个:
if(file.eof())
{
file.clear();
file.seekg(0 , ios::end)
}
…然后删除字符串末尾的空白。这几乎起到了作用。函数提取不带空格的字符串,但得到一个无限循环
我的实际问题是:如何检查下一个字符是否为EOF
,如果不能,是否有其他方法可以这样做
以下是我的实际功能:
bool readNextString(ifstream &file , char* &pBuffer)
{
if(file.eof()){
return false;
}
for(; file.good() && isWhitespace(file.peek()) && !file.eof() ; file.seekg(1 , ios::cur))
;
if(file.eof()){
cout << "The file is empty.\n";
return false;
}else{
streamoff startPos = file.tellg();
cout << "startPos : " << startPos << endl;
for(;file.good() && file.peek()!='\n' && file.peek()!=',' && file.peek()!= EOF; file.seekg(1 , ios::cur))
;
streamoff A = file.tellg();
cout << "A : " << A << endl;
file.seekg(-1 , ios::cur);
for(;file.good() && isWhitespace(file.peek()) ; file.seekg(-1 , ios::cur))
;
file.seekg(2 , ios::cur);
streamoff endPos = file.tellg();
cout << "endPos : " << endPos << endl;
pBuffer = new char[endPos-startPos];
if(pBuffer)
{
file.seekg(startPos , ios::beg);
file.get(pBuffer , endPos-startPos , ',' || '\n');
for(;file.good() && file.peek()!='\n' && file.peek()!=',' && file.peek()!= EOF; file.seekg(1 , ios::cur))
;
file.seekg(2 , ios::cur);
streamoff temp = file.tellg();
cout << "temp : " << temp << endl;
return true;
}else{
cout << "Error! Not enough memory to complete the task.\nPlease close some applications and try again.\n";
return false;
}
}
}
bool readNextString(ifstream&file,char*&pBuffer)
{
if(file.eof()){
返回false;
}
对于(;file.good()&&isWhitespace(file.peek())&&&!file.eof();file.seekg(1,ios::cur))
;
if(file.eof()){
库特
如何检查下一个字符是否为EOF
像这样
if (file.peek() == EOF)
{
// next char is EOF
...
}
首先,不要使用seek跳过空白。只需获取
性格和性格是不可能的
第二,你似乎误解了
istream::good()
和istream::eof()
。从来没有
无论何时,istream::good()
合适,并且
istream::eof()
通常仅在输入完成后才适用
失败。对于跳过空白的循环,通常
解决办法是:
while ( isspace( file.peek() ) && file.peek() != EOF ) {
file.get(); // ignore read character...
}
其他循环也有类似的注释,除了
您不希望忽略读取的字符。要收集
字符,直到下一个,”
,例如:
std::string field;
while ( file.peek() != ',' && file.peek() != EOF ) {
field.push_back( file.get() );
}
(和您的文件.get(pBuffer,endPos-startPos,','| |'\n')
当然并没有达到您期望的效果;表达式,'
||“\n”
将始终计算为true
,在转换时
到字符
,是'\01
)
最后,尽管上述策略会起作用,但它更可取
将较大的文本单位输入到std::stream
,并解析
也就是说,如果文本是面向行的,请使用以下内容:
std::string line;
while ( std::getline( file, line ) ) {
// Parse line, using std::istringstream if appropriate,
// although this doesn't seem to be the case for your code.
}
这比你正在做的事情要简单几个数量级。好的。我做的不是这样!getline()为了胜利!:D
这是我的代码(这次可读性更强):
bool readNextString(ifstream&file,char-pBuffer[])
{
while(isWhitespace(file.peek())&&&!file.eof())
忽略(1);
如果(!file.eof())
{
streamoff start=file.tellg();
stringstream to comma;
if(file.getline(pBuffer,200,,'))
{
仅供参考,你真的不想从这样的文件中解析字符串。要么将整个文件读入缓冲区,要么一次将大块文件读入缓冲区并在内存中解析。不要进行一百万次的读取。这很慢。而对于这一点,实际上更为复杂。@Dave逐字读取并不一定慢;istream
进行缓冲。但是,使用seek速度很慢;在许多实现中,seek会导致缓冲区丢失,每个字符会有两个系统调用。(不必这样做,但在缓冲区内进行seek应该非常罕见,库不会对其进行优化。)是的,这在我的代码中,但我不能正常工作。当我试图找出下一个“,”,“\n”或在本例中是EOF时,问题出现在第二个for循环中。当我检查get pointer(tellg)的位置时,在我的代码中,我将其保存为“A”,它告诉我位置是-1…:(我不确定,但我认为tellg会失败,因为您试图读取文件的结尾。尝试在调用peek之前调用tellg,而不是之后调用。或者尝试简化。我还没有理解您的问题,或者阅读其他答案,但您的代码看起来确实非常复杂。@john,这是一个很好的观点。Oncefile.peek()
返回文件结尾,tellg
无效,将失败。在输入文件上使用多次传递以进行解析的整个策略已被打破。感谢您提供的详细答案,但我认为这对我没有多大帮助…1.您给我的第一个代码几乎与我的相同,并且无法正常工作。该文件。peek()!=EOF失败。2.第二个代码实际上可能会有帮助…3.关于我的代码-我不太理解您,但我认为它工作得很好,因为问题只出现在文件的末尾…4.对于getline()-这是我的第二个选择,但我想了解如何使用seekg实现这一点…使用此方法一定有办法实现这一点…再次-非常感谢您的帮助:)@dragonatorfile.peek()
永不失败。Iffile.peek()
返回EOF
,这可能是因为您在文件末尾,或者您已经遇到了某种错误。单独的代码段用于解释不同的错误:一旦您到达文件末尾,文件
失败,并且没有其他操作(包括查找)对于3,我引用的行的结束条件是字符0x01
。或者您读取准确的计数:您可能想要的是file.read(pBuffer,endPos-startPos)
(但这仍然不是一个好的解决方案)。@dragonator如果目标只是获得gseek()的经验
:您可能必须在每次搜索之前立即调用file.clear()
,或者使用C++11(它指定在seekg
中清除eofbit
,然后再执行其他操作)。
std::string line;
while ( std::getline( file, line ) ) {
// Parse line, using std::istringstream if appropriate,
// although this doesn't seem to be the case for your code.
}
bool readNextString(ifstream &file , char pBuffer[] )
{
while(isWhitespace(file.peek()) && !file.eof())
file.ignore(1);
if(!file.eof())
{
streamoff start = file.tellg();
stringstream toComma;
if(file.getline(pBuffer , 200 , ','))
{
toComma << pBuffer;
toComma.getline(pBuffer ,200, '\n');
int i=strlen(pBuffer)-1;
for(; isWhitespace(pBuffer[i]) ;i--)
;
pBuffer[i+1] = '\0';
file.clear();
file.seekg(start + strlen(pBuffer) , file.beg);
return true;
}else return false;
}
return false;
}
void printCities()
{
ifstream city ;
city.open("cities.txt", fstream::in);
if(city.is_open())
{
if(!isEmpty(city))
{
char currCity[200];
int counter = 1;
while(readNextString(city , currCity) && counter < 10)
cout << counter++ << ". " << currCity << endl;
}else
cout << "There are no cities added.\n";
city.close();
}else
cout << "Error by opening 'cities.txt'.Make sure that the file exist and try again.\n";
}