课堂派题库格式转换程序
Posted wkfvawl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了课堂派题库格式转换程序相关的知识,希望对你有一定的参考价值。
一、背景
这个学期开设的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<< ‘\\n‘;//写入题干 map<string,string>::iterator iter; for(iter = sbj[i].options.begin(); iter != sbj[i].options.end(); iter++) outf<<iter->first<<"."<<iter->second<< ‘\\n‘;//写入选项 outf<< ‘\\n‘<< ‘\\n‘<< ‘\\n‘; 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+"\\n"); 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+"\\r\\n"); 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()+"\\r\\n"); out.write("\\r\\n"+"\\r\\n"+"\\r\\n"); out.flush(); // 把缓存区内容压入文件 catch (IOException e) e.printStackTrace(); System.out.println("文本转换完成!");
五、遇到的一些问题
以上是关于课堂派题库格式转换程序的主要内容,如果未能解决你的问题,请参考以下文章
计算机网络湖科大微课堂笔记 p54-57 IPv4数据报的首部格式网际控制报文协议ICMP虚拟专用网VPN与网络地址转换NAT