首页 > 代码库 > 黑马程序员-入学笔试题

黑马程序员-入学笔试题

笔试结束,列一下笔试题和我的解答,最后得分29.7。

1、 编写一个类,在main方法中定义一个Map对象(采用泛型),加入若干个对象,然后遍历并打印出各元素的key和value。

package com.itheima;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class Test1 {

	public static void main(String[] args) {
		//定义一个key值为String类型,value值为Integer类型的Map集合,可用于存储一段话中各个单词出现次数信息
		TreeMap<String,Integer> tm=new TreeMap<String,Integer>();
		tm.put("hello", 2);
		tm.put("you", 8);
		tm.put("are", 4);
		tm.put("do", 6);
		//第一种方式遍历TreeMap元素:keySet
		Set<String> kSet=tm.keySet();
		Iterator<String> it=kSet.iterator();
		while(it.hasNext()){
			String str=it.next();
			Integer val=tm.get(str);
			System.out.println(str+" : "+val);
		}
		System.out.println("============================");
		//第二种方式遍历TreeMap元素:EntrySet
		Set<Map.Entry<String, Integer>> eSet=tm.entrySet();
	    Iterator<Map.Entry<String,Integer>> itor=eSet.iterator();  
		while(itor.hasNext()){  
			Map.Entry<String, Integer> me=itor.next();  
			String s=me.getKey();  
		    Integer v=me.getValue();  
		    System.out.println(s+" : "+v);
		}		
 	}
}

2、 有五个学生,每个学生有3门课(语文、数学、英语)的成绩,写一个程序接收从键盘输入学生的信息,输入格式为:name,30,30,30(姓名,三门课成绩),然后把输入的学生信息按总分从高到低的顺序写入到一个名称"stu.txt"文件中。要求:stu.txt文件的格式要比较直观,打开这个文件,就可以很清楚的看到学生的信息。

package com.itheima;

/*
 * 思路:1. 定义Student对象,让其自身具备比较性,同时复写toString方法,方便后面写入文件
 *     2. 将键盘输入封装成字符缓冲流,按行读取,每一行字符串封装成一个Student对象
 *     3. 将Student对象放到TreeSet集合中,实现按序存储
 *     4. 将TreeSet集合中的各个Student对象写入到stu.txt文件中
 */
import java.io.*;
import java.util.Iterator;
import java.util.TreeSet;

public class Test2 {

	public static void main(String[] args) throws Exception
	{
		BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));  
		BufferedWriter bufw=new BufferedWriter(new FileWriter("stu.txt"));
		TreeSet<Student> ts=new TreeSet<Student>();
		String line=null;
		System.out.println("请输入学生信息,格式如name,30,30,30:");
		//将从键盘接收到学生信息放到一个TreeSet集合中
		while((line=bufr.readLine())!=null){
			if("over".equals(line))
				break;
			String[] strs=line.split(",");
			if(strs.length!=4){
				System.out.println("输入信息格式不对,请重新输入");
				continue;
			}
			ts.add(fillStu(strs));
		}
		bufr.close();
		//将TreeSet写入到stu.txt文件中
		Iterator<Student> it=ts.iterator();
		while(it.hasNext()){
			Student stu=it.next();
			bufw.write(stu.toString());
			bufw.newLine();
		}
		bufw.flush();
		bufw.close();
	}
	//根据一个字符串数组信息填充生成Student对象
	public static Student fillStu(String[] strs){
		Student stu=new Student(strs[0],Float.parseFloat(strs[1]),Float.parseFloat(strs[2]),Float.parseFloat(strs[3]));
		return stu;
	}
}
//定义Student类,实现带泛型的Comparable接口,让Student对象自身具备比较性
class Student implements Comparable<Student>{

	private String name;
	private float yuWen;
	private float shuXue;
	private float yingYu;
	private float sum;
	public Student(String name, float yuWen, float shuXue, float yingYu) {
		super();
		this.name = name;
		this.yuWen = yuWen;
		this.shuXue = shuXue;
		this.yingYu = yingYu;
		this.sum=yuWen+shuXue+yingYu;
	}
	@Override
	//复写compareTo()方法,实现Student对象按总分比较,总分一致时按姓名比较
	public int compareTo(Student o) {
        float result=this.sum-o.sum;
        if(result>0)
        	return -1;
        else if(result==0){
        	return this.name.compareTo(o.name);
        }
		return 1;
	}
	public String toString(){
		return name+", 语文成绩:"+yuWen+" 数学成绩:"+shuXue+" 英语成绩:"+yingYu+" ---- 总分:"+sum;
	}
}

3、 自定义枚举 Week 用于表示星期,Mon,Tue,Wed...要求每个枚举值都有toLocaleString 方法,用于获得枚举所表示的星期的中文格式 星期一、星期二、星期三...

package com.itheima;

public class Test3{
	public static void main(String[] args){
		//测试实现的enum枚举,枚举对象的中文格式是否可以正常显示
		Week wed=Week.Wed;
		System.out.println(wed.toLocalString());
	}
}
enum Week {
	//定义Mon,Tue,Wed...等枚举对象,使用内部类形式实现抽象方法
	Mon {
		public String toLocalString() {
			return "星期一";
		}
	},
	Tue {
		public String toLocalString() {
			return "星期二";
		}
	},
	Wed {
		public String toLocalString() {
			return "星期三";
		}
	},
	Thu {
		public String toLocalString() {
			return "星期四";
		}
	},
	Fri {
		@Override
		public String toLocalString() {
			return "星期五";
		}
	},
	Sat {
		public String toLocalString() {
			return "星期六";
		}
	},
	Sun {
		public String toLocalString() {
			return "星期天";
		}
	};
	//定义枚举类的抽象方法
	public abstract String toLocalString();	
}

4、 请说明Java中字符‘\‘的含义,有什么作用?

package com.itheima;

/*
 * 答:1.'\'可以转义字符,将其后面紧跟的字母或符号转换成其它的含义。
 *     常用的转义字符有:\n:换行,\b:退格,\r:按下回车键,\t:制表符,相当于tab键。
 *    2. 因为'\'会转义后面的字符,所以代码中如果要保持\原先的意思,需要在 \前面再加一个\,表示后面的\保持原形,不转义
 */

5、 将字符串中进行反转。abcde --> edcba

package com.itheima;

/*
 * 思路:将待转换的字符串先转换成字符数组,对字符数组进行首尾互换,即实现了反转,再将首尾互换后的字符数组封装成字符串返回
 */

public class Test5 {

	public static void main(String[] args) {
		String str="abcdefghi";
		System.out.println(rev(str));
	}
	public static String rev(String str){
		//将字符串转换成字符数组
		char[] chs=str.toCharArray();
		int len=str.length();
		char temp;
		//实现字符数组首尾互换
		for(int i=0;i<len/2;i++){
			temp=chs[i];
			chs[i]=chs[len-1-i];
			chs[len-1-i]=temp;
		}
		//字符数组封装成字符串返回
		return new String(chs);
	}
}

6、 分析以下程序运行结果,说明原理。(没有分析结果不得分)。---下面直接分析给出的代码,原题中只有代码,没有任何注释。

package com.itheima;
//分析如下:
public class Test6 {
	
    public static void main(String args[]) {
    MyThread t = new MyThread();
    //仅调用t.run()并没有启动线程,只是普通的函数调用
    t.run();
    //t线程启动,开始在一个与主线程不同的线程分支运行run方法中的代码,t线程与主线程抢夺CPU资源
    //run方法一开始就休眠,所以主线程抢到CPU时间,开始运行下面的System.out.println("A")
    t.start();
    System.out.println("A");
    }
}
class MyThread extends Thread {
    public void run() {
        try {
            Thread.sleep(3000);
            } catch (InterruptedException e) {
         }
        //休眠结束运行下面的语句
        System.out.println("B");
        }
}
/*
 程序运行结果是
 B
 A
 B
运行结果分析:
1. JVM启动后,从main函数入口,开始执行,并创建main主线程
2. 主线程创建MyThread对象t,但t所代表的线程还没有启动
3. 主线程调用线程对象t的run()方法,这时还是没有启动t线程,只是普通的函数调用,所以程序会sleep 3秒,然后打印B
4. 主线程调用t.start(),t线程被启动,开始有一个线程分支在运行,分支中运行的是t.run中的代码,而main主线程仍在main函数中往下执行
5. t线程分支和main主线程开始抢夺CPU时间,因为t线程分支中run方法中一开始就sleep 3秒,所以主线程轻而易举地抢到执行权,继续往下执行,
6. main函数的下一条语句是打印A,所以输出A,这时,main主线程执行完毕
7. 主线程完毕后,t线程分支还没休眠结束,所以console控制台应该会停顿差不多3秒的时间,然后t线程中接着执行run方法中的剩余语句,打印B.
 */

7、 有一个类为ClassA,有一个类为ClassB,在ClassB中有一个方法b,此方法抛出异常,在ClassA类中有一个方法a,请在这个方法中调用b,然后抛出异常。在客户端有一个类为TestC,有一个方法为c ,请在这个方法中捕捉异常的信息。完成这个例子,请说出java中针对异常的处理机制。

package com.itheima;
/*
 * 思路:将一个int型值转换成ASCII码字符,如果int值超过了127,抛出异常,用这个例子来切合题目并说明java异常处理机制
 */
public class Test7 {

	public static void main(String[] args) {
		c();
	}
	//c()方法中调用A类的a()方法,OutASCIIException异常没必要再抛给更上层调用者,直接在c()方法中捕获并处理
	public static void c(){
		A clsA=new A();
		try {
			clsA.a();
			System.out.println("异常抛出点之后的try块的语句不执行。。。");
		} catch (OutASCIIException e) {
			System.out.println(e.toString());
			System.out.println("错误的数值 是:"+e.getVal());
		}
	}
}
//A类中的a()方法调用B类的b(int)方法,对异常不做处理,直接在函数声明中抛出,让上层调用者处理
class A{
	public void a() throws OutASCIIException 
	{
		B clsB=new B();
		char d=clsB.b(145);
	}	
}
//B类,其中的b方法实现int值到ASCII字符的转换,可能抛出自定义异常OutASCIIException
class B{
	public char b(int a) throws OutASCIIException{
		if(a>127)
			throw new OutASCIIException("超出了ASCII码值的范围,转换成字符失败:",a);
		return (char)a;
	}
}
//自定义异常,将一个int型值转换成ASCII字符,当要转换的int值超过ASCII码取值范围时,抛出异常
class OutASCIIException extends Exception
{
	int val;
	OutASCIIException(String msg, int val){
		super(msg);
		this.val=val;
	}
	int getVal(){
		return val;
	}	
}
/*
 * java异常处理机制:
 * java通过类的形式来描述异常,将异常封装成对象。
 * java异常体系根节点是Throwable类,它描述了异常的共性(异常信息,引发异常的原因,可抛性等)。
 * java提供2种处理异常的方式:
 * 1. 用try...catch...finally语句处理
 *    try中存放可能出现异常的代码,try块中异常抛出点之后的语句不会再执行;
 *    catch捕获异常并进行异常处理;finall中存放一定会执行的代码,不管异常有没有发生。
 * 2. 在函数上用throws声明该函数可能出现的异常类,让函数的调用者去处理该异常
                 调用者捕获该异常后,可以继续向上throws异常,直到抛给jvm,也可以用try...catch处理。
 */

8、 定义一个文件输入流,调用read(byte[] b)方法将exercise.txt文件中的所有内容打印出来(byte数组的大小限制为5)。

package com.itheima;

/*
 * 思路:因为缓冲区数组固定是5个字节大小,而当文件中汉字时,汉字占2个字节,一次读取5个字节可能出现截取半个汉字的情况,所以不能急着打印;
 *     先分析一次读取后是否截取到了半个汉字,如果是,只打印前4个字节的内容,然后退回一个字节再读取,如果不是,直接输出;
 *     由此想到了利用随机访问文件流,可以设置当前指针位置,必要时回退一个字节。
 */
import java.io.FileInputStream;
import java.io.RandomAccessFile;

public class Test8 {

	public static void main(String[] args) throws Exception
	{
		RandomAccessFile raf=new RandomAccessFile("exercise.txt","r");
		byte[] buf=new byte[5];
		int len=0;
		int currentPos=0;
		while((len=raf.read(buf))!=-1){
			String str=new String(buf,0,len);
			currentPos=currentPos+len;
			int i=0;
			//i表示一个ASCII字符字节位置或一个汉字的第一个字节位置,汉字GBK编码的第一个字节都小于0
			while(i<5){
				if(buf[i]<0)
					i=i+2;
				else
					i=i+1;
			}
			//read(buf)后,如果截取到了半个汉字,那buf[4]肯定是一个汉字的第一个字节,buf[4]<0,上面的i=6
		    if(i==6){
		    	//截取了半个汉字时,应该退回到前一个位置,重新再读取5个字节
		    	currentPos=currentPos-1;
			    raf.seek(currentPos);
			    //只把前4个字节的内容打印出来
			    System.out.print(str.substring(0,str.length()-1));
		    }else{
		    	//截取到完整汉字,整个输出
			    System.out.print(str);
		    }
		}				
	}
}

9、 写一方法,打印等长的二维数组,要求从1开始的自然数由方阵的最外圈向内螺旋方式地顺序排列。 如: n = 4 则打印:

1  2  3  4
12 13 14 5
11 16 15 6
10 9  8  7                                

package com.itheima;

/*
 * 思路:1. 按螺旋的圈数进行循环,对于n阶方阵,螺旋圈数是(n+1)/2.
 *     2. 每一圈都是按顺时针走,顺时针位置上的值依次增加,可以先循环列出向右增长的横行和向下增长的竖列的值,剩下的半圈的值可利用对称性得到。
 *     3. 里面一圈的起始值是它外面一圈左侧位置上的值加1
 */
public class Test9 {

	public static void main(String[] args) {
		xzArray(8);
	}
	public static void xzArray(int n){
		int[][] arr=new int[n][n];
		//如果每一圈开头位置相邻左侧位置的值为start,那每一圈开头的值就是start+1,最外面一圈的start值设置为0
		int start=0;
	    //按螺旋的圈数进行循环,给定n值的方阵,其螺旋的圈数(n+1)/2
		for(int q=0;q<(n+1)/2;q++){
			//除第一圈外,从外向里,每一圈的开头起始值是其左侧紧邻位置的值+1,即start+1
			if(q!=0){
				start=arr[q][q-1];
			}
		    //获取每一圈往右增长的一行和往下增长的一列的值,每一圈的元素个数是随着圈从外向内的层次数而变化的,用j表示,i代表每一圈向右的一行相对起始值的偏移
			for(int j=q,i=0;j<n-q&&i<=j;j++,i++){			
				arr[q][j]=start+i+1;
				//圈子越向内时,每行或每列的元素个数会减少,所以转折的越快
				arr[j][n-1-q]=start+i+n-2*q;
			}
			//获得每一圈往右增长的一行和往下增长的一列的值,向左增长的行数据和向上增长的列数据分别利用对称特性行到,每对对称位置的两个元素加起来的值都是该层最右下角元素值的2倍。
			for(int i=q+1;i<n-q;i++){
				arr[i][q]=2*arr[n-1-q][n-1-q]-arr[q][i];
				arr[n-1-q][i]=2*arr[n-1-q][n-1-q]-arr[i][n-1-q];
			}
		}
		printArray(arr);
	}
	//打印数组的函数
	public static void printArray(int[][] arr){
		for(int i=0;i<arr.length;i++){
			for(int j=0;j<arr[i].length;j++){
				//printf实现格式化打印
				System.out.printf("%4d",arr[i][j]);
			}
			System.out.println();
		}
	}
}

10、  金额转换,阿拉伯数字转换成中国传统形式。

 例如:101000001010   转换为   壹仟零壹拾亿零壹仟零壹拾圆整

package com.itheima;

/*
 * 思路:1. 先试图将普通的4位数及4位数以下的金额转换成传统汉字形式
 *     2. 任一长串金额,可以以4位为一组进行分组,分组内金额的转换形式与普通单独的4位数金额一致,分组外,每个分组整合有不同的单位
 *     3. 程序可以转换整数部分长达16位的金额,最高单位是万亿,再向上的单位暂时没有理清,后面有机会会补充
 *     4. 考虑带小数点的金额,转换方法类似,相对整数部分摊简单一些,小数可以精确到小数点后3位数,3位以后的小数没有可用的单位,不考虑
 *     5. 阿拉伯数字与汉字大写之间的转换利用查表法实现
 *     
 */
public class Test10 {

	public static void main(String[] args) {
		String str="400100001010.098";
		//String str="0100";
		//System.out.println(four2Ch(str));
		num2Ch(str);
	}
	public static void num2Ch(String str){
		String[] strs=str.split("\\.");		
		int len=strs[0].length();
		StringBuilder strBuilder=new StringBuilder();
		StringBuilder strB=new StringBuilder();
		String[] bigTable={"圆","万","亿","万亿"};
		int n=0;
		//以4位为一组,先不带单位转换该组为汉字形式,然后每组再加上对应的"圆","万","亿","万亿"单位
		while(len>0){
			int start=(len-4)>0?len-4:0;
			strB=four2Ch(strs[0].substring(start, len));
			strBuilder.insert(0,strB);
			if(strB.length()==0){
				//有多个连续的零时只显示一个
				if(!strBuilder.toString().startsWith("零")){
					strBuilder.insert(strB.length(),"零");
				}
			}else{
				strBuilder.insert(strB.length(),bigTable[n]);
			}
			n++;
			len=len-4;
		}
		if(strs.length>1){
			strBuilder.append(point2Ch(strs[1]));
		}else{
			strBuilder.append("整");
		}
		System.out.println(strBuilder.toString());
	}
	
    //将一个任意4位以内的数转换成中国传统货币形式
	public static StringBuilder four2Ch(String str){
		StringBuilder strB=new StringBuilder();
		String[] numTable={"零","壹","贰","叁","肆","伍","陆","柒","捌","玖"};
		String[] unitTable={"","拾","百","仟"};
		int len=str.length();
		char[] chArr=str.toCharArray();		
		for(int i=len-1;i>=0;i--){
			//某一位上为0是,不显示该位的单位
			if(chArr[i]=='0'){	
				//结尾处的0不转换,直接去掉,除结尾外,其余位置有连续的多个零时,只保留一个零
				if(i!=len-1&&chArr[i+1]!='0')
					strB.append("零");
			}
			//该位上值不为0时,转换该值为汉字形式,并显示其单位
			else{
				strB.append(unitTable[len-1-i]);
				strB.append(numTable[chArr[i]-48]);
			}				
		}
		return strB.reverse();
	}
	//将小数转换成角、分、厘形式
	public static StringBuilder point2Ch(String str){
		StringBuilder strP=new StringBuilder();
		String[] pnumTable={"零","壹","贰","叁","肆","伍","陆","柒","捌","玖"};
		String[] punitTable={"角","分","厘"};
		int len=str.length();
		char[] chArr=str.toCharArray();	
		for(int i=0;i<len;i++){
			if(chArr[i]=='0'){
				if(i!=len-1&&chArr[i+1]!='0')
					strP.append("零");
			}else{
				
				strP.append(pnumTable[chArr[i]-48]);
				strP.append(punitTable[i]);
			}
		}
		return strP;
	}
}