C++ 需要帮助对二维字符串数组进行排序

时间:2021-06-02 02:38:48

标签: c++ arrays sorting

我对字符串 Table[X][Y] 排序有点困难。正如标记的那样,我使用 C++,并且必须使用标准库并使其适用于所有 C++(不仅是 C++ 11)。

Table 的大小是固定的(X 读取文件有多少行,Y 是固定的,因为每行都有不同的“属性”)。

当我创建表时,它的每个部分都是从以前从文件中读取并存储在字符串中的内容中作为 Table[X][Y] = stringX.data(); 获得的。我在第一列中有数字(我将用作排序标准的那个)、姓名、地址等在其他列中。

创建Table的部分是:

Table[i][0] = string1.data();
Table[i][1] = string2.data();
Table[i][2] = string3.data();
Table[i][3] = string4.data();
Table[i][4] = string5.data();

其中“i”是 while(fgets) 的当前“迭代”,它一次从文件中读取一行,执行一些操作并在这些字符串中存储该行每一部分的“最终值”阅读。

我必须使用第一列作为条件以降序对表格进行排序。

让我们想象一下表格是这样的:Table[4][3]

20 | Jhon  | 14th July 
2  | Mary  | 9th June
44 | Mark  | 10th December
1  | Chris | 4th Feb

我需要这样的输出:

44 | Mark  | 10th December
20 | Jhon  | 14th July 
2  | Mary  | 9th June
1  | Chris | 4th Feb

我一直在阅读几个问题和页面,他们对 int/chars 数组进行排序或将数组转换为向量,然后使用它们。我正在尝试对我拥有的字符串 Table 进行排序而不进行任何转换(如果可能的话,我不知道)。

我不知道我是否设法解释了这个问题和我已经足够清楚的情况。我没有把我所有的代码都放在里面,因为除了字符串表的声明和然后作为 string.data 放置在表中的字符串之外,其余的代码与表和排序过程无关。代码打开文件,逐行读取,从一些分隔符和特殊字符中过滤我需要的信息,并将每个“排名标准”​​放入一个字符串,然后在评估每个标准并给出一个“排名”后分配一个“排名”总分(然后存储在“string1”中)。 完成所有这些后,我创建字符串 Table[x][y] 并将过滤和处理过的信息一次一行放置在该表中(因为我在从文件中读取每一行时对其进行赋值)。

唯一剩下的就是将表格从得分最高的到最后一个排序,然后创建一个包含前 10 名的文件。

我提前感谢并感谢您花时间阅读本文以及您可以提供的任何提示、信息、代码或来源。

1 个答案:

答案 0 :(得分:0)

首先,正如评论中提到的,在 C++ 中使用 std::vector 完成了一个变长数组。您当前使用的语法

std::string Table[X][Y]

其中 XY 是运行时变量,不是合法的 C++。鉴于您的示例,标准的 C++ 声明将是这样的:

std::vector<std::array<std::string, 3>> Table;

所以让我们假设这就是您要使用的。


下一步是根据第一列对数据进行排序。这可以通过使用 std::sort 算法函数以及指示您使用第一列作为排序条件的适当谓词来完成。

以下是一个使用您的数据的简短示例,说明了这一切是如何完成的:

#include <vector>
#include <array>
#include <iostream>
#include <algorithm>
#include <string>

int main()
{
    std::vector<std::array<std::string, 3>> Table;

    // Set up the test data  
    Table.push_back({"20", "Jhon", "14th July"});
    Table.push_back({"2", "Mary", "9th June"});
    Table.push_back({"44", "Mark", "10th December"});
    Table.push_back({"1", "Chris", "4th Feb"});

    std::cout << "Before sort:\n\n";
    for (auto& s : Table)
        std::cout << s[0] << " | " << s[1] << " | " << s[2] << "\n";
        
    std::cout << "\n\nAfter sort:\n\n";
    
    // Sort the data using the first column of each `std::array` as the criteria
    std::sort(Table.begin(), Table.end(), [&](auto& a1, auto& a2) 
              { return std::stoi(a1[0]) > std::stoi(a2[0]); });

    // Output the results: 
    for (auto& s : Table)
        std::cout << s[0] << " | " << s[1] << " | " << s[2] << "\n";
}

这是最终的输出:

Before sort:

20 | Jhon | 14th July
2 | Mary | 9th June
44 | Mark | 10th December
1 | Chris | 4th Feb


After sort:

44 | Mark | 10th December
20 | Jhon | 14th July
2 | Mary | 9th June
1 | Chris | 4th Feb

输出需要一些格式,但这并不重要。

请记住,数据的来源很重要,无论是来自文件还是硬编码,如上例所示。无论您如何填充 Table,这取决于您。目标是向您展示填充数据后如何对数据进行排序。


我们做的第一件事是创建表格并用测试数据填充它。请注意,向量有一个 push_back 函数来向向量添加条目。

然后对 std::sort 的调用有一个谓词函数(lambda),其中谓词被赋予两个项目,在这种情况下,它将是两个 std::array 的引用。然后目标是返回是否应将第一个 std::array(在本例中为 a1)放在第二个 std::array (a2) 之前。

注意我们只关心第一列,所以我们只需要考虑每个数组的array[0],并比较它们。

还要注意,由于 array[0] 是 std::string,我们根本无法按字典顺序比较它——我们需要将字符串转换为 int 并比较 int价值。这就是 std::stoi 调用转换为整数的原因。

关于排序谓词的最后一件事是我们想要一个降序排序。因此,要使用的比较运算符是 > 而不是“传统的”<(它会以升序方式排序)。

希望这能解释代码的作用。


编辑:

由于您试图让这段代码在 C++98 中工作,最简单的方法是

  1. 改为std::vector<std::vector<std::string>>而不是std::vector<std::array<std::string, 3>>

  2. 不要使用 C++11 提供的大括号初始化

  3. 使用比较函数而不是 lambda。

鉴于此,这里是 C++98 的代码:

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

bool SortFirstColumn(const std::vector<std::string>& a1,
                     const std::vector<std::string>& a2)
{
   return atoi(a1[0].c_str()) > atoi(a2[0].c_str());
}
 
int main()
{
    std::vector<std::vector<std::string>> Table;

    // Set up the test data  
    std::vector<std::string> vect(3);
    vect[0] = "20"; 
    vect[1] = "Jhon"; 
    vect[2] = "14th July"; 
    Table.push_back(vect);
    vect[0] = "2"; 
    vect[1] = "Mary"; 
    vect[2] = "9th June"; 
    Table.push_back(vect);
    vect[0] = "44"; 
    vect[1] = "Mark"; 
    vect[2] = "10th December"; 
    Table.push_back(vect);
    vect[0] = "1"; 
    vect[1] = "Chris"; 
    vect[2] = "10th December"; 
    Table.push_back(vect);

    std::cout << "Before sort:\n\n";
    for (size_t i = 0; i < Table.size(); ++i)
        std::cout << Table[i][0] << " | " << Table[i][1] << " | " << Table[i][2] << "\n";
        
    std::cout << "\n\nAfter sort:\n\n";
    
    // Sort the data using the first column of each `std::vector<std::string>` as the criteria
    std::sort(Table.begin(), Table.end(), SortFirstColumn);

    // Output the results: 
    for (size_t i = 0; i < Table.size(); ++i)
        std::cout << Table[i][0] << " | " << Table[i][1] << " | " << Table[i][2] << "\n";
}