如何在 C++ 中对文本文件进行排序

How to do sorting in a text file in c++

我正在处理我的 C++(文件处理)项目,但卡在了一个点上

这是我的 .txt 文件

SNO, Name, NoOfPeopleLiked
1, The Shawshank Redemption, 77 
2, The Godfather, 20        
3, Into The Wild, 35
4, The Dark Knight, 55      
5, 12 Angry Men, 44
6, Schindler's List, 33
7, The Lord of the Rings: The Return of the King, 25
8, Pulp Fiction, 23
9, The Good, the Bad and the Ugly, 32   
10, The Lord of the Rings: The Fellowship of the Ring, 56

我必须显示关于 NoOfPeopleLiked 前 5 部电影 就这样:

示例输出

1, The Shawshank Redemption, 77
2, The Lord of the Rings: The Fellowship of the Ring, 56
3, The Dark Knight, 55
4, 12 Angry Men, 44
5, Into The Wild, 36

所以我必须进行排序,这是我目前所做的


void topFive()
{
    Movies v[20];       //class object array
    fstream top;        //for reading
    top.open("movies.txt");

    for (int h = 0; h < 10; h++) // reading from txt file
    {
        top >> v[h].serial >> v[h].movieName >> v[h].liked; 
    }
    // run loops two times: one for walking throught the array
    // and the other for comparison
    for (int step = 0; step < 5; ++step) 
    {
        for (int i = 0; i < 5 ; ++i) 
        {

            // To sort in descending order, change > to < in this line.
            if (v[i].liked > v[i + 1].liked) 
            {

                // swap if greater is at the rear position
                int temp = v[i].liked;
                v[i].liked = v[i + 1].liked;
                v[i + 1].liked = temp;
            }
        }
    }
    //  to print the array
    for (int i = 0; i < 5; ++i)
    {
        cout << v[i].serial << ", " << v[i].movieName << ", " << v[i].liked << endl;
    }
}   

老实说,我不知道如何完美地解决这个问题,我被这个问题困扰了大约 6-7 个小时,但仍然无法做出任何逻辑。我希望你们能帮助我并更好地指导我。提前致谢:)

我已经使用 std::regex 模块实现了下一个解决方案。加上一些字符串操作。以及原因分类!

在我的代码输入文件名为0302.txt,请在运行代码之前将其重命名为您需要的名称。

Try it online!

#include <vector>
#include <string>
#include <regex>
#include <fstream>
#include <tuple>
#include <iostream>
#include <stdexcept>
#include <algorithm>

int main() {
    try {
        auto StrTrim = [](std::string & str){
            str.erase(0, str.find_first_not_of("\t\n\v\f\r ")); // left trim
            str.erase(str.find_last_not_of("\t\n\v\f\r ") + 1); // right trim
        };
        std::ifstream ifile("0302.txt");
        std::string line;
        std::vector<std::string> lines;
        // Read all lines of file.
        while (std::getline(ifile, line)) {
            StrTrim(line);
            if (line.empty())
                continue;
            lines.push_back(line);
        }
        if (!lines.empty())
            lines.erase(lines.begin(), lines.begin() + 1); // remove first header line
        lines.erase(lines.begin(), lines.begin() + 1); // remove first header line
        std::vector<std::tuple<size_t, std::string, size_t>> data;
        std::regex re(R"((\d+)\s*,\s*(.+)?\s*,\s*(\d+))");
        for (auto const & line: lines) {
            std::smatch matches;
            if (std::regex_match(line, matches, re)) {
                if (matches.size() != 4)
                    throw std::runtime_error("Matched line with not 3 elements: '" + line + "'!");
                data.push_back(std::make_tuple(size_t(std::stoi(matches[1])), matches[2], size_t(std::stoi(matches[3]))));
            } else
                throw std::runtime_error("Unmatched line: '" + line + "'!");
        }
        std::sort(data.begin(), data.end(), [](auto const & l, auto const & r){
            return std::get<2>(l) > std::get<2>(r);
        });
        for (size_t i = 0; i < 5; ++i) {
            if (i >= data.size())
                break;
            std::cout << (i + 1) << "|" << std::get<0>(data[i]) << ", " << std::get<1>(data[i]) << ", " << std::get<2>(data[i]) << std::endl;
        }
        return 0;
    } catch (std::exception const & ex) {
        std::cout << "Exception: " << ex.what() << std::endl;
        return -1;
    }
}

输入文件0302.txt:

SNO, Name, NoOfPeopleLiked
1, The Shawshank Redemption, 77 
2, The Godfather, 20        
3, Into The Wild, 35
4, The Dark Knight, 55      
5, 12 Angry Men, 44
6, Schindler's List, 33
7, The Lord of the Rings: The Return of the King, 25
8, Pulp Fiction, 23
9, The Good, the Bad and the Ugly, 32   
10, The Lord of the Rings: The Fellowship of the Ring, 56

控制台输出:

1|1, The Shawshank Redemption, 77
2|10, The Lord of the Rings: The Fellowship of the Ring, 56
3|4, The Dark Knight, 55
4|5, 12 Angry Men, 44
5|3, Into The Wild, 35

您只需将文件中的字符串插入向量中,然后使用自定义比较器函数进行排序。此比较器函数可以从输入字符串中提取排名(假设排名在最后一个逗号之后,假设输入模式是统一的)并将其用于比较。代码:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <sstream>
#include <fstream>

using namespace std;

int get_rank(std::string input) {
    std::stringstream ss(input);
    std::string s;
    // keep extracting strings, last one would be your 'int' rank
    for(; ss >> s; );
    return std::atoi(s.c_str());
}

int main() {
    std::ifstream infile("movies.txt");
    std::vector<std::string> v;
    std::string line;
    std::getline(infile, line);
    for( ; getline( infile, line ); )
        v.push_back(line);
    std::sort(v.begin(), v.end(), [](std::string s1, std::string s2) -> bool { return get_rank(s1) > get_rank(s2); });
    for(int i = 0;i < 5;i++)
        cout << i + 1 << "," << v[i].substr(v[i].find(",") + 1) << endl;
    return 0;
}