- 表达式计算(支持空格,连乘,连除)(选做题,不计分)
【问题描述】
从标准输入中读入一个整数算术运算表达式,如5 - 1 * 2 * 3 + 12 / 2 / 2 = 。计算表达式结果,并输出。
要求:
1、表达式运算符只有+、-、*、/,表达式末尾的'='字符表示表达式输入结束,表达式中可能会出现空格;
2、表达式中不含圆括号,不会出现错误的表达式;
3、出现除号/时,以整数相除进行运算,结果仍为整数,例如:5/3结果应为1。
【输入形式】
在控制台中输入一个以'='结尾的整数算术运算表达式。
【输出形式】
向控制台输出计算结果(为整数)。
【样例1输入】
5 - 1 * 2 * 3 + 12 / 2 / 2 =
【样例1输出】
2
【样例2输入】
500 =
【样例2输出】
500
【样例1说明】
输入的表达式为5 - 1 * 2 * 3 + 12 / 2 / 2 =,按照整数运算规则,计算结果为2,故输出2。
【样例2说明】
输入的表达式为500 = ,没有运算符参与运算,故直接输出500。
算法之一提示:
1、可以利用gets函数,读取整行表达式;
2、对于空格,可以考虑首先去除表达式中的所有空格
3、可以设一计数器用来记录已读取、但未参加运算的运算符的个数,根据该计数器来判断如何进行运算;
4、可以设计一函数:实现二元整数算术运算。
import java.util.Scanner;
import java.util.Scanner;
import java.util.Stack;
public class ArithmeticExpression {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String expression = scanner.nextLine();
int result = evaluateExpression(expression);
System.out.println( result);
}
private static boolean isOperator(char c) {
return c == '+' || c == '-' || c == '*' || c == '/';
}
private static int getPrecedence(char op) {
if (op == '+' || op == '-')
return 1;
if (op == '*' || op == '/')
return 2;
return 0;
}
private static int applyOperation(int num1, int num2, char op) {
switch (op) {
case '+':
return num1 + num2;
case '-':
return num1 - num2;
case '*':
return num1 * num2;
case '/':
return num1 / num2;
default:
return 0;
}
}
private static int evaluateExpression(String expression) {
Stack<Integer> operands = new Stack<>();
Stack<Character> operators = new Stack<>();
for (int i = 0; i < expression.length(); i++) {
char c = expression.charAt(i);
if (Character.isWhitespace(c))
continue;
if (Character.isDigit(c)) {
int num = c - '0';
while (i + 1 < expression.length() && Character.isDigit(expression.charAt(i + 1))) {
num = num * 10 + (expression.charAt(i + 1) - '0');
i++;
}
operands.push(num);
} else if (c == '(') {
operators.push(c);
} else if (c == ')') {
while (!operators.isEmpty() && operators.peek() != '(') {
int num2 = operands.pop();
int num1 = operands.pop();
char op = operators.pop();
int result = applyOperation(num1, num2, op);
operands.push(result);
}
operators.pop(); // 弹出左括号
} else if (isOperator(c)) {
while (!operators.isEmpty() && isOperator(operators.peek()) && getPrecedence(operators.peek()) >= getPrecedence(c)) {
int num2 = operands.pop();
int num1 = operands.pop();
char op = operators.pop();
int result = applyOperation(num1, num2, op);
operands.push(result);
}
operators.push(c);
}
}
while (!operators.isEmpty()) {
int num2 = operands.pop();
int num1 = operands.pop();
char op = operators.pop();
int result = applyOperation(num1, num2, op);
operands.push(result);
}
return operands.pop();
}
}
2.合并数列
【问题描述】从标准输入上读入2N行(行号从0开始)由空格分隔的整数,并顺序将第2i和2i+1行(0 <= i <= N)合并成一个由小到大排好序并删除重复数字的数列,写在标准输出上,每个数列一行。每一个原始数列不超过50个数字。
【输入形式】输入2N行整数,每行对应一个数列。每行有k个数字,是属于这一数列的所有整数,由空格分隔。这些整数随机排列,并可能含有重复数字。程序的任务就是将每两个相邻的数列合并成一个,并且从小到大排序,同时要删除重复数字。
【输出形式】输出有N行,每行有若干个空格分隔的整数,是在输入文件中对应两个输入行的合并结果。并且:
1.这些数字已经从小到大排序。
2.不含重复数字。
【样例输入】
18 29 30 27 26
20 30 5 29
76 80
99 233 87 35 24 9
27 234 27
65 70 39 87 35 24 100
【样例输出】
5 18 20 26 27 29 30
9 24 35 76 80 87 99 233
24 27 35 39 65 70 87 100 234
【样例说明】输入共有6行整数。第一个数列含5个整数,分别是18、29、30、27、26。依次类推,第二个数列含4个整数,第三个数列含2个整数,......,第六个数列含7个整数。输出共有三行数字。输出的第一行是将原输出的第一、二个数列合并,同时删除重复数字并从小到大排序的结果。输出的第二行是将原输出的第三、四个数列合并,同时删除重复数字并从小到大排序的结果。输出的第三行是将原输出的第五、六个数列合并,同时删除重复数字并从小到大排序的结果。
【运行时限】要求每次运行时间限制在10秒之内。超出时间则认为程序错误。
【评分标准】输出的数字中。如果你的程序计算的完全正确,该测试点得10分,否则算该测试点得分为0。
import java.util.*;
public class MergeAndSort {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
List<List<Integer>> result = new ArrayList<>();
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.isEmpty()) {
break;
}
List<Integer> line1 = parseLine(line);
if (!scanner.hasNextLine()) {
// 如果只有单独的一行,直接输出该行而不进行合并
result.add(line1);
break;
}
List<Integer> line2 = parseLine(scanner.nextLine());
if (line1.isEmpty() || line2.isEmpty()) {
// 如果其中一行为空,直接输出非空的行
if (!line1.isEmpty()) {
result.add(line1);
}
if (!line2.isEmpty()) {
result.add(line2);
}
} else {
List<Integer> merged = mergeAndSort(line1, line2);
result.add(merged);
}
}
for (List<Integer> mergedList : result) {
Collections.sort(mergedList); // 对每一行进行排序
for (int num : mergedList) {
System.out.print(num + " ");
}
System.out.println();
}
}
private static List<Integer> parseLine(String line) {
List<Integer> numbers = new ArrayList<>();
String[] tokens = line.split(" ");
for (String token : tokens) {
numbers.add(Integer.parseInt(token));
}
return numbers;
}
private static List<Integer> mergeAndSort(List<Integer> list1, List<Integer> list2) {
Set<Integer> set = new TreeSet<>();
set.addAll(list1);
set.addAll(list2);
return new ArrayList<>(set);
}
}
3.计算星期
【问题描述】
已知1980年1月1日是星期二。
任意输入一个日期,求这一天是星期几。
【输入形式】
从键盘输入一行字符串"Y-M-D",是一个有效的公历日期。其中Y为年(1980≤Y≤3000),M为月,D为天,都不带有前缀0。
【输出形式】
在屏幕输出结果。
输出只有一行,是代表该日星期的字符串。对于星期一至星期日,分别输出Monday、Tuesday、Wednesday、Thursday、Friday、Saturday、Sunday。在行末要输出一个回车符。判断闰年的算法是:
年份能被4整除并且不能被100整除,或者能被四百整除。
【输入样例】
2004-1-6
【输出样例】
Tuesday
【评分标准】
本题不准使用数学库函数。运行时限1秒。结果完全正确得20分,每个测试点4分。
import java.util.Scanner;
public class CalculateWeekday {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
String[] tokens = input.split("-");
int year = Integer.parseInt(tokens[0]);
int month = Integer.parseInt(tokens[1]);
int day = Integer.parseInt(tokens[2]);
int weekday = calculateWeekday(year, month, day);
String weekdayString = getWeekdayString(weekday);
System.out.println(weekdayString);
}
private static int calculateWeekday(int year, int month, int day) {
// 计算从1980年1月1日到目标日期的总天数
int days = calculateTotalDays(year, month, day);
// 1980年1月1日是星期二,因此计算星期数时需要加上偏移量
int offset = 2;
// 对7取模,得到星期几的数值(0代表星期一,1代表星期二,以此类推)
int weekday = ( days) % 7;
return weekday;
}
private static int calculateTotalDays(int year, int month, int day) {
// 每个月的天数
int[] daysInMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
// 判断是否为闰年,并更新2月的天数
if (isLeapYear(year)) {
daysInMonth[1] = 29;
}
int totalDays = 0;
// 计算整年的天数
for (int i = 1980; i < year; i++) {
if (isLeapYear(i)) {
totalDays += 366;
} else {
totalDays += 365;
}
}
// 计算当年的天数
for (int i = 0; i < month - 1; i++) {
totalDays += daysInMonth[i];
}
totalDays += day;
return totalDays;
}
private static boolean isLeapYear(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
private static String getWeekdayString(int weekday) {
String[] weekdays = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
return weekdays[weekday];
}
}
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Scanner;
public class CalculateWeekday {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-M-d");
LocalDate date = LocalDate.parse(input, formatter);
DayOfWeek weekday = date.getDayOfWeek();
String weekdayString = weekday.toString();
System.out.println(weekdayString);
}
}
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.Scanner;
public class CalculateWeekday {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
String[] tokens = input.split("-");
int year = Integer.parseInt(tokens[0]);
int month = Integer.parseInt(tokens[1]);
int day = Integer.parseInt(tokens[2]);
LocalDate date = LocalDate.of(year, month, day);
DayOfWeek weekday = date.getDayOfWeek();
String weekdayString = weekday.toString().substring(0, 1) + weekday.toString().substring(1).toLowerCase();
System.out.println(weekdayString);
}
}
4、比较两组整数
【问题描述】
比较两组整数是否有相同的元素,不考虑元素的顺序,并忽略元素重复的情况。例如:
1 4 9 16 9 7 4 9 11
与下列一组整数:
11 7 9 16 4 1
相同。
【输入形式】
分行输入两组整数,以空格分割
【输出形式】
打印两组整数中相同的元素,顺序以第一行的整数输出顺序为准,如果没有相同元素,打印"No Answer"
【输入样例】
1 4 9 16 9 7 4 9 11
11 7 9 16 4 1
【输出样例】
"#"代表空格
1#4#9#16#7#11#
【样例说明】
输入两组整数
1 4 9 16 9 7 4 9 11
11 7 9 16 4 1
由于这两个数组具有相同的元素,顺序打印第一行与第二行相同的元素
【评分标准】
该题要求输出相同元素,答对得20分,每个测试点4分。
import java.util.*;
public class CompareIntegers {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input1 = scanner.nextLine();
String input2 = scanner.nextLine();
String[] nums1 = input1.split(" ");
String[] nums2 = input2.split(" ");
Set<String> set1 = new LinkedHashSet<>(Arrays.asList(nums1));
Set<String> set2 = new HashSet<>(Arrays.asList(nums2));
set1.retainAll(set2);
if (set1.isEmpty()) {
System.out.println("No Answer");
} else {
StringBuilder output = new StringBuilder();
for (String num : nums1) {
if (set1.contains(num)) {
output.append(num).append(" ");
set1.remove(num);
}
}
output.deleteCharAt(output.length() - 1);
System.out.println(output.toString());
}
}
}
5、字符串匹配
问题描述】利用"通配符",可以用简单的方法标记一组字符串。
通配符有两个,"?"代表一个任意字符,"*"代表0个或多个任意字符。
例如:
AB?.txt可以表示AB1.txt,AB2.txt,ABa.txt 等。
AB*.txt可以表示AB.txt, AB1.txt,AB332.txt,ABaa.txt等。
编写程序,判断一个字符串是否符合一个含有通配符的串。
【输入文件】从文件match.in读取输入。
第一行是一个串,含有通配符"?"或"*",或两者兼有。
第二行是一个数字n(3≤n≤10),代表后续有n个待检验串。
后面的n行,每行有一个不含通配符的待检验串。
输入中的所有串均只包含英文字母(大小写)和数字,不含空格,长度在80字符以内。
【输出文件】输出到文件match.out中。将所有符合的串按原顺序分行打印。在每一行末均输出一个回车符。
【输入样例】
abcd?123*
4
abce123
abcda12345
abcda123
1234
【输出样例】
abcda12345
abcda123
【样例说明】abcda12345和abcda123符合abcd?123*的顺序。
【评分标准】结果正确则该测试点得满分,否则该测试点得0分。上传c语言源程序为match.c。
import java.util.Scanner;
public class everydayjava {
public static boolean matchPattern(String pattern, String text) {
int m = pattern.length();
int n = text.length();
boolean[][] a = new boolean[m + 1][n + 1];
a[0][0] = true;
for (int i = 1; i <= m; i++) {
for (int j = 0; j <= n; j++) {
if (pattern.charAt(i - 1) == '*') {
a[i][j] = a[i - 1][j] || (j > 0 && a[i][j - 1]);
} else if (j > 0 && (pattern.charAt(i - 1) == '?' || pattern.charAt(i - 1) == text.charAt(j - 1))) {
a[i][j] = a[i - 1][j - 1];
}
}
}
return a[m][n];
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入测试判断模板: ");
String pattern = scanner.nextLine();
System.out.print("请输入测试数据的个数: ");
int n = scanner.nextInt();
scanner.nextLine();
System.out.println("请输入用于测试的字符串:");
for (int i = 0; i < n; i++) {
String text = scanner.nextLine();
if (matchPattern(pattern, text)) {
System.out.println(text);
}
}
scanner.close();
}
}
6.将文件中每一行字符反序
【问题描述】对于一个文本文件text1.dat,编写一个程序,将该文件中的每一行字符颠倒顺序后输出到另一个文件text2.dat中。
【输入文件】输入文件为当前目录下的text1.dat,该文件含有多行任意字符,也可能有空行。每个文本行最长不超过80个字符。在最后一行的结尾也有一个回车符。
【输出文件】输出文件为当前目录下的text2.dat。
【样例输入】设输入文件text1.dat为:
This is a test!
Hello, world!
How are you?
【样例输出】输出文件text2.dat为:
!tset a si sihT
!dlrow ,olleH
?uoy era woH
【样例说明】将输入文件反序输出。
【评分标准】输出文件应与输入文件的字符个数相等,并且符合题目规定的格式。如果你的程序输出正确,该测试点得满分,否则该测试点不得分。
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class ReverseLines {
public static void main(String[] args) {
String inputFile = "text1.dat";
String outputFile = "text2.dat";
try (BufferedReader reader = new BufferedReader(new FileReader(inputFile));
BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile))) {
String line;
while ((line = reader.readLine()) != null) {
String reversedLine = reverseString(line);
writer.write(reversedLine);
writer.newLine();
}
System.out.println("Reversing lines completed successfully.");
} catch (IOException e) {
System.out.println("An error occurred: " + e.getMessage());
}
}
private static String reverseString(String str) {
StringBuilder reversed = new StringBuilder(str);
return reversed.reverse().toString();
}
}