代码之家  ›  专栏  ›  技术社区  ›  Fihop

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

c++
  •  3
  • Fihop  · 技术社区  · 15 年前

    我想得到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 回复  |  直到 11 年前
        1
  •  3
  •   procrastinate_later    15 年前

    将| |改为&是不够的&'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;
    }
    
        2
  •  7
  •   Jerry Coffin    15 年前

    while( !myfile.eof() ) 基本上总是错误的,因此无法正确检测文件的结尾。既然你用的是 getline

    while (getline(myfile, line1)) // ...
    

    同样,这里的逻辑是:

        if( line1 != "" || line1 != "\t" || line1 != "\n" || !line1.empty() )
            line2 = line1;
    

    …显然是错的。我猜你真的想 && 而不是 || 为了这个。从目前的情况来看,结果总是正确的,因为无论价值如何 line1 包含,它必须至少等于 仅包含新行 完全不包含任何内容(但这对于结果为假是必要的)。两者的测试 !line1.empty() line1 != "" 也显得多余。

        3
  •  5
  •   JH.    15 年前

    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;
    }
    
        4
  •  2
  •   sbi    15 年前


    您可以通过执行 myfile >> std::ws 在你打电话之前 std::getline() . 这将消耗所有前导空格。

    那么你的病情就降到 !line1.empty() . 当行中只包含 您的版本失败的空白。

        5
  •  1
  •   5andr0    12 年前

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