OOP 1~3总结
oop 1~3总结
前言
-
知识点
1.类的基本运用、类与对象的运用、类与数组的运用、关联类的使用2.接口的初步了解与运用
3.日期类的使用这三次作业的最后一题涉及到的知识点比较多,综合性很强。宏观上重点考察的是我们对面向对象技术的整体把握,对程序设计原则的理解与使用,同时在细节上也考察了我们对java语法的掌握。例如:用正则表达式处理输入语句的格式、用数组、列表或Map对数据进行存储、用split()函数分割字符串等等。在完成作业时,由于题目每次都进行迭代,一次比一次难,涉及到的知识点也一次比一次多。
-
题量
整体的题量不算多,但是质量很高,每道题目的侧重点都稍有不同。若能认真完成作业上的题目,将每道题都理解透彻,就会对个人能力的提升有极大的帮助。
-
难度
对我个人而言,最后一题的难度是非常的大。不仅题干长难以理解,并且要有宏观的设计能力,要将不同的类之间的关系理清晰。但是我的基础比较差,有很多基础的语法我还没有搞清楚。再加上这个题目是老师原创的,之前没有见过类似的,我觉得比较抽象,也增加了题目的难度,完成起来很是困难。
设计与分析
第一次作业 答题判题程序-1
设计实现答题程序,模拟一个小型的测试,要求输入题目信息和答题信息,根据输入题目信息中的标准答案判断答题的结果。
输入格式:
程序输入信息分三部分:
1、题目数量
格式:整数数值,若超过1位最高位不能为0,
样例:34
2、题目内容
一行为一道题,可以输入多行数据。
格式:"#N:"+题号+" "+"#Q:"+题目内容+" "#A:"+标准答案
格式约束:题目的输入顺序与题号不相关,不一定按题号顺序从小到大输入。
样例:#N:1 #Q:1+1= #A:2
\#N:2 #Q:2+2= #A:4
3、答题信息
答题信息按行输入,每一行为一组答案,每组答案包含第2部分所有题目的解题答案,答案的顺序号与题目题号相对应。
格式:"#A:"+答案内容
格式约束:答案数量与第2部分题目的数量相同,答案之间以英文空格分隔。
样例:#A:2 #A:78
2是题号为1的题目的答案
78是题号为2的题目的答案
答题信息以一行"end"标记结束,"end"之后的信息忽略。
输出格式:
1、题目数量
格式:整数数值,若超过1位最高位不能为0,
样例:34
2、答题信息
一行为一道题的答题信息,根据题目的数量输出多行数据。
格式:题目内容+" ~"+答案
样例:1+1=~2
2+2= ~4
3、判题信息
判题信息为一行数据,一条答题记录每个答案的判断结果,答案的先后顺序与题目题号相对应。
格式:判题结果+" "+判题结果
格式约束:
1、判题结果输出只能是true或者false,
2、判题信息的顺序与输入答题信息中的顺序相同
样例:true false true
类图:
源码如下:
import java.util.Scanner;
class Question {
int questionNumber;
String questionContent;
String standardAnswer;
public Question() {
}
public Question(int questionNumber, String questionContent, String standardAnswer) {
this.questionNumber = questionNumber;
this.questionContent = questionContent;
this.standardAnswer = standardAnswer;
}
public void setQuestionContent(String questionContent) {
this.questionContent = questionContent;
}
public String getQuestionContent() {
return questionContent;
}
}
class Paper {
Question[] questions;
String[] standardAnswers;
public Paper(int numQuestions) {
questions = new Question[numQuestions];
standardAnswers = new String[numQuestions];
}
public void addQuestion(Question question, int index) {
questions[index] = question;
}
public void setStandardAnswer(String standardAnswer, int index) {
standardAnswers[index] = standardAnswer;
}
public boolean isCorrectAnswer(AnswerSheet answerSheet, int index) {
return standardAnswers[index].equals(answerSheet.getAnswer(index));
}
public Question getQuestion(int index) {
return questions[index];
}
}
class AnswerSheet {
String[] answers;
public AnswerSheet(int numQuestions) {
answers = new String[numQuestions];
}
public void setAnswer(String answer, int index) {
answers[index] = answer;
}
public String getAnswer(int index) {
return answers[index];
}
}
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
input.nextLine(); // Consume newline
Paper paper = new Paper(n);
AnswerSheet answerSheet = new AnswerSheet(n);
for (int i = 0; i < n; i++) {
String line = input.nextLine();
String[] input1 = line.split(" *#N: *| *#A: *| *#Q: *");
int num1 = Integer.parseInt(input1[1]) - 1;
String content1 = input1[2];
String standardAnswer1 = input1[3];
Question question= new Question(num1, content1, standardAnswer1);
paper.addQuestion(question, question.questionNumber);
paper.setStandardAnswer(question.standardAnswer, question.questionNumber);
}
String answerInput = input.nextLine();
String[] answers = answerInput.split(" *#A: *");
for (int i = 0; i < n; i++) {
answerSheet.setAnswer(answers[i + 1], i);
}
for (int i = 0; i < n; i++) {
System.out.println(paper.getQuestion(i).getQuestionContent() + "~" + answerSheet.getAnswer(i));
}
for (int i = 0; i < n; i++) {
if (i == n - 1) {
System.out.print(paper.isCorrectAnswer(answerSheet, i));
} else {
System.out.print(paper.isCorrectAnswer(answerSheet, i) + " ");
}
}
}
}
设计思路:
这道题目我是在老师给出来的设计建议上进行的类设计,分别设计了Question、Paper、和AnswerSheet类。
- Question类表示一个题目,包含题号、题目内容和标准答案。这个类提供了带参数的构造函数用于初始化题目对象,以及 getter 和 setter 方法来获取和设置题目内容。
- Paper类用于表示整张试卷,包含了题目数组和标准答案数组。构造函数接受题目数量作为参数,初始化题目和标准答案数组。addQuestion()方法接收Question类的对象和其在数组中的索引位置用来向试卷中添加题目;setStandardAnswer()方法接收传入的标准答案和索引位置用来向试卷中添加标准答案;isCorrectAnswer() 方法用于判断学生的答案是否正确。getQuestion() 方法来获取试卷中的某个题目。
- AnswerSheet类用于表示学生的答题卡,包含了学生的答案数组。构造函数接收题目数量作为参数,初始化答案数组。并且提供了setter和getter方法来获取和设置学生的答案。
- Main类包含了 首先从用户输入读取题目数量 n,然后创建试卷对象和答题卡对象。接着通过循环读取用户输入的每道题目的信息,解析后将题目添加到试卷对象中,并设置标准答案。读取学生的答案输入后,将学生的答案设置到答题卡对象中。最后循环输出每个题目及对应的学生答案,以及判断每个学生答案是否正确。
第二次作业 答题判题程序-2
以下粗体字显示的是在答题判题程序-1基础上增补或者修改的内容。
要求输入题目信息、试卷信息和答题信息,根据输入题目信息中的标准答案判断答题的结果。
输入格式:
程序输入信息分三种,三种信息可能会打乱顺序混合输入:
1、题目信息
一行为一道题,可输入多行数据(多道题)。
格式:"#N:"+题目编号+" "+"#Q:"+题目内容+" "#A:"+标准答案
格式约束:
1、题目的输入顺序与题号不相关,不一定按题号顺序从小到大输入。
2、允许题目编号有缺失,例如:所有输入的题号为1、2、5,缺少其中的3号题。此种情况视为正常。
样例:#N:1 #Q:1+1= #A:2
\#N:2 #Q:2+2= #A:4
2、试卷信息
一行为一张试卷,可输入多行数据(多张卷)。
格式:"#T:"+试卷号+" "+题目编号+"-"+题目分值
题目编号应与题目信息中的编号对应。
一行信息中可有多项题目编号与分值。
样例:#T:1 3-5 4-8 5-2
3、答卷信息
答卷信息按行输入,每一行为一张答卷的答案,每组答案包含某个试卷信息中的题目的解题答案,答案的顺序与试卷信息中的题目顺序相对应。
格式:"#S:"+试卷号+" "+"#A:"+答案内容
格式约束:答案数量可以不等于试卷信息中题目的数量,没有答案的题目计0分,多余的答案直接忽略,答案之间以英文空格分隔。
样例:#S:1 #A:5 #A:22
1是试卷号
5是1号试卷的顺序第1题的题目答案
22是1号试卷的顺序第2题的题目答案
答题信息以一行"end"标记结束,"end"之后的信息忽略。
输出格式:
1、试卷总分警示
该部分仅当一张试卷的总分分值不等于100分时作提示之用,试卷依然属于正常试卷,可用于后面的答题。如果总分等于100分,该部分忽略,不输出。
格式:"alert: full score of test paper"+试卷号+" is not 100 points"
样例:alert: full score of test paper2 is not 100 points
2、答卷信息
一行为一道题的答题信息,根据试卷的题目的数量输出多行数据。
格式:题目内容+""+答案++""+判题结果(true/false)
约束:如果输入的答案信息少于试卷的题目数量,答案的题目要输"answer is null"
样例:3+2=5true
**4+6=~22~false.**
answer is null
3、判分信息
判分信息为一行数据,是一条答题记录所对应试卷的每道小题的计分以及总分,计分输出的先后顺序与题目题号相对应。
格式:题目得分+" "+....+题目得分+"~"+总分
格式约束:
1、没有输入答案的题目计0分
2、判题信息的顺序与输入答题信息中的顺序相同
样例:5 8 0~13
根据输入的答卷的数量以上2、3项答卷信息与判分信息将重复输出。
4、提示错误的试卷号
如果答案信息中试卷的编号找不到,则输出”the test paper number does not exist”。
类图:
源码如下:
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class Question {
private int number;
private String content;
private String answer;
public Question(int number, String content, String answer) {
this.number = number;
this.content = content;
this.answer = answer;
}
public int getNumber() {
return number;
}
public String getContent() {
return content;
}
public String getAnswer() {
return answer;
}
}
class Question_Paper {
private int paperNumber;
private Map<Integer, Integer> questionScores;
public Question_Paper(int paperNumber) {
this.paperNumber = paperNumber;
this.questionScores = new HashMap<>();
}
public int getPaperNumber() {
return paperNumber;
}
public void addQuestionScore(int questionNumber, int score) {
questionScores.put(questionNumber, score);
}
public int getTotalScore() {
int totalScore = 0;
for (int score : questionScores.values()) {
totalScore += score;
}
return totalScore;
}
}
class Paper {
private int paperNumber;
private List<String> answers;
public Paper(int paperNumber) {
this.paperNumber = paperNumber;
this.answers = new ArrayList<>();
}
public void addAnswer(String answer) {
answers.add(answer);
}
public int getPaperNumber() {
return paperNumber;
}
public List<String> getAnswers() {
return answers;
}
}
class Answer {
private int questionNumber;
private String answer;
public Answer(int questionNumber, String answer) {
this.questionNumber = questionNumber;
this.answer = answer;
}
public int getQuestionNumber() {
return questionNumber;
}
public String getAnswer() {
return answer;
}
}
class AnswerSheet {
private List<Paper> papers;
public AnswerSheet() {
this.papers = new ArrayList<>();
}
public void addPaper(Paper paper) {
papers.add(paper);
}
public List<Paper> getPapers() {
return papers;
}
}
class InputMatching {
String questionNumMatching = "#N: *[1-9][\\d]?";
String questionMatching = "#Q:[\\D\\d\\S]+";
String standardAnswerMatching = "#A:[\\D\\d\\S]+";
String questionInput = questionNumMatching + " " + questionMatching + " " + standardAnswerMatching;
String answerInput = "#S:[1-9][\\d]?[\\d]{8}(#A:[1-9][\\d]?-[\\D\\d\\S]+)";
String paperInput = "#T: *[1-9][\\d]?([1-9][\\d]?-[1-9][\\d]?)+";
public InputMatching() {
}
}
class ParseInput {
private InputMatching inputMatching;
public ParseInput(InputMatching inputMatching) {
this.inputMatching = inputMatching;
}
public List<Question> parseQuestions(List<String> inputs) {
List<Question> questions = new ArrayList<>();
Pattern pattern = Pattern.compile(inputMatching.questionInput);
for (String input : inputs) {
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
int number = Integer.parseInt(matcher.group(1));
String content = matcher.group(2);
String answer = matcher.group(3);
questions.add(new Question(number, content, answer));
}
}
return questions;
}
public List<Question_Paper> parseQuestionPapers(List<String> inputs) {
List<Question_Paper> questionPapers = new ArrayList<>();
Pattern pattern = Pattern.compile(inputMatching.paperInput);
for (String input : inputs) {
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
int paperNumber = Integer.parseInt(matcher.group(1));
Question_Paper questionPaper = new Question_Paper(paperNumber);
String[] pairs = matcher.group(2).split(" ");
for (String pair : pairs) {
String[] parts = pair.split("-");
int questionNumber = Integer.parseInt(parts[0]);
int score = Integer.parseInt(parts[1]);
questionPaper.addQuestionScore(questionNumber, score);
}
questionPapers.add(questionPaper);
}
}
return questionPapers;
}
public AnswerSheet parseAnswerSheet(List<String> inputs) {
AnswerSheet answerSheet = new AnswerSheet();
Pattern pattern = Pattern.compile(inputMatching.answerInput);
Paper currentPaper = null;
for (String input : inputs) {
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
int paperNumber = Integer.parseInt(matcher.group(1));
if (currentPaper == null || currentPaper.getPaperNumber() != paperNumber) {
currentPaper = new Paper(paperNumber);
answerSheet.addPaper(currentPaper);
}
String answer = matcher.group(2);
currentPaper.addAnswer(answer);
}
}
return answerSheet;
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
List<String> inputs = new ArrayList<>();
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
if (line.equals("end")) {
break;
}
inputs.add(line);
}
InputMatching inputMatching = new InputMatching();
ParseInput parseInput = new ParseInput(inputMatching);
List<Question> questions = parseInput.parseQuestions(inputs);
List<Question_Paper> questionPapers = parseInput.parseQuestionPapers(inputs);
AnswerSheet answerSheet = parseInput.parseAnswerSheet(inputs);
Map<Integer, Question> questionMap = new HashMap<>();
for (Question question : questions) {
questionMap.put(question.getNumber(), question);
}
for (Question_Paper questionPaper : questionPapers) {
int totalScore = questionPaper.getTotalScore();
if (totalScore != 100) {
System.out.println("alert: full score of test paper" + questionPaper.getPaperNumber() + " is not 100 points");
}
}
// 遍历答题卡中的每一张试卷
for (Paper paper : answerSheet.getPapers()) {
int totalScore = 0; // 用于存储该试卷的总分
StringBuilder scoreInfo = new StringBuilder(); // 用于存储分数信息的字符串构建器
// 遍历该试卷中的每一个答案
for (String answer : paper.getAnswers()) {
// 检查答案是否符合要求
// 在这里处理有效答案的逻辑,例如根据答案计算分数等
// 比如,根据答案进行评分,并将得分加到总分上
// int answerScore = calculateScore(answer);
// totalScore += answerScore;
// 构建分数信息,例如将每个答案的得分添加到分数信息中
// scoreInfo.append("Answer: ").append(answer).append(", Score: ").append(answerScore).append("\n");
}
// 输出该试卷的总分和分数信息
System.out.println("Total score for paper " + paper.getPaperNumber() + ": " + totalScore);
System.out.println("Score information:\n" + scoreInfo.toString());
}
}
// public static int calculateScore(String answer) {
//
//
// }
}
设计思路:
试卷题目类是新增的,用于保存试卷中的题目信息。由于试卷中的题目序号与题目本身的题号不一致。且题目在不同试卷中的分值可能不一样,因此,设计试卷题目类。
Question_Paper这个类通过映射(Map
)来存储问题和分数的关系,是一种有效的数据结构选择。每个问题通过其编号在映射中唯一标识,对应的分数则作为值存储。
Paper这个类的设计和Question_Paper类类似,也是通过映射来存储问题和答案的关系。不同的是Paper类存储的是学生或考生给出的答案,Question_Paper类存储的是试卷中问题的分数。
第三次作业 答题判题程序-3
设计实现答题程序,模拟一个小型的测试,以下粗体字显示的是在答题判题程序-2基础上增补或者修改的内容,要求输入题目信息、试卷信息、答题信息、学生信息、删除题目信息,根据输入题目信息中的标准答案判断答题的结果。
输入格式:
程序输入信息分五种,信息可能会打乱顺序混合输入。
1、题目信息
题目信息为独行输入,一行为一道题,多道题可分多行输入。
格式:"#N:"+题目编号+" "+"#Q:"+题目内容+" "#A:"+标准答案
格式约束:
1、题目的输入顺序与题号不相关,不一定按题号顺序从小到大输入。
2、允许题目编号有缺失,例如:所有输入的题号为1、2、5,缺少其中的3号题。此种情况视为正常。
样例:#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
2、试卷信息
试卷信息为独行输入,一行为一张试卷,多张卷可分多行输入数据。
格式:"#T:"+试卷号+" "+题目编号+"-"+题目分值+" "+题目编号+"-"+题目分值+...
格式约束:
题目编号应与题目信息中的编号对应。
一行信息中可有多项题目编号与分值。
样例:#T:1 3-5 4-8 5-2
3、学生信息
学生信息只输入一行,一行中包括所有学生的信息,每个学生的信息包括学号和姓名,格式如下。
格式:"#X:"+学号+" "+姓名+"-"+学号+" "+姓名....+"-"+学号+" "+姓名
格式约束:
答案数量可以不等于试卷信息中题目的数量,没有答案的题目计0分,多余的答案直接忽略,答案之间以英文空格分隔。
样例:
#S:1 #A:5 #A:22
1是试卷号
5是1号试卷的顺序第1题的题目答案
4、答卷信息
答卷信息按行输入,每一行为一张答卷的答案,每组答案包含某个试卷信息中的题目的解题答案,答案的顺序号与试 卷信息中的题目顺序相对应。答卷中:
格式:"#S:"+试卷号+" "+学号+" "+"#A:"+试卷题目的顺序号+"-"+答案内容+...
格式约束:
答案数量可以不等于试卷信息中题目的数量,没有答案的题目计0分,多余的答案直接忽略,答案之间以英文空格分隔。
答案内容可以为空,即””。
答案内容中如果首尾有多余的空格,应去除后再进行判断。
样例:
#T:1 1-5 3-2 2-5 6-9 4-10 7-3
#S:1 20201103 #A:2-5 #A:6-4
1是试卷号
20201103是学号
2-5中的2是试卷中顺序号,5是试卷第2题的答案,即T中3-2的答案
6-4中的6是试卷中顺序号,4是试卷第6题的答案,即T中7-3的答案
注意:不要混淆顺序号与题号
5、删除题目信息
删除题目信息为独行输入,每一行为一条删除信息,多条删除信息可分多行输入。该信息用于删除一道题目信息,题目被删除之后,引用该题目的试卷依然有效,但被删除的题目将以0分计,同时在输出答案时,题目内容与答案改为一条失效提示,例如:”the question 2 invalid~0”
格式:"#D:N-"+题目号
格式约束:
题目号与第一项”题目信息”中的题号相对应,不是试卷中的题目顺序号。
本题暂不考虑删除的题号不存在的情况。
样例:
#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
#T:1 1-5 2-8
#X:20201103 Tom-20201104 Jack
#S:1 20201103 #A:1-5 #A:2-4
#D:N-2
end
输出
alert: full score of test paper1 is not 100 points
1+1=~5~false
the question 2 invalid~0
20201103 Tom: 0 0~0
答题信息以一行"end"标记结束,"end"之后的信息忽略。
输出格式:
1、试卷总分警示
该部分仅当一张试卷的总分分值不等于100分时作提示之用,试卷依然属于正常试卷,可用于后面的答题。如果总分等于100 分,该部分忽略,不输出。
格式:"alert: full score of test paper"+试卷号+" is not 100 points"
样例:alert: full score of test paper2 is not 100 points
2、答卷信息
一行为一道题的答题信息,根据试卷的题目的数量输出多行数据。
格式:题目内容+""+答案++""+判题结果(true/false)
约束:如果输入的答案信息少于试卷的题目数量,每一个缺失答案的题目都要输出"answer is null" 。
样例:
3+2=~5~true
4+6=~22~false.
answer is null
3、判分信息
判分信息为一行数据,是一条答题记录所对应试卷的每道小题的计分以及总分,计分输出的先后顺序与题目题号相对应。
格式:学号+" "+姓名+": "+题目得分+" "+....+题目得分+"~"+总分
格式约束:
1、没有输入答案的题目、被删除的题目、答案错误的题目计0分
2、判题信息的顺序与输入答题信息中的顺序相同
样例:20201103 Tom: 0 0~0
根据输入的答卷的数量以上2、3项答卷信息与判分信息将重复输出。
4、被删除的题目提示信息
当某题目被试卷引用,同时被删除时,答案中输出提示信息。样例见第5种输入信息“删除题目信息”。
5、题目引用错误提示信息
试卷错误地引用了一道不存在题号的试题,在输出学生答案时,提示”non-existent question~”加答案。例如:
输入:
#N:1 #Q:1+1= #A:2
#T:1 3-8
#X:20201103 Tom-20201104 Jack-20201105 Www
#S:1 20201103 #A:1-4
end
输出:
alert: full score of test paper1 is not 100 points
non-existent question~0
20201103 Tom: 0~0
如果答案输出时,一道题目同时出现答案不存在、引用错误题号、题目被删除,只提示一种信息,答案不存在的优先级最高,例如:
输入:
#N:1 #Q:1+1= #A:2
#T:1 3-8
#X:20201103 Tom-20201104 Jack-20201105 Www
#S:1 20201103
end
输出:
alert: full score of test paper1 is not 100 points
answer is null
20201103 Tom: 0~0
6、格式错误提示信息
输入信息只要不符合格式要求,均输出”wrong format:”+信息内容。
例如:wrong format:2 #Q:2+2= #4
7、试卷号引用错误提示输出
如果答卷信息中试卷的编号找不到,则输出”the test paper number does not exist”,答卷中的答案不用输出,参见样例8。
8、学号引用错误提示信息
如果答卷中的学号信息不在学生列表中,答案照常输出,判分时提示错误。参见样例9。
类图:
源码:
因为第三次的题目对我来讲有些困难,PTA上没有得多少分,所以源码就不贴出来了
踩坑心得
- 一开始在写第一题时,我心情比较焦虑,越是焦虑就越是写不出来,反而焦虑之感又增多,对做出来这道题目毫无帮助。用的方法总是报错说数组越界,但是到最后我也没找出来原因。这次在重新做的时候冷静了许多,思路也更加的清晰了。所以面对难题心态一定不能崩掉噢~
- 第一次的作业在第一时间看到的时候很是惊讶,理解能力较差的我连题目都读不懂,不知道想让我干什么,写的东西也是一团乱麻,最后截止的时候也没得到多少分。但是当我现在来总结时,将这道题目重新做了一遍,比较容易就写出来了并且得到了满分(我可太开心了嘻嘻)。但是还有需要修改的地方,可以让程序更加健壮。
- 从使用数组、到列表、Map映射的方法,越来越简便,所以当题目越来越复杂时,我们不要拘泥于同一种方法,尝试其他的方法或许会有新的收获。
改进建议
1.没有把解析字符串的方法单独写为一个类,没有严格遵守程序的单一职责原则。
2.有多个题目没有做出来,课下需要按照老师发出来的考设计思路修改我现有的代码,争取将这三道题目搞懂,为接下来的PTA做准备
3.题目中有些问题处理的并不周全,例如多试卷多答卷的情况,乱序输入的情况以及输入的格式错误的情况。思考问题可以更全面一些
总结
经过了三周的PTA训练,我认为我在对题目的理解,对java基本语法的运用方面有所进步。学习了正则表达式、数组、列表和Map的基本使用方法。但是PTA上的这三次题目,我的问题还有很多,测试点也没有完全通过,这说明我的类设计和整体的结构是有问题的。在第三次提交的过程中,我发现自己陷入了复杂程序细节调试的陷阱中而忽略了宏观的类设计。在今后的作业和学习中,我一定会端正自己的态度,努力提升自己的能力。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步