zoukankan      html  css  js  c++  java
  • 课堂派题库格式转换程序

    一、背景

    这个学期开设的Java程序设计课程,需要用课堂派来签到和平常练习,老师苦于课堂派后台的课堂测试需要人工填入题目,好在课堂派运行符合格式的题目直接从word文档中导入,于是让我们来写一个小程序来实现这个格式转换。老师用的源题库是有特殊格式的,这样我们就可以通过一些特殊的标记来实现对源题库的读取,我最开始使用C++来实现的,后来补充的Java的版本。该程序主要是对string的操作,二者之中有许多相同的函数方法,但具体的写法却有所不同,同时Java的限制数组越界、不能更改String的一些特点,也让有些头疼,Java写的还是太少了!

    二、格式要求

    源题库样例:

    目标题库格式:

    具体要求:

    1.第一行为题干,中间不要换号(课堂派后台只能识别一行题干),可以加题号,也可以不加题号,编写程序时可以通过一个选项开关让使用者决定是否需要保留题号。

    2.答案要写在题目开头或者结尾,用括号括起来,大小写括号均可。在题干末尾添加本题的类型和分数,用大括号括起来。题目的类型需要通过答案的个数自己判断,题目的分数需要程序的使用者来输入。

    3.题干之后是选项行,选项中不要空行,一个选项是单独的一行,选项字母需要英文大写。

    4.每一道题与下一道题目之间需要空三行作为标志。

    5.源题库中的有些题目可能会有解析,这里解析不需要提取处理。

    6.源题库中出现的Chapter和Section的内容可以输出到控制台,目标文件中不要出现。

    三、C++源代码

    #include<fstream>  //ifstream
    #include<iostream>
    #include<string>
    #include<map>
    using namespace std;
    
    struct subject
    {
        int id;//题目序号
        int type;//题目类型
        string stem;//题干内容
        map<string,string>options;//选项与答案的map键值对
        int num;//选项个数
        string score;//题目分数
        string key;//答案
        string analysis;//有些题目需要解析
    };
    
    int main()
    {
        string s,temp;
        string path;
        ofstream outf;
        ifstream inf;
        int cnt=0;//记录题目的个数
        int num1=0;//单选题个数
        int num2=0;//多选题个数
        int flag=0;//默认保留原题号
        char select;//是否保留题号的选项
        string score;
        struct subject sbj[100];
        string::size_type pos(0);
        cout << "请输入需要转换的文本文件路径:(例:C://in.txt)" <<endl;
        cin >> path;
        if(inf)
        {
            cout << "打开文本文件成功!" <<endl;
        }
        else
        {
            cout << "打开文本文件失败!" <<endl;
        }
        inf.open(path);//打开文本文件I://chapter1.txt
        cout << "请输入转换输出的文本文件路径:(例:C://out.txt)" <<endl;
        cin >> path;
        outf.open(path);//需要写入的文本文件
    
        //目标文本的读取
        cout << "转换完成后的题目是否保留原题号?(y/n)" <<endl;
        while(1)
        {
            cin >> select;
            if(select=='y')
            {
                flag=1;
                break;
            }
            else if(select=='n')
            {
                flag=0;
                break;
            }
            else
            {
                cout << "只能输入y或n,请重新输入!" <<endl;
            }
        }
        while (getline(inf, s))
        {
            if(s.substr(0,7)=="Chapter")
            {
                cout<<s<<endl;
            }
            else if(s.substr(0,7)=="Section")
            {
                cout<<s<<endl;
            }
            //提取选项信息
            else if(s.substr(0,1)>="0"&&s.substr(0,1)<="9") //提取题干信息
            {
                cnt++;
                if(flag==1)
                {
                    pos =s.find(".");
                    temp=s.substr(pos+1,s.length()-pos);
                    sbj[cnt].stem = temp;//保存题干内容
                }
                else if(flag==0)
                {
                    sbj[cnt].stem = s;
                }
                sbj[cnt].id = cnt;
                sbj[cnt].num = 0;
                while (getline(inf, s))
                {
                    if(s.substr(0,4)=="Key:")//提取答案信息
                    {
                        temp=s.substr(4,s.length()-4);
                        pos =temp.find(" ");
                        sbj[cnt].key=temp.substr(0,pos);
                        cout<<sbj[cnt].key<<endl;
                        for(int i=0; i<sbj[cnt].key.length(); i++)//答案替换为大写字母
                        {
                            if(sbj[cnt].key[i]>='a'&&sbj[cnt].key[i]<='z')
                            {
                                sbj[cnt].key[i]=sbj[cnt].key[i]-32;
                            }
                        }
                        pos=sbj[cnt].key.length()-1;
                        if(temp.length()>sbj[cnt].key.length())
                        {
                            sbj[cnt].analysis=temp.substr(pos,temp.length()-pos);
                        }
    
                    }
                    else if((s[0]>='a'&&s[0]<='z')||(s[0]>='A'&&s[0]<='Z'))//提取选项信息
                    {
                        if(s[0]>='a'&&s[0]<='z')//选项是小写字母,转为大写字母
                        {
                            s[0]=s[0]-32;
                        }
                        sbj[cnt].options.insert(pair<string,string>(s.substr(0,1),s.substr(2,s.length()-2)));//保存选项
                        sbj[cnt].num++;
                    }
                    else if(s.substr(0,1)=="#")//分隔符,下一道题
                    {
                        break;
                    }
                }
                cout<<""<<cnt<<"道题识别成功!!"<<endl;
                cout<<sbj[cnt].stem<<endl;
                cout<<"答案:"<<sbj[cnt].key<<endl<<endl;
            }
        }
        cout<<"读取文本文件成功!"<<endl;
    
        //目标文本的处理
        for(int i=1; i<=cnt; i++)
        {
            pos=0;
            sbj[i].stem.insert(pos,""+sbj[i].key+"");//答案的插入
            if(sbj[i].key.length()==1)
            {
                sbj[i].stem=sbj[i].stem+"[单选题]";
                num1++;
            }
            else if(sbj[i].key.length()>1)
            {
                sbj[i].stem=sbj[i].stem+"[多选题]";
                num2++;
            }
        }
        cout<<"检测到单选题"<<num1<<"道,多选题"<<num2<<""<<endl;
        cout<<"请输入题目的分数:[1~100]"<<endl;
        cin>>score;
    
        for(int i=1; i<=cnt; i++)
        {
            sbj[i].score=score;
            sbj[i].stem=sbj[i].stem+"["+score+"分]";
        }
        for(int i=1; i<=cnt; i++)//文本写入
        {
            outf<<sbj[i].stem<< '
    ';//写入题干
            map<string,string>::iterator iter;
            for(iter = sbj[i].options.begin(); iter != sbj[i].options.end(); iter++)
            {
                outf<<iter->first<<"."<<iter->second<< '
    ';//写入选项
            }
            outf<< '
    '<< '
    '<< '
    ';
        }
        inf.close();
        outf.close();
        cout<<"文本转换完成!"<<endl;
        return 0;
    }

    四、Java源代码

    import java.io.*;
    import java.util.*;
    //import java.util.Map;
    //import java.util.HashMap;
    class subject
    {
         int id;//题目序号
         int type;//题目类型
         int num;//选项个数
         String stem;//题干内容
         int score;//题目分数
         String key;//答案
         String analysis;//有些题目需要解析
         Map<String,String>options=new LinkedHashMap<String,String>();//map映射,LinkedHashSet正序输出
         public subject()//构造函数
         {
             id = 0;
             type = 1;
             num = 0;
             score =1;
             stem = null;
             key = null;
             analysis = null;
         }
    }
    
    public class Main {
        
        public static void main(String args[]) {
            int cnt = 0;
            int num1=0;//单选题个数
            int num2=0;//多选题个数
            int flag=0;//默认保留原题号
            char select;//是否保留题号的选项
            int score;
            String pathname_in;
            String pathname_out;
            Scanner in=new Scanner(System.in);
            subject [] sbj;
            sbj = new subject[1000];
            for(int i=0;i<sbj.length;i++){
                sbj[i]= new subject();
            }
            //String pathname = "I://chapter1.txt"; 
            System.out.println("请输入需要转换的文本文件路径:(例:C://in.txt)");
            pathname_in =in.nextLine();
            System.out.println("请输入转换输出的文本文件路径:(例:C://out.txt)");
            pathname_out =in.nextLine();
            System.out.println("转换完成后的题目是否保留原题号?(y/n)");
            while(true){
                select =in.nextLine().charAt(0);
                if(select=='y'){
                    flag=1;
                    break;
                }
                else if(select=='n'){
                    flag=0;
                    break;
                }
                else
                {
                    System.out.println("只能输入y或n,请重新输入!");
                }
            }
            
            try (FileReader reader = new FileReader(pathname_in);
                 BufferedReader br = new BufferedReader(reader) // 建立一个对象,它把文件内容转成计算机能读懂的语言
            ) {
                String line;
                //网友推荐更加简洁的写法
                while ((line = br.readLine()) != null) {
                    if(line.length()==0){
                        continue;
                    }
                    else if(line.substring(0,7).equals("Chapter")){
                        System.out.println(line);
                    }
                    else if(line.substring(0,7).equals("Section")){
                        System.out.println(line);
                    }
                    else if((line.charAt(0)>='0')&&(line.charAt(0)<='9')){
                        cnt++;
                        String temp;
                        int pos;
                        if(flag==1){
                            pos =line.indexOf('.');
                            temp=line.substring(pos+1,line.length());
                            sbj[cnt].stem = temp;//保存题干内容
                        }
                        else if(flag==0){
                            sbj[cnt].stem = line;
                        }
                        sbj[cnt].id=cnt;
                        sbj[cnt].num=0;
                        while ((line = br.readLine()) != null) {
                            System.out.println(line);
                            if(line.length()==0){
                                continue;
                            }
                            else if(line.charAt(0)=='#'){
                                break;//分隔符
                            }
                            else if(line.length()<=4)
                            {
                                continue;
                            }
                            else if(line.substring(0,4).equals("Key:")){
                                temp = line.substring(4,line.length());//答案和解析的内容
                                pos = temp.indexOf(' ');
                                if(pos==-1){//没有解析说明
                                    sbj[cnt].key= temp.toUpperCase();//写回
                                    System.out.println(sbj[cnt].key);
                                }
                                else {
                                    sbj[cnt].key=temp.substring(0,pos);//答案选项
                                    sbj[cnt].key=sbj[cnt].key.toUpperCase();//写回
                                    pos=sbj[cnt].key.length()-1;
                                    if(temp.length()>sbj[cnt].key.length()){
                                        sbj[cnt].analysis=temp.substring(pos,temp.length()-pos);
                                    }
                                }
                            }
                            else if(((line.charAt(0)>='a'&&line.charAt(0)<='z')||(line.charAt(0)>='A'&&line.charAt(0)<='Z'))&&(line.charAt(1)=='.')){
                                String opt = line.substring(0,2);//选项
                                String detail = line.substring(2,line.length());//选项描述
                                sbj[cnt].options.put(opt,detail);
                                sbj[cnt].num++;  
                            }
                            else
                            {
                                continue;
                            }
                        }
                        System.out.println("第"+cnt+"道题识别成功!!");
                        System.out.println(sbj[cnt].stem);
                        System.out.println("答案:"+sbj[cnt].key+"
    ");
                    }
                    else
                    {
                        continue;
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println("读取文本文件成功!");
            for(int i=1;i<=cnt;i++){
                sbj[i].stem="( "+sbj[i].key+" )"+sbj[i].stem;
                if(sbj[i].key.length()==1){
                    sbj[i].stem=sbj[i].stem+"[单选题]";
                    num1++;
                }
                else if(sbj[i].key.length()>1){
                    sbj[i].stem=sbj[i].stem+"[多选题]";
                    num2++;
                }
                
            }
            System.out.println("检测到单选题"+num1+"道,多选题"+num2+"道");
            System.out.println("请输入题目的分数:[1~100]");
            score =in.nextInt();
            for(int i=1; i<=cnt; i++){
                sbj[i].score=score;
                sbj[i].stem=sbj[i].stem+"["+score+"分]";
            }
            try {
                File writeName = new File(pathname_out); // 相对路径,如果没有则要建立一个新的output.txt文件
                writeName.createNewFile(); // 创建新文件,有同名的文件的话直接覆盖
                try (FileWriter writer = new FileWriter(writeName);
                     BufferedWriter out = new BufferedWriter(writer)
                ) {
                    for(int i=1; i<=cnt; i++){//文本写入
                        out.write(sbj[i].stem+"
    "); 
                        Iterator<Map.Entry<String, String>> entries = sbj[i].options.entrySet().iterator();  
                        while(entries.hasNext()){  
                            Map.Entry<String, String> entry = entries.next();  
                            out.write(entry.getKey()+entry.getValue()+"
    ");
                        }  
                        out.write("
    "+"
    "+"
    "); 
                    }
                    out.flush(); // 把缓存区内容压入文件
                }
            } catch (IOException e){
                e.printStackTrace();
            }
            System.out.println("文本转换完成!");
        }
    }

     五、遇到的一些问题

     

    1.Java中关于HashMap的元素遍历的顺序问题

    摘自https://www.cnblogs.com/xdp-gacl/p/3558625.html

    在使用如下的方式遍历HashMap里面的元素时

    for (Entry<String, String> entry : hashMap.entrySet()) {
         MessageFormat.format("{0}={1}",entry.getKey(),entry.getValue());
     }

      发现得到的元素不是按照之前加入HashMap的顺序输出的,这个问题我之前倒是没有注意过,后来上网查了一下原因,发现是:HashMap散列图、Hashtable散列表是按“有利于随机查找的散列(hash)的顺序”。并非按输入顺序。遍历时只能全部输出,而没有顺序。甚至可以rehash()重新散列,来获得更利于随机存取的内部顺序。
      总之,遍历HashMap或Hashtable时不要求顺序输出,即与顺序无关。

    Map<String, String> paramMap = new HashMap<String, String>();

      可以用java.util.LinkedHashMap 就是按加入时的顺序遍历了。

    Map<String, String> paramMap = new LinkedHashMap <String, String>();

      类似的还有 java.util.LinkedHashSet

    2.C++中对字符串中所有指定的子串进行替换的函数

    /*
     * string& str              源字符串
     * const string& old_value  被替换子串
     * const string& new_value  替换子串
     */
    string& replace_all(string& str,const string& old_value,const string& new_value)//替换函数
    {
        while (true)
        {
            string::size_type   pos(0);
            if ((pos = str.find(old_value)) != string::npos)
            {
                str.replace(pos, old_value.length(), new_value);
            }
            else
            {
                break;
            }
        }
        return   str;
    }
  • 相关阅读:
    Atitit 架构师的技术框架体系图 各种引擎列表 脚本引擎 groovy beanshel php nodejs rhino等 表达式引擎技术 Ognl/MVELl等 通讯, rest 命令解
    Atitit 架构师的分类 架构师都有哪些种类? 1. 应用架构师 应用架构师是行业中数量最多的架构师,主要负责公司产品的技术架构。产品架构师需要对业务有足够的理解,根据产品需求设计架构,在运营团
    Atitit 教育学体系 教育学主要内容多语言,教学论,心理学,体育 高等教育学 职业技术教育学 教育史
    Atitit 微信开发文档总结获取token和菜单管理功能 /bookmarksHtmlEverythingIndexPrj/src/com/attilax/wechatToto/wechatMen
    Atitit 薪酬管理法 工作手册 员:薪酬管理办法 1.薪酬结构 所有员工的薪酬均由岗位工资、级别工资、校龄工资、特别津贴、绩效工资和季度奖金六部分组成。其中岗位工资、级别工资、校龄工资、22
    Atitit springcloud的艺术 attilax总结 目录 1.1. 服务治理:Spring Cloud Eureka 39 注册中心 1 1.2. 第4章 客户端负载均衡:Spring
    ATITIT 后发优势 后发劣势 vs 先发优势的思考 目录 1.1. “后发优势” 1 1.2. “后发劣势”论 1 1.3. 科技、经济界有两种矛盾的说法“后发优势”和“后发劣势” 1 2
    Atitit java项目常用类库表 目录 1. Ati总的常用库 1 1.1. 表达式,语言解析类库 1 1.2. 字符串模板解析库velocity freemark 1 1.3. rest库
    Atitit 命令行dsl传递参数的几种模式对比 cli url模式 键值对NameValuePair urlutil String string = " host 101.13
    Atitit java字符串模板渲染总结 目录 1. 总结:指标 1 1.1. 支持中文变量 提升可读性 1 1.2. 变量placeholder简单性,,velo可以直接¥前导简单。。Free的
  • 原文地址:https://www.cnblogs.com/wkfvawl/p/11515110.html
Copyright © 2011-2022 走看看