我想在txt文件中获取最后一行但不是空行。
这是我的代码:
string line1, line2;
ifstream myfile(argv[1]);
if(myfile.is_open())
{
while( !myfile.eof() )
{
getline(myfile, line1);
if( line1 != "" || line1 != "\t" || line1 != "\n" || !line1.empty() )
line2 = line1;
}
myfile.close();
}
else
cout << "Unable to open file";
问题是我无法检查空行。
答案 0 :(得分:8)
好的,让我们从明显的部分开始吧。这个:while( !myfile.eof() )
基本上总是错误的,所以你不会正确地检测文件的结尾。由于您使用getline
来读取数据,因此您需要检查其返回值:
while (getline(myfile, line1)) // ...
同样,这里的逻辑:
if( line1 != "" || line1 != "\t" || line1 != "\n" || !line1.empty() )
line2 = line1;
......显然是错的。我猜你真的想要&&
代替||
。就目前而言,结果总是正确的,因为无论line1
包含什么值,它都必须至少一个这些值(即,它不能同时包含它们)选项卡和只包含换行符和根本不包含任何内容 - 但这对于结果必须是错误的。对!line1.empty()
和line1 != ""
的测试似乎也是多余的。
答案 1 :(得分:4)
为什么不向后阅读文件?这样您就不必扫描整个文件来完成此任务。似乎它应该是可能的。
int main(int argc, char **argv)
{
std::cout<<"Opening "<<fn<<std::endl;
std::fstream fin(fn.c_str(), std::ios_base::in);
//go to end
fin.seekg(0, std::ios_base::end);
int currpos = fin.tellg();
//go to 1 before end of file
if(currpos > 0)
{
//collect the chars here...
std::vector<char> chars;
fin.seekg(currpos - 1);
currpos = fin.tellg();
while(currpos > 0)
{
char c = fin.get();
if(!fin.good())
{
break;
}
chars.push_back(c);
currpos -= 1;
fin.seekg(currpos);
}
//do whatever u want with chars...
//this is the reversed order
for(std::vector<char>::size_type i = 0; i < chars.size(); ++i)
{
std::cout<<chars[i];
}
//this is the forward order...
for(std::vector<char>::size_type i = chars.size(); i != 0; --i)
{
std::cout<<chars[i-1];
}
}
return 0;
}
答案 2 :(得分:3)
将||更改为&amp;&amp;'s来检查行是否为空是不够的。如果有七个空格,一个制表符,另外三个空格,最后一个换行怎么办?您不能列出只获取一行空格的所有方法。相反,检查行中的每个字符以查看它是否为空格。
在此代码中,如果在行中找到任何非空格字符,则is_empty
将为false。
bool is_empty = true;
for (int i = 0; i < line.size(); i++) {
char ch = line[i];
is_empty = is_empty && isspace(ch);
}
完整解决方案:
#include <iostream>
#include <fstream>
#include <cctype>
#include <string>
using namespace std;
int main(int argc, char* argv[]) {
string line;
string last_line;
ifstream myfile(argv[1]);
if(myfile.is_open())
{
while( getline(myfile, line) ) {
bool is_empty = true;
for (int i = 0; i < line.size(); i++) {
char ch = line[i];
is_empty = is_empty && isspace(ch);
}
if (!is_empty) {
last_line = line;
}
}
myfile.close();
cout << "Last line: " << last_line << endl;
}
else {
cout << "Unable to open file";
}
return 0;
}
答案 3 :(得分:2)
除了其他人说的话:
在致电myfile >> std::ws
之前,您可以通过std::getline()
来避免阅读空白。这将消耗所有前导空格。
然后你的病情减少到!line1.empty()
。当该行只包含几个空格时,这也适用于您的版本失败的情况。
答案 4 :(得分:1)
我无法根据我的需要谷歌一个合适的get_last_line函数,这就是我想出的。您甚至可以通过调用instream get_last_line函数来读取多个非空的最后一行,而无需重置搜索器。它支持1个仅限char的文件。我添加了reset参数,可以将其设置为ios_base :: end,以便在读取最后一行后允许输出操作
std::string& get_last_line(
std::istream& in_stream,
std::string& output = std::string(),
std::ios_base::seekdir reset = std::ios_base::cur)
{
output.clear();
std::streambuf& buf = *in_stream.rdbuf();
bool text_found = false;
while(buf.pubseekoff(-1, std::ios_base::cur) >= 0)
{
char c = buf.sgetc();
if(!isspace(c))
text_found = true;
if(text_found)
{
if(c == '\n' || c == -1)
break;
output.insert(0, sizeof c, c);
}
}
buf.pubseekoff(0, reset);
return output;
}
std::string& get_last_line(
const std::string& file_name,
std::string& output = std::string())
{
std::ifstream file_in(
file_name.c_str(),
std::ios_base::in | std::ios_base::ate);
if(!file_in.is_open())
{
output.clear();
return output;
}
get_last_line(file_in, output);
file_in.close();
return output;
}