【问题标题】:Sorting elements in dynamic array by same name按相同名称对动态数组中的元素进行排序
【发布时间】:2021-04-05 11:34:56
【问题描述】:

我有一个用 C++ 编写的程序,它会生成具有相同教师姓名的文件,这些文件还要按时间顺序(按天和小时)排序:

<hour> <day> <group> <surname> <subject>

(这里是example.txt内容):

10:15-11:30 Friday gr1 Smith Programming
07:10-09:15 Wednesday gr2 Taylor InternetofThings
11:00-12:00 Monday gr2 Smith Java
10:20-11:45 Thursday gr1 Taylor Matchematic

工作后,程序生成文件:

Smith.txt :

11:00-12:00 Monday gr2 Java
10:15-11:30 Friday gr1 Programming

Taylor.txt :

07:10-09:15 Wednesday gr2 InternetofThings
10:20-11:45 Thursday gr1 Matchematic

我已经设法将 txt 文件中的数据加载到动态数组中(代码如下)。我不知道如何进行名称搜索和排序(名称可以不同,行数也可以不同)。我正在考虑一个循环,它会从动态数组的“姓”变量中查找相同的字母,但我不知道如何实现它。

struct Line {
  string hour;
  string day;
  string group;
  string surname;
  string subject; 
};

void readLine(ifstream& file, Line& line) {
  file >> line.hour >> line.day >> line.group >> line.surname >> line.subject;
}

void readLineTab(ifstream& file, Line* lineTab, const int numOfLines) {
  for (int i = 0; i < numOfLines; i++) {
    readLine(file, lineTab[i]); 
  }
}

void printLine(const Line& line) {
  cout << line.hour << " " << line.day << " " << line.group << " " << line.surname << " " << 
  line.subject << endl;
}

void printLineTab(Line* lineTab, const int size) {
  for (int i = 0; i < size; i++) {
    printLine(lineTab[i]);
  }
}

int checkFile(string& filePath, int& numOfLines) {
  ifstream file;
  file.open(filePath.c_str());
  if (file.fail()) {
    cerr << "Error file open: " << filePath << endl;
    file.close();
    return 1;
  }
  string line;
  int lineNr = 0;
  while (getline(file, line)) {
    lineNr++;
    numOfLines++;
  }
  file.close();
  return 0;
}

int main(int argc, char** argv) {
  int numOfLines = 0; 
  ifstream file; 
  string filePath = "example.txt"; 

  if (checkFile(filePath, numOfLines)) {
    return 1;
  }

  Line* lineTab = new Line[numOfLines];

  file.open(filePath.c_str());
  if (file.fail()) {
    cerr << "Error file open: " << filePath << endl;
    return 1;
  }

  readLineTab(file, lineTab, numOfLines);
  printLineTab(lineTab, numOfLines);

  delete[] lineTab;
  file.close();
  return 0;
}

【问题讨论】:

  • 您可能需要std::map&lt;std::string,Line&gt;std::unordered_map&lt;std::string,Line&gt; 来执行此操作,但请注意,这些密钥字符串必须是唯一的。如果不是,您将需要std::multimap&lt;std::string,Line&gt;。你可以在这里找到这些类的文档:en.cppreference.com/w/cpp/container
  • 您是否被限制使用标准库中的容器类?
  • 一种简单的方法是只读取一行,检查是否存在教师文件,如果不存在则创建一个。如果确实存在,请将数据附加到文件中。
  • std::string.find(str2) 是用于在str中查找str2的工具。
  • 当您想按天排序时,您应该将日期名称转换为可排序的周索引(星期一=1,...,星期六=6)。然后按 1/ 姓氏、2/ 周索引 3/ 小时对数组进行排序。完成后,只需写入已排序的数组,如果姓氏已更改,则打开一个新文件(以空姓氏开头以在第一条记录上创建一个新文件)。顺便说一句,如果你可以使用std::map 容器,它会更容易实现。

标签: c++ sorting struct dynamic-arrays fromfile


【解决方案1】:

一种可能的方法是按姓氏、天数、小时数对数组进行排序。但是要按天排序,您必须将字符串转换为可排序的索引,例如从星期一的 1 到星期六的 6。

我会在您的代码中添加以下内容:

Line 结构中添加一个week_index 成员,并为转换构建一个map

struct Line {
    string hour;
    string day;
    int week_index;
    string group;
    string surname;
    string subject;
};

std::map<std::string, int> weekdays = {
    {"Monday", 1},
    {"Tuesday", 2},
    {"Wednesday", 3},
    {"Thursday", 4},
    {"Friday", 5},
    {"Saturday", 6}
};

void readLine(ifstream& file, Line& line) {
    file >> line.hour >> line.day >> line.group >> line.surname >> line.subject;
    line.week_index = weekdays[line.day];
}

添加比较功能:

bool comp(const Line& first, const Line& second) {
    if (first.surname < second.surname) {
        return true;
    }
    if (first.surname > second.surname) {
        return false;
    }
    if (first.week_index < second.week_index) {
        return true;
    }
    if (first.week_index > second.week_index) {
        return false;
    }
    if (first.hour < second.hour) {
        return true;
    }
    return false;
}

最后,对数组进行排序并写入相关文件:

...
readLineTab(file, lineTab, numOfLines);
printLineTab(lineTab, numOfLines);

std::sort(lineTab, lineTab + numOfLines, comp);

string surname = "";
std::ofstream ofs;
for (const Line* line = lineTab; line < lineTab + numOfLines; line++) {
    if (line->surname != surname) {
        if (ofs.is_open()) ofs.close();
        ofs.open(line->surname + std::string(".txt"));
        surname = line->surname;
    }
    ofs << line->hour << " " << line->day << " " << line->group << " " << line->subject << '\n';
}
ofs.close();

delete[] lineTab;
...

【讨论】:

  • 我还有一个问题,你能在向量上不使用 std::map 的情况下做到吗?
  • @VertcoreDesign:我在这里使用了映射,因为我不想在数组中实现线性搜索,但它可以替换为普通的结构数组 (struct { const char * day_name; int week_day;};)。跨度>
  • 你可以表示你是否会用这个数组而不是使用 map 因为我尝试了但有些东西不起作用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-05
  • 1970-01-01
  • 1970-01-01
  • 2016-02-01
相关资源
最近更新 更多