如何获取文本文件中的最后一行但不是空行

时间:2010-07-21 03:50:49

标签: c++

我想在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";

问题是我无法检查空行。

5 个答案:

答案 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;
}