习题课:结构、链表、文件

《计算机程序设计》

苏醒

计算机学院计算机研究所编译系统研究室

结构体:只买一本

编程实现

书店图书的类型分为八大类,书的信息使用结构Book表示。书店目前有一批孤本图书(某书只有一本),总数为TOTALNUM=16,这些书的信息用一个数组books来存储,书的ID号就是该书在books数组中的序号。小明想把已有的各个类型的孤本书各买1本,请问他最少需支付多少钱?

onlybuyone.cpp
#include <iostream>
using namespace std;
#define TOTALNUM 16
struct Book {
  double price; // 价格,小于100
  int tpid; // 取0~7,分别对应政治、经济、社会、艺术、物理、化学、生物、地理八大类
};
double onlyBuyOne(Book books[]) {
  
}
int main() {
  int i;
  Book books[TOTALNUM]; // 孤本图书构成的数组
  for (i = 0; i < TOTALNUM; i++) // 输入孤本书的信息,数组的序号作为该书本的ID号
    cin >> books[i].price >> books[i].tpid;
  cout << onlyBuyOne(books) << endl;
  return 0;
}

结构体:只买一本

只买一本:解法1
double onlyBuyOne(Book books[]) {
  double total = 0.0;
  // 遍历所有书,找到每一类别最低价格
  for (int i = 0; i < 8; i++) {
    // 该类最低价格
    double minPrice = 100.0;
    for (int j = 0; j < TOTALNUM; j++)
      if (books[j].tpid == i && books[j].price < minPrice)
        minPrice = books[j].price;
    total += minPrice;
  }
  return total;
}

结构体:只买一本

只买一本:解法2
double onlyBuyOne(Book books[]) {
  // 价格数组,存储每类书的最低价格,初始化为100.0
  double prices[8];
  for (int i = 0; i < 8; i++) 
    prices[i] = 100.0;
  // 遍历所有书,找到同类别最低价格
  for (int i = 0; i < TOTALNUM; i++)
    if (books[i].price < prices[books[i].tpid])
      prices[books[i].tpid] = books[i].price;
  // 计算总价格
  double total = 0.0;
  for (int i = 0; i < 8; i++)
    total += prices[i];
  return total;
}

链表:在最大节点后插入新节点

编程实现

下面有结构node的定义,指针head中存放着node节点组成的单向链表的首节点地址。函数insertAfterBiggest的功能是将新节点t插入到head所指向的链表中值最大的节点后面,返回新链表。

insertafterbiggest.cpp
#include <iostream>
using namespace std;
struct node {
  int data;
  node *next;
};
node *insertAfterBiggest(node *head, node *t) {

}
insertafterbiggest.cpp
int main() {
  int n; cin >> n;
  node *head = nullptr, *cur = nullptr, *tmp;
  for (int i = 0; i < n; i++) {
    tmp = new node;
    cin >> tmp->data; tmp->next = nullptr;
    if (head == nullptr) {
      head = tmp;
      cur = head;
    } else {
      cur->next = tmp;
      cur = cur->next;
    }
  }
  tmp = new node;
  cin >> tmp->data;
  head = insertAfterBiggest(head, tmp);
  return 0;
}

链表:在最大节点后插入新节点

在最大节点后插入新节点
node *insertAfterBiggest(node *head, node *t) {
  // 找到最大节点
  node *biggest = head;
  for (node *p = head; p; p = p->next)
    if (p->data > biggest->data)
      biggest = p;
  // 插入新节点
  t->next = biggest->next;
  biggest->next = t;
  return head;
}

考考你

如果要在最大结点之前插入,应该如何实现?

链表:在最大节点前插入新节点

在最大节点前插入新节点
node *insertAfterBiggest(node *head, node *t) {
  // 找到最大节点,同时记录前一个节点
  node *biggest = head, prevbiggest = nullptr;
  for (node *p = head, prev = nullptr; p; prev = p, p = p->next) {
    if (p->data > biggest->data) {
      biggest = p;
      prevbiggest = prev;
    }
  }
  // 插入新节点
  t->next = biggest;
  if (prevbiggest)
    prevbiggest->next = t;
  else
    head = t;
  return head;
}

文件:统计日志来源

编程实现

  • 现有一个系统日志文件,每条日志记录包含4行内容,每一行的字符数不大于200。
    • 第一行是日志类型,目前有5种类型分别是DEBUG、INFO、WARNING、ERROR和CRITICAL
    • 第二行是日志产生的时间戳
    • 第三行是日志产生源
    • 第四行是具体日志内容

实现getLogCount函数,查询在日志文件file_path中源自日志产生源log_src的记录有多少条

WARNING
2024/4/15 14:44:14
Microsoft-Windows-Servicing21
A reboot is necessary before the selectable update Microsoft-RemoteDesktopConnection
INFO
2024/3/15 7:48:25
Microsoft-Windows-Servicing20
Package KB5034441 was successfully changed to the Installed state.
查询给定日志源的日志条数
int getLogCount(const char* file_path, char *log_src) {

}

文件:统计日志来源

查询给定日志源的日志条数
#include <fstream>
using namespace std;
int getLogCount(const char* file_path, char *log_src) {
  int count = 0;
  char line[200];
  ifstream fin(file_path);
  while (fin.getline(line, 200)) {  // 读取第一行
    fin.getline(line, 200);         // 跳过第二行
    fin.getline(line, 200);         // 读取第三行
    if (strcmp(log_src, line) == 0) // 判断是否匹配
      count++;
    fin.getline(line, 200);         // 跳过第四行
    // 当前日志已处理完毕
  }
  fin.close();
  return count;
}

计算机程序设计