对于以下几题所使用的语言的要求: (1) 每题所使用的编程语言可以使用Java、Python或Scala; (2) 除非题目中有特别说明,语言的标准库都是可以使用的,不要使用其他第三方的库。 1. 文件改名工具 编写一个程序,将指定目录及其所有子目录下的所有包含空格的文件改名(无需将目录改 名),改名的规则为将原文件名中的空格替换为下划线“_”。如果改名后的文件名出现冲突, 则报告错误信息并且中止改名。指定目录可以由命令行参数指定。 2. 文本编辑器 编写一个微型的面向行的文本编辑器。用户通过命令行的方式与文本编辑器交互。编辑器接 收如下命令: a [<文本>] 追加一行文本(若无文本,则追加一个空行) d <行号> 删除指定行 i <行号> <文本> 在指定行之前插入一行文本 s 显示所有的行,包括每行的行号 u 撤销上一个编辑操作(a、d、i都属于编辑操作,其他不是) w <文件名> 将所有内容输出到指定的文件中 q 退出 例: 输入: a Hello world! 输入: a This is a line of text. 输入: i 2 the second line 输入: a the last line 输入: s 输出: 1: Hello world! 2: the second line 3: This is a line of text. 4: the last line 输入: d 2 输入: u 输入: d 3 输入: w a.txt 输入: q a.txt文件的内容应当是: Hello world! the second line the last line 要求:在设计时应当考虑其可扩展性,例如,日后如果需要增加新的编辑命令,应避免对已 实现的命令的代码进行修改。 3.归并 编写一个方法merge,该方法的两个输入参数的类型为任意可比较大小的类型的序列,用户调 用该方法时保证输入的两个序列都是按照升序排列好的。编写一个函数,对两个序列进行合 并,生成一个新的序列,该序列包含两个输入序列中的所有元素,并且这些元素在合并后的 序列中也是升序排列的。将合并后的序列返回。 自己定义函数接口,给出函数实现,并且写出测试代码。 例如,若选用Java语言,用户会这样使用该函数: List<Integer> s1 = Arrays.asList(3, 6, 7, 12); List<Integer> s2 = Arrays.asList(-1, 5, 14); List<Integer> result = merge(s1, s2); 若使用Python语言,用户会这样使用该函数: s1 = [3, 6, 7, 12] s2 = [-1, 5, 14] result = merge(s1, s2) 若使用Scala语言,用户会这样使用该函数: val s1 = 3 :: 6 :: 7 :: 12 :: Nil val s2 = -1 :: 5 :: 14 :: Nil val result = merge(s1, s2) 要求:需要注意算法效率,应当保证算法的时间复杂度为O(n),其中n是两个输入列表的长度 和。不允许使用现成的排序方法实现。 4. 消息队列 实现一个支持多线程的消息队列,支持两种操作: (1) push:向队列中放置一个新的元素; (2) pop:从队列中取出一个元素。 执行pop时,若队列中的元素为空,则当前线程阻塞,直到队列中有元素位置。 自己给出接口和实现,并且写出测试代码。
第一题:
1. 文件改名工具
编写一个程序,将指定目录及其所有子目录下的所有包含空格的文件改名(无需将目录改
名),改名的规则为将原文件名中的空格替换为下划线“_”。如果改名后的文件名出现冲突,
则报告错误信息并且中止改名。指定目录可以由命令行参数指定。
1 import java.io.File; 2 3 public class Test{ 4 public static void main(String[] args){ 5 File file = new File("C:/01-test"); 6 if(!file.exists()){ 7 System.out.println("没有指定的目录文件。"); 8 return; 9 }else{ 10 boolean flag = rename(file); 11 if(!flag){ 12 System.out.println("没有要修改的文件"); 13 } 14 } 15 } 16 17 public static boolean rename(File file){ 18 boolean state = false; 19 File[] files = file.listFiles(); 20 if(files != null){ 21 for(File f:files){ 22 if(!f.isDirectory()){ 23 String s = f.getName(); 24 int i = s.indexOf(" "); 25 if(i != -1){ 26 state = true; 27 s = s.replaceAll(" ", "-"); 28 File f2 = new File(f.getParent() + "/" + s); 29 boolean flag = f.renameTo(f2); 30 if(flag){ 31 System.out.println("成功修改一个文件名"); 32 }else{ 33 System.out.println("失败"); 34 } 35 } 36 } 37 rename(f); 38 } 39 } 40 return state; 41 } 42 }
第二题:
2. 文本编辑器
编写一个微型的面向行的文本编辑器。用户通过命令行的方式与文本编辑器交互。编辑器接
收如下命令:
a [<文本>] 追加一行文本(若无文本,则追加一个空行)
d <行号> 删除指定行
i <行号> <文本> 在指定行之前插入一行文本
s 显示所有的行,包括每行的行号
u 撤销上一个编辑操作(a、d、i都属于编辑操作,其他不是)
w <文件名> 将所有内容输出到指定的文件中
q 退出
例:
输入: a Hello world!
输入: a This is a line of text.
输入: i 2 the second line
输入: a the last line
输入: s
输出: 1: Hello world!
2: the second line
3: This is a line of text.
4: the last line
输入: d 2
输入: u
输入: d 3
输入: w a.txt
输入: q
a.txt文件的内容应当是:
Hello world!
the second line
the last line
要求:在设计时应当考虑其可扩展性,例如,日后如果需要增加新的编辑命令,应避免对已
实现的命令的代码进行修改。
1 import java.io.File; 2 import java.io.FileNotFoundException; 3 import java.io.PrintWriter; 4 import java.util.ArrayList; 5 import java.util.Scanner; 6 7 public class Test02 { 8 public static void main(String[] args) { 9 ArrayList<String> strList = new ArrayList<String>(); 10 Scanner sc = new Scanner(System.in); 11 String commonBak = ""; 12 String deleteBak = ""; 13 boolean state = false; 14 exit: 15 while (true) { 16 String str = sc.nextLine(); 17 if (str.length() == 1 || str.substring(1, 2).equals(" ")) { 18 String temp = str.substring(0, 1); 19 switch (temp) { 20 case "a": 21 if (str.length() == 1 || str.substring(2).equals(null)) { 22 strList.add(""); 23 } else { 24 strList.add(str.substring(2)); 25 state = true; 26 commonBak = str; 27 } 28 break; 29 case "d": 30 if (str.length() == 1 || str.substring(2).equals(null)) { 31 System.out.println("请添加行号"); 32 } else { 33 String s = str.substring(2).replaceAll(" ", ""); 34 boolean flag = false; 35 for (int i = 0; i < s.length(); i++) { 36 if (java.lang.Character.isDigit((char) s.charAt(i))) { 37 flag = true; 38 } else { 39 flag = false; 40 } 41 } 42 if (flag) { 43 int line = Integer.parseInt(s); 44 if (line > strList.size()) { 45 System.out.println("行号太大,找不到指定的行"); 46 } else { 47 deleteBak = strList.get(line - 1); 48 strList.remove(line - 1); 49 state = true; 50 commonBak = str; 51 } 52 } else { 53 System.out.println("指定的行号不正确"); 54 } 55 } 56 break; 57 case "i": 58 if (str.length() == 1 || str.substring(2).equals(null)) { 59 System.out.println("请添加行号"); 60 } else { 61 String arr[] = str.split(" "); 62 boolean flag = false; 63 for (int i = 0; i < arr[1].length(); i++) { 64 if (java.lang.Character.isDigit((char) arr[1] 65 .charAt(i))) { 66 flag = true; 67 } else { 68 flag = false; 69 } 70 } 71 if (flag) { 72 int line = Integer.parseInt(arr[1]); 73 if (line > strList.size()) { 74 System.out.println("行号太大,找不到指定的行"); 75 } else { 76 String s = ""; 77 for (int i = 2; i < arr.length; i++) { 78 s = s + arr[i] + " "; 79 } 80 strList.add(line - 1, s); 81 state = true; 82 commonBak = str; 83 } 84 } else { 85 System.out.println("指定的行号不正确"); 86 } 87 } 88 break; 89 case "s": 90 for (int i = 0; i < strList.size(); i++) { 91 int num = i + 1; 92 System.out.println(num + ":" + strList.get(i)); 93 } 94 break; 95 case "u": 96 if(!state || commonBak.equals("")){ 97 System.out.println("没有上一步操作,无法撤销!"); 98 }else{ 99 String common = commonBak.substring(0, 1); 100 switch (common){ 101 case "a": 102 strList.remove(strList.size() - 1); 103 break; 104 case "d": 105 String arrD[] = commonBak.split(" "); 106 int line = Integer.parseInt(arrD[1]); 107 strList.add(line - 1, deleteBak); 108 break; 109 case "i": 110 String arrI[] = commonBak.split(" "); 111 int lineI = Integer.parseInt(arrI[1]); 112 strList.remove(lineI - 1); 113 break; 114 default: 115 break; 116 } 117 } 118 break; 119 case "w": 120 String arr[] = str.split(" "); 121 File file = new File("D:/" + arr[1]); 122 PrintWriter pfp = null; 123 try { 124 pfp = new PrintWriter(file); 125 for(int i = 0; i < strList.size(); i++){ 126 pfp.print(strList.get(i) + " "); 127 } 128 System.out.println("已保存在D:/" + arr[1]); 129 } catch (FileNotFoundException e) { 130 e.printStackTrace(); 131 } finally { 132 pfp.close(); 133 } 134 break; 135 case "q": 136 System.out.println("已退出"); 137 break exit; 138 case "p": 139 for (int i = 0; i < strList.size(); i++) { 140 System.out.println(strList.get(i)); 141 } 142 break; 143 default: 144 break; 145 } 146 } else { 147 System.out.println("请在命令后加空格"); 148 } 149 } 150 } 151 }
第三题:
3.归并
编写一个方法merge,该方法的两个输入参数的类型为任意可比较大小的类型的序列,用户调
用该方法时保证输入的两个序列都是按照升序排列好的。编写一个函数,对两个序列进行合
并,生成一个新的序列,该序列包含两个输入序列中的所有元素,并且这些元素在合并后的
序列中也是升序排列的。将合并后的序列返回。
自己定义函数接口,给出函数实现,并且写出测试代码。
例如,若选用Java语言,用户会这样使用该函数:
List<Integer> s1 = Arrays.asList(3, 6, 7, 12);
List<Integer> s2 = Arrays.asList(-1, 5, 14);
List<Integer> result = merge(s1, s2);
若使用Python语言,用户会这样使用该函数:
s1 = [3, 6, 7, 12]
s2 = [-1, 5, 14]
result = merge(s1, s2)
若使用Scala语言,用户会这样使用该函数:
val s1 = 3 :: 6 :: 7 :: 12 :: Nil
val s2 = -1 :: 5 :: 14 :: Nil
val result = merge(s1, s2)
要求:需要注意算法效率,应当保证算法的时间复杂度为O(n),其中n是两个输入列表的长度
和。不允许使用现成的排序方法实现。
1 import java.util.ArrayList; 2 import java.util.Arrays; 3 import java.util.List; 4 5 public class Test03 { 6 public static void main(String[] args) { 7 List<Integer> s1 = Arrays.asList(3, 6, 7, 12); 8 List<Integer> s2 = Arrays.asList(-1, 5, 14); 9 List<Integer> result = merge(s1, s2); 10 for(int i = 0; i < result.size(); i++){ 11 System.out.println(result.get(i)); 12 } 13 } 14 15 public static List merge(List s1, List s2) { 16 Object obj = s1.get(0); 17 if (obj instanceof Integer) { 18 int[] arr = new int[s1.size() + s2.size()]; 19 // 合并 20 for (int i = 0; i < s1.size() + s2.size(); i++) { 21 if (i < s1.size()) { 22 arr[i] = (int) s1.get(i); 23 } else { 24 arr[i] = (int) s2.get(i - s1.size()); 25 } 26 } 27 // 排序 28 for (int i = 0; i < arr.length; i++) { 29 for (int j = 0; j < arr.length; j++) { 30 // 小于号:从小到大排序;大于号:从大到小排序; 31 if (arr[i] < arr[j]) { 32 int bak = arr[j]; 33 arr[j] = arr[i]; 34 arr[i] = bak; 35 } 36 } 37 } 38 // 添加到list 39 List<Integer> result = new ArrayList<Integer>(); 40 for (int i = 0; i < arr.length; i++) { 41 result.add(arr[i]); 42 } 43 return result; 44 } else if (obj instanceof Double) { 45 // 待添加 46 return null; 47 } else if (obj instanceof Float) { 48 // 待添加 49 return null; 50 } else { 51 return null; 52 } 53 } 54 }
第四题:
4. 消息队列
实现一个支持多线程的消息队列,支持两种操作:
(1) push:向队列中放置一个新的元素;
(2) pop:从队列中取出一个元素。
执行pop时,若队列中的元素为空,则当前线程阻塞,直到队列中有元素位置。
自己给出接口和实现,并且写出测试代码。
1 import java.util.ArrayList; 2 import java.util.List; 3 4 class Test04 { 5 public static void main(String[] args) { 6 Server s = new Server(); 7 MyPush myPush = new MyPush(s); 8 MyPop myPop = new MyPop(s); 9 Thread t1 = new Thread(myPush); 10 Thread t2 = new Thread(myPop); 11 t1.start(); 12 t2.start(); 13 } 14 } 15 16 class Server { 17 List<String> list = new ArrayList(); 18 int index = 0; 19 20 public synchronized void push(String s) { 21 while (index == 20) { 22 try { 23 this.wait(); 24 } catch (InterruptedException e) { 25 e.printStackTrace(); 26 } 27 } 28 this.notify(); 29 index++; 30 list.add(s); 31 System.out.println("添加了一行内容,现在共有" + index + "行。"); 32 } 33 34 public synchronized void pop() { 35 while (index == 0) { 36 try { 37 System.out.println("没有内容,无法获取。"); 38 this.wait(); 39 } catch (InterruptedException e) { 40 e.printStackTrace(); 41 } 42 } 43 this.notify(); 44 list.remove(list.size() - 1); 45 index--; 46 int num = index + 1; 47 System.out.println("删除了第" + num + "行内容。" + "还剩" + list.size() + "行内容。"); 48 } 49 } 50 51 class MyPush implements Runnable { 52 Server s = new Server(); 53 54 public MyPush(Server s) { 55 this.s = s; 56 } 57 58 @Override 59 public void run() { 60 for (int i = 0; i < 20; i++) { 61 s.push("test"); 62 try { 63 Thread.sleep((int) (Math.random() * 1000)); 64 } catch (Exception e) { 65 e.printStackTrace(); 66 } 67 } 68 } 69 } 70 71 class MyPop implements Runnable { 72 Server s = new Server(); 73 74 public MyPop(Server s) { 75 this.s = s; 76 } 77 78 @Override 79 public void run() { 80 for (int i = 0; i < 20; i++) { 81 s.pop(); 82 try { 83 Thread.sleep((int) (Math.random() * 1000)); 84 } catch (Exception e) { 85 e.printStackTrace(); 86 } 87 } 88 } 89 }