PINTIA - 7-4 得分处理 (10 分)

7-4 得分处理 (10 分)

一、题干

编写程序来处理学生分数数据。
程序的输入包含以下两种格式之一的文本行:
学生的姓名和学生ID,分别为<student id>, <name>
为一门课程的一名学生评分,为<student id>, <course name>, <marks>
两种格式的示例是:

3190101234, Zhang San
3190101111, Linear Algebra, 89.5

逗号用作每个字段的分隔符,并且永远不会出现在任何字段中。请注意,人名和课程名称有多个词。为了使您的代码更容易,可以将分数视为double
最初不知道学生的人数和课程的数量。开头的行数也不知道。不同格式的行不按顺序显示。一名学生可能不会每门课程都被录取。

您的程序应读入每一行并以.csv格式打印出摘要表。
输出的第一行是表头,包括如下字段:
student id, name, <course name 1>, <course name 2>, ..., average
课程名称是按字母顺序阅读的所有课程。每个逗号后应有一个空格
然后,输出的每一行都是一个学生的数据,按其学生ID的升序排列,并带有每个课程的分数,例如:
3190101234, Zhang San, 85.0, , 89.5, , , 87.3
对于尚未注册的课程,请在逗号前留一个空白,并且不应计入平均值。平均值有一位小数。每个逗号后应有一个空格。
输出的最后一行是每个课程的平均分数的摘要行,例如:
, , 76.2, 87.4, , , 76.8
输出的所有数字(包括平均值)都保留一位小数

输入格式

如上文所述。

输出格式

如上文所述。标准输出是由gcc编译的程序生成的,第一个小数点后一位是“ gcc方式”。

样本输入

3180111435, Operating System, 34.5
3180111430, Linear Algebra, 80
3180111435, Jessie Zhao
3180111430, Zhiwen Yang
3180111430, Computer Architecture, 46.5
3180111434, Linear Algebra, 61.5
3180111434, Anna Teng

样本输出

student id, name, Computer Architecture, Linear Algebra, Operating System, average
3180111430, Zhiwen Yang, 46.5, 80.0, , 63.2
3180111434, Anna Teng, , 61.5, , 61.5
3180111435, Jessie Zhao, , , 34.5, 34.5
, , 46.5, 70.8, 34.5, 50.6

二、注意

  1. 数据分为 name,student_id,course,marks这四部分,个人认为其他数据与name的关系不大。
  2. 对于数据结构的选择,set适合存储课程名,避免重复。map用来存student_id -- name。对于student_id -- courses -- marks更像是一个树状,一个student_id对应多个course,而且每个course都对有一个marks,所以map<x, map<x,x>>这种结构比较合适,但逻辑挺复杂的,尤其是遍历的时候。
  3. 对于输入与输出,可以重点理解题干中的关键字,有几种情况是我第一次做的时候没考虑进去的。
  4. 输出每个数据都必须有一位小数;只有学号和姓名也需要输出;输入的成绩有可能为0;

三、代码

#include <iostream>
#include <string>
#include <map>
#include <set>
#include <iomanip>
using namespace std;

int main()
{
    
    
    string str_id, str_info;	// str_info : student_id后的字符串
    string str;
    map<string, map<string, double>> id_course;	// id -> course -> mark
    map<string, string> id_name;	// id -> name
    set<string> course;	// course
    double s = 0;
    int n = 0;

    while(getline(cin, str)) {
    
    	// ctrl+D 结束
        string::size_type n = str.find_first_of(',');
        str_id = str.substr(0, n);		// 取str的学号部分
        str_info = str.substr(n+2);		// 取 除"student_id, "外的部分
        n = str_info.find(',');		// 判断输入的是 姓名 or 课程和成绩
		
        if(n == string::npos) {
    
    		// 存储 姓名
            id_name[str_id] = str_info;
        }
        else {
    
    		// set中存课程名, map<x,map<x,x>>中存储课程名与成绩
            (id_course[str_id])[str_info.substr(0, n)] = stof(str_info.substr(n+2));
            course.insert(str_info.substr(0, n)); 
        }
    }

    cout << "student id, name, ";
    if(!course.empty()) {
    
    	// 如果有课程的话,输出课程
        for(auto i:course) {
    
    
            cout << i << ", ";
        }
    }
    cout << "average" << endl;	// 根据题目, "average"是要输出的,不管有没有课程
    
    if(!id_course.empty()){
    
    	// 有课程
        for(auto i:id_course) {
    
    
        	// 输出学号与姓名
            cout << i.first << ", " << id_name[i.first] << ", ";
            // 输出课程与成绩
            double sum = 0;
            int num = 0;
            for(auto j:course) {
    
    
                auto search = (id_course[i.first]).find(j); // 是否能在map中找到课程 ?
                if(search == (id_course[i.first]).end()) {
    
    
                    cout << ", ";
                }
                else {
    
    
                    cout << fixed << setprecision(1) << (id_course[i.first])[j] << ", ";
                    sum += (id_course[i.first])[j];
                    num ++;
                }
            }
	
			// fixed : 输出小数点后一位
            cout << fixed << setprecision(1) << sum/num << endl;
        }
    }
    else {
    
    	// 无课程
        for(auto i:id_name) {
    
    
            cout << i.first << ", " << i.second << endl;
        }
    }

    cout << ", , ";
    if(!course.empty()){
    
    
        for(auto i:course) {
    
    
            double sum = 0;
            int num = 0;
            for(auto j:id_course) {
    
    
                auto search = j.second.find(i);
                if(search != j.second.end()) {
    
    
                    num ++;
                    sum += j.second[i];
                }
            }
            cout << fixed << setprecision(1) << sum/num << ", ";
            s += sum/num;
            n ++;
        }
        cout << fixed << setprecision(1) << s/n << endl;
    }

    
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_44336650/article/details/107185822