结对项目-四则运算

news/2024/9/25 18:14:32

github链接

这个作业属于哪个课程 班级的链接
这个作业要求在哪里 作业要求的链接
这个作业的目标 实现四则运算自动生成程序,结对协作开发
姓名 学号
柳浩 3122004444
洪吉潮

PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 20 25
Estimate 估计这个任务需要多少时间 60 65
Development 开发 200 200
Analysis 需求分析 (包括学习新技术) 20 30
Design Spec 生成设计文档 50 45
Design Review 设计复审 30 30
Coding Standard 代码规范 (为目前的开发制定合适的规范) 20 20
Design 具体设计 30 35
Coding 具体编码 150 160
Code Review 代码复审 30 35
Test 测试(自我测试,修改代码,提交修改) 30 35
Reporting 报告 50 60
Test Repor 测试报告 20 25
Size Measurement 计算工作量 10 10
Postmortem & Process Improvement Plan 事后总结,并提出过程改进计划 30 30
合计 750 805
  • 设计实现过程
    代码功能通过三个类去实现:Fraction,Question,Generator

    三个类的大致结构如下图:
  • Fraction类:
    Fraction类主要作用是对分数进行管理,提供分数的自动调整和计算接口给上层类调用,如:约分,格式转化(字符流转化为数字存储以及已有分数转化为字符串便于写入文件等),以及分数 之间的运算的实现等,
    Fraction类大致结构如下:
class Fraction //分数管理类
{
private:int numerator; // 分子int denominator; // 分母int gcd(int a, int b);// 计算最大公约数,用于约分void reduce();// 约分分数
public:std::string get_str_fra();//得到分数的字符串形式float get_frac()const;//得到分数的浮点数形式Fraction(int n = 0, int d = 1);//通过传入分子和分母构造FractionFraction(std::string& s);//通过传入string字符串生成分数Fraction operator+(const Fraction& other) const;//分数加法Fraction operator-(const Fraction& other) const;//分数减法Fraction operator*(const Fraction& other) const;//分数乘法Fraction operator/(const Fraction& other) const;//分数除法bool operator>(const Fraction& other) const;//重载大于比较bool operator<(const Fraction& other) const;//重载小于比较bool operator!=(const Fraction& other) const;//重载不等比较bool operator==(const Fraction& other) const;//重载等于比较friend std::ostream& operator<<(std::ostream& os, const Fraction& f);//重载分数的流提取运算符friend std::istream& operator>>(std::istream& is, Fraction& f);//重载分数的流插入运算符};
  • Question类:
    Question类主要作用是对单个题目进行管理,提供比较两个题目是否相同的接口便于上层类进行查重,对读取的字符流转化为相应数据结构进行计算以及将题目转化为字符流便于写入文件。还有单个题目的随机实现接口。
    Question类大致结构如下:
class Question //管理一个计算题的类
{
private:int range;//数值的范围int num;//计算数字的个数(两个或三个)bool par_flag;//有无括号int par_pos;//括号的位置std::vector<Fraction> data;//存储每个数据std::vector<int> oper;//存储运算符std::vector<int> step;//存储运算步骤,用于查重Fraction result;//存储结果以Fraction类形式std::vector<std::string> que;//存储题目,以string字符串数组的方式std::string res;//存储结果,以string的形式
public:friend std::ostream& operator<<(std::ostream& os, const Question& q);//重载流插入运算符,实现向文件中打印题目Question(int _range, int _num);//以数据范围和个数生成一个题目Question(std::vector<std::string>& vs);//从文件中读到的一个题目拆分成的字符串数组构建一个题目void get_DataOper(std::vector<std::string>& vs);//第二种构造下用于得到数据和运算符int get_oper(std::string& v);//用于将运算符转化为数字记录void get_str();//根据题目生成字符串数组quebool operator==(const Question& other) const;//重载“==”符号用于比较两个题目是否重复void ran_oper();//生成随机运算符,用于第一种构造void ran_data();//生成随机数据,用于第二种构造int GetPri(int ope);//得到运算符的优先级void get_result();//得到本题结果void calculate();//生成运算先后步骤,被get_result()调用Fraction _calculate(Fraction& tmp1, Fraction& tmp2, int st);//计算两个分数的运算结果,被calculate调用Fraction get_fra_res();std::string get_str_res();std::vector<std::string> infixToPostfix(const std::string& infix)const;bool areEquivalent(const std::string& expr1, const std::string& expr2)const;int precedence(char op)const;
};
  • Generator类
    Generator类的主要作用是决定随机生成的题目的数量以及对题目进行判重,对从文件中读取到的内容预处理并交给下层类进行处理,最后得到准确率。将生成的题目和得到的准确度写入文件
    Generator类大致结构如下:
class Generator//计算题生成器
{
private:int number;//题目数量int range;//题目数据的范围std::vector<Question> questions;//存档所有题目std::unordered_multimap<Fraction, Question, MyHash> record;//记录已生成题目,用于查重std::string qFile;//目标题目写入/读取文件std::string aFile;//目标答案写入/读取文件
public:Generator(int _num, int _range, const char* _qfile = "Exercises.txt", const char* _afile = "Answers.txt");//构造函数用于生成题目Generator(const char* _qfile, const char* _afile, const char* _rfile = "Grade.txt");//构造函数二用于检查错误题目数量~Generator();//析构函数void Create();//创建题目bool judge(Question& q);//判断题目是否已有重复void Write();//写入目标文件void Accuracy(const char* rfile);//处理文件读取的内容生成题目计算结果,调用_accuracy()得到精确度void _accuracy(std::vector<Question>& que, std::vector<Fraction>& ans, const char* rfile);//计算得到精确度
};

main函数:

点击查看代码
#include"arith.h"int main(int argc, char* argv[])
{try {if (argc != 5){std::cout << "输入参数不完整" << std::endl;return 1;}std::vector<std::string> args;for (int i = 0; i < argc; ++i){args.push_back(std::string(argv[i]));}if (args[1] == "-n" || args[1] == "-r"){int num, range;if (args[1] == "-n" && args[3] == "-r"){num = std::stoi(args[2]);range = std::stoi(args[4]);}else if (args[3] == "-n" && args[1] == "-r"){num = std::stoi(args[4]);range = std::stoi(args[2]);}else{std::cout << "输入参数不完整" << std::endl;return 1;}Generator gen(num, range);std::cout << "生成成功" << std::endl;}else if (args[1] == "-e" || args[1] == "-a"){int epos, apos;if (args[1] == "-e" && args[3] == "-a"){epos = 2;apos = 4;}else if (args[3] == "-e" && args[1] == "-a"){apos = 2;epos = 4;}else{std::cout << "输入参数不完整" << std::endl;return 1;}Generator gen(args[epos].c_str(), args[apos].c_str());std::cout << "判题成功" << std::endl;}else{std::cout << "输入参数不完整" << std::endl;return 1;}return 0;}catch (const std::exception& e){std::cerr << "Exception caught:" << e.what() << std::endl;}
}
main函数中对命令行参数进行分析,参数不符合条件时打印错误信息,参数符合条件时,对于两种功能(生成题目和判断答案)都进行了实现。

代码流程图如下:

  • 性能分析
    使用Visual studio内置的性能分析工具得到结果如下:


    改进思路:利用生成器,多线程与多进程,异步编程,编译器优化,使用RAII等等方法可以多角度对代码进行优化

  • 测试
    功能测试:
    1.命令行参数不全测试,对于参数缺失的情况进行反馈

    2.生成题目测试



    3.判断题目正确率测试,第一题为设置的错误答案,结果无误



使用Microsoft测试框架进行单元测试测试:

如图,测试均通过。测试代码如下:
对Fraction类进行测试
4.测试Fraction类自动管理分数能力

TEST_METHOD(TestMethod_get_str_fra){Fraction f(25, 4);Assert::AreEqual(std::string("6'1/4"), f.get_str_fra());}

5.测试Fraction类的数值管理正确性

TEST_METHOD(Test_get_frac){int num = 6;int den = 5;Fraction f(num, den);float res = (float)num / (float)den;Assert::AreEqual(res, f.get_frac());}

Question类的测试
6.测试自动生成题目能力

TEST_METHOD(TestMethod_ConstructorQuestion1){Question q(10, 3);Assert::AreEqual(q.range, 10);Assert::AreEqual(q.num, 3);Assert::AreEqual((int)q.data.size(), 3);}

7.测试加减乘除运算的正确性

TEST_METHOD(TestMethod_ADD){std::string s("1. 1/2 + 2/3 =");std::istringstream iss(s);std::vector<std::string> words;std::string word;while (iss >> word){words.push_back(word);}Question q(words);std::string res("1'1/6");Fraction f(7, 6);Assert::IsTrue(res == q.res);Assert::IsTrue(f == q.result);}
TEST_METHOD(TestMethod_SUB){std::string s("1. 2/3 - 1/2 =");std::istringstream iss(s);std::vector<std::string> words;std::string word;while (iss >> word){words.push_back(word);}Question q(words);std::string res("1/6");Fraction f(1, 6);Assert::IsTrue(res == q.res);Assert::IsTrue(f == q.result);}
TEST_METHOD(TestMethod_MUL){std::string s("1. 1/2 × 2/3 =");std::istringstream iss(s);std::vector<std::string> words;std::string word;while (iss >> word){words.push_back(word);}Question q(words);std::string res("1/3");Fraction f(1, 3);Assert::IsTrue(res == q.res);Assert::IsTrue(f == q.result);}
TEST_METHOD(TestMethod_DIV){std::string s("1. 1/2 ÷ 2/3 =");std::istringstream iss(s);std::vector<std::string> words;std::string word;while (iss >> word){words.push_back(word);}Question q(words);std::string res("3/4");Fraction f(3, 4);Assert::IsTrue(res == q.res);Assert::IsTrue(f == q.result);}

项目总结:
本次结对项目提升了合作开发的能力,是一次令人受益匪浅的开发经历

具体各方法的实现如下:

Fraction类内方法:

点击查看代码
// 计算最大公约数,用于约分
int Fraction::gcd(int a, int b) {return b == 0 ? a : gcd(b, a % b);
}// 约分分数
void Fraction::reduce() {int divisor = gcd(numerator, denominator);numerator /= divisor;denominator /= divisor;// 确保分母总是正数if (denominator < 0) {numerator = -numerator;denominator = -denominator;}
}std::string Fraction::get_str_fra()
{std::string fra;if (numerator > denominator){fra += std::to_string(numerator / denominator);fra.push_back('\'');}if (numerator % denominator == 0){if (numerator == denominator){return std::string("1");}fra.erase(fra.size() - 1);return fra;}fra += std::to_string(numerator % denominator);fra.push_back('/');fra += std::to_string(denominator);return fra;
}float Fraction::get_frac()const
{return (float)numerator / (float)denominator;
}// 构造函数
Fraction::Fraction(int n , int d ) : numerator(n), denominator(d) {if (d == 0) {throw std::invalid_argument("Denominator cannot be zero.");}reduce();
}
Fraction::Fraction(std::string& s) : numerator(0), denominator(1)
{int inte = 0;size_t pos1 = s.find('\'');size_t pos2 = s.find('/');if (pos1 == std::string::npos && pos2 == std::string::npos){std::string integer = s.substr(0);inte = std::stoi(integer);numerator += inte * denominator;}else if (pos2 != std::string::npos){int begin = 0;int len = 0;if (pos1 != std::string::npos){begin = pos1 + 1;len = pos2 - pos1;std::string integer = s.substr(0, pos1);inte = std::stoi(integer);}else{len = pos2;}std::string integer = s.substr(begin, len);numerator = std::stoi(integer);integer = s.substr(pos2 + 1);denominator = std::stoi(integer);numerator += inte * denominator;}}// 重载加法运算符
Fraction Fraction::operator+(const Fraction& other) const {if (numerator == 0){return other;}if (other.numerator == 0){return *this;}return Fraction(numerator * other.denominator + other.numerator * denominator,denominator * other.denominator);
}// 重载减法运算符
Fraction Fraction::operator-(const Fraction& other) const {return Fraction(numerator * other.denominator - other.numerator * denominator,denominator * other.denominator);
}// 重载乘法运算符
Fraction Fraction::operator*(const Fraction& other) const {if (numerator == 0 || other.numerator == 0){return Fraction(0);}return Fraction(numerator * other.numerator, denominator * other.denominator);
}// 重载除法运算符
Fraction Fraction::operator/(const Fraction& other) const {return Fraction(numerator * other.denominator, denominator * other.numerator);
}//比较两个分数大小
bool Fraction::operator>(const Fraction& other) const {return numerator * other.denominator > denominator * other.numerator;
}//比较两个分数大小
bool Fraction::operator<(const Fraction& other) const {return !(*this > other);
}//判断相等
bool Fraction::operator==(const Fraction& other) const {if (numerator == 0 && other.numerator == 0)return true;else{return (numerator == other.numerator) && (denominator == other.denominator);}
}
bool Fraction::operator!=(const Fraction& other) const {return !(*this == other);
}// 输出流运算符重载
std::ostream& operator<<(std::ostream& os, const Fraction& f) {os << f.numerator << "/" << f.denominator;return os;
}// 输入流运算符重载
std::istream& operator>>(std::istream& is, Fraction& f) {is >> f.numerator >> f.denominator;f.reduce();return is;
}
Question类内方法:
点击查看代码
std::ostream& operator<<(std::ostream& os, const Question& q) {for (auto it : q.que){os << it << " ";}return os;
}Question::Question(int _range, int _num):range(_range), num(_num), par_flag(false)
{ran_data();//生成数字ran_oper();//生成运算符get_result();//得到结果get_str();//生成字符串
}
Question::Question(std::vector<std::string>& vs)
{if (vs.size() == 5){num = 2;Fraction d1(vs[1]);Fraction d2(vs[3]);data.push_back(d1);data.push_back(d2);oper.push_back(get_oper(vs[2]));}else{num = 3;get_DataOper(vs);}get_result();//得到结果get_str();//生成字符串}void Question::get_DataOper(std::vector<std::string>& vs)
{int dp1, dp2, dp3, oper1, oper2;if (vs[1] == "("){par_flag = true;par_pos = 0;}else if (vs[3] == "("){par_flag = true;par_pos = 1;}else{par_flag = false;par_pos = 2;}if (par_pos == 0){dp1 = 2;dp2 = 4;dp3 = 7;oper1 = 3;oper2 = 6;}else if (par_pos == 1){dp1 = 1;dp2 = 4;dp3 = 6;oper1 = 2;oper2 = 5;}else{dp1 = 1;dp2 = 3;dp3 = 5;oper1 = 2;oper2 = 4;}data.push_back(Fraction(vs[dp1]));data.push_back(Fraction(vs[dp2]));data.push_back(Fraction(vs[dp3]));oper.push_back(get_oper(vs[oper1]));oper.push_back(get_oper(vs[oper2]));
}
int Question::get_oper(std::string& v)
{if (v == "+")return 0;if (v == "-")return 1;if (v == "×")return 2;if (v == "÷")return 3;
}
void Question::get_str()
{if (result == Fraction(0)){res = std::string("0");}elseres = result.get_str_fra();for (auto e : data){if (e == Fraction(0))que.push_back(std::string("0"));elseque.push_back(e.get_str_fra());}auto pos = que.begin() + 1;for (auto it : oper){switch (it){case ADD:que.insert(pos, std::string("+")); break;case SUB:que.insert(pos, std::string("-")); break;case MUL:que.insert(pos, std::string("×")); break;case DIV:que.insert(pos, std::string("÷")); break;default:break;}pos = que.begin() + 3;}if (par_flag){int left_par, right_par;if (par_pos == 0){left_par = 0;right_par = 4;}else{left_par = 2;right_par = 6;}que.insert(left_par + que.begin(), std::string("("));que.insert(right_par + que.begin(), std::string(")"));}que.emplace(que.end(), std::string("="));
}//判断相等
bool Question::operator==(const Question& other) const {std::string q1, q2;for (int i = 1; i < que.size()-1; ++i){q1 += que[i];};for (int i = 1; i < other.que.size() - 1; ++i){q2 += other.que[i];}return areEquivalent(q1, q2);}std::vector<std::string> Question::infixToPostfix(const std::string& infix) const{std::stack<char> operators;std::vector<std::string> postfix;for (char ch : infix) {if (isdigit(ch)) {std::string num(1, ch);postfix.insert(postfix.end(), num);}else if (ch == '(') {operators.push(ch);}else if (ch == ')') {while (!operators.empty() && operators.top() != '(') {postfix.push_back(std::string(1, operators.top()));operators.pop();}operators.pop(); // Remove '(' from the stack}else {while (!operators.empty() && precedence(operators.top()) >= precedence(ch)) {postfix.push_back(std::string(1, operators.top()));operators.pop();}operators.push(ch);}}while (!operators.empty()) {postfix.push_back(std::string(1, operators.top()));operators.pop();}return postfix;
}// 比较两个表达式是否等价
bool Question::areEquivalent(const std::string& expr1, const std::string& expr2) const{auto postfix1 = infixToPostfix(expr1);auto postfix2 = infixToPostfix(expr2);return postfix1 == postfix2;
}// 定义运算符的优先级
int Question::precedence(char op) const{if (op == '+' || op == '-') return 1;if (op == '*' || op == '/') return 2;return 0;
}void Question::ran_oper()
{std::mt19937 rng(std::random_device{}());std::uniform_int_distribution<int> dist(0, range);if (num == 3 && dist(rng) % 2 == 0){par_flag = true;par_pos = dist(rng) % 2;}int _num = num;while (--_num != 0){int choice = dist(rng) % 4;oper.push_back(choice);}
}void Question::ran_data()
{std::mt19937 rng(std::random_device{}());std::uniform_int_distribution<int> dist(0, range);std::uniform_int_distribution<int> dist1(1, range);int _num = num;while (_num-- != 0)//随机出数字{int numerator = dist(rng);int denominator = dist1(rng);Fraction f(numerator, denominator);data.push_back(f);}
}int Question::GetPri(int ope)
{if (ope == ADD || ope == SUB)return 1;elsereturn 2;
}void Question::get_result()
{if (num == 2){step.push_back(0);}else{int prev_step, next_step;if (par_flag){prev_step = par_pos;}else{if (GetPri(oper[0]) < GetPri(oper[1])){prev_step = 1;}else{prev_step = 0;}}next_step = (prev_step + 1) % 2;step.push_back(prev_step);step.push_back(next_step);}calculate();
}void Question::calculate()
{if (num == 2){result = _calculate(data[0], data[1], 0);}else if (num == 3) {std::stack<Fraction> inter;int i = 0;inter.push(data[i++]);inter.push(data[i++]);if (step[0] == 1){inter.push(data[i++]);}Fraction tmp2 = inter.top();inter.pop();Fraction tmp1 = inter.top();inter.pop();tmp1 = _calculate(tmp1, tmp2, 0);inter.push(tmp1);if (i < num){inter.push(data[i++]);}tmp2 = inter.top();inter.pop();tmp1 = inter.top();inter.pop();result = _calculate(tmp1, tmp2, 1);}}
Fraction Question::_calculate(Fraction& tmp1, Fraction& tmp2, int st)
{if (oper[step[st]] == SUB){if (tmp2 > tmp1){oper[step[st]] = ADD;}}if (oper[step[st]] == DIV){if (tmp2 == Fraction(0)){oper[step[st]] = MUL;}}switch (oper[step[st]]){case ADD:return tmp1 + tmp2;case SUB:return tmp1 - tmp2;case MUL:return tmp1 * tmp2;case DIV:return tmp1 / tmp2;default:break;}
}
Fraction Question::get_fra_res()
{return result;
}
std::string Question::get_str_res()
{return res;
}float MyHash::operator()(const Fraction& res) const {
float result = res.get_frac();
return result;
}
Generator类内方法:
点击查看代码
Generator::Generator(int _num, int _range, const char* _qfile, const char* _afile):number(_num), range(_range), qFile(_qfile), aFile(_afile)
{Create();
}
Generator::Generator(const char* _qfile, const char* _afile, const char* _rfile):qFile(_qfile), aFile(_afile)
{Accuracy(_rfile);
}
Generator::~Generator()
{}//生成题目和答案
void Generator::Create()
{int num = number;while (num-- != 0){std::mt19937 rng(std::random_device{}());std::uniform_int_distribution<int> dist(2, 3);int count = dist(rng);Question q(range, count);if (judge(q)){num++;continue;}else{questions.push_back(q);record.insert({ q.get_fra_res(), q});}}Write();
}//判断有无相同的题目
bool Generator::judge(Question& q)
{if (record.count(q.get_fra_res()) != 0){auto range = record.equal_range(q.get_fra_res());for (auto it = range.first; it != range.second; it++){if (it->second == q){return true;}}}return false;}//将题目和答案写入文件
void Generator::Write()
{std::ofstream QueFile;QueFile.open(qFile);for (int i = 0; i < questions.size(); i++){QueFile << std::to_string(i + 1) << ".   " << questions[i] << std::endl;}std::ofstream AnsFile;AnsFile.open(aFile);for (int i = 0; i < questions.size(); i++){AnsFile << std::to_string(i + 1) << ".   " << questions[i].get_str_res() << std::endl;}
}
//根据题目和答案判断正确率
void Generator::Accuracy(const char* rfile)
{std::ifstream QueFile(qFile);std::ifstream ResFile(aFile);std::string line;std::vector<Fraction> answers;while (getline(QueFile, line)){std::istringstream iss(line);std::vector<std::string> words;std::string word;while (iss >> word){words.push_back(word);}Question q(words);questions.push_back(q);}while (getline(ResFile, line)){std::istringstream iss(line);std::vector<std::string>words;std::string word;while (iss >> word){words.push_back(word);}Fraction ans(words[1]);answers.push_back(ans);}return _accuracy(questions, answers, rfile);}
void Generator::_accuracy(std::vector<Question>& que, std::vector<Fraction>& ans,const char* rfile)
{int right = 0;int wrong = 0;std::string rs("(");std::string ws("(");for (int i = 0; i < que.size(); i++){std::stringstream ss;if (que[i].get_fra_res() != ans[i]){wrong++;ss << i + 1;ws += ss.str();ws += ",";}else{right++;ss << i + 1;rs += ss.str();rs += ",";}}if (ws.size() != 1)ws.erase(ws.end() - 1);if (rs.size() != 1)rs.erase(rs.end() - 1);ws.append(")");rs.append(")");std::ofstream OutFile;OutFile.open(rfile);OutFile << "Correct:" << right << " " << rs << std::endl;OutFile << " wrong :" << wrong << " " << ws << std::endl;};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/64668.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

java作业

要求做几道练习题,体会java一些比较细的知识点 1. • 第一行输出false是因为这行代码比较两个枚举变量s和t是否引用同一对象。s被赋值为Size.SMALL,而t被赋值为Size.LARGE。由于它们引用不同的枚举实例,所以输出为false。 • 第二行输出false是因为这行代码首先通过s.getCla…

基于Sentinel自研组件的系统限流、降级、负载保护最佳实践探索

一、Sentinel简介 Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。 Sentinel 具有以下特征: •丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、…

信息学奥赛复赛复习03-CSP-J2019-03-纪念品-背包、01背包、完全背包

PDF文档公众号回复关键字:202409251 2019 CSP-J 题目3 纪念品 [题目描述] 小伟突然获得一种超能力,他知道未来 T天 N 种纪念品每天的价格。某个纪念品的价格是指购买一个该纪念品所需的金币数量,以及卖出一个该纪念品换回的金币数量 每天,小伟可以进行以下两种交易无限次:任…

《DNK210使用指南 -CanMV版 V1.0》第二十六章 摄像头图像捕获实验

第二十六章 摄像头图像捕获实验 1)实验平台:正点原子DNK210开发板 2)章节摘自【正点原子】DNK210使用指南 - CanMV版 V1.0 3)购买链接:https://detail.tmall.com/item.htm?&id=782801398750 4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/k…

实时网络的仿真和配置工具RTaW Pegase v4.6版本更新

01概述随着嵌入式系统日益复杂,高效可靠的设计工具变得愈发重要。RTaW公司的仿真工具RTaW-Pegase最新发布的4.6版本,为用户带来了一系列重要更新和功能增强。本文将详细介绍RTaW-Pegase v4.6版本的主要更新内容,涵盖了DDS、SOME/IP、Ethernet、CAN以及SDV等多个关键领域的改…

CTFSHOW pwn03 WrriteUp

本文来自一个初学CTF的小白,如有任何问题请大佬们指教! 题目来源 CTFShow pwn - pwn03 (ret2libc) https://ctf.show/challenges 思路 1.下载题目放到checksec先查一下2.IDA打开题目Shift + F12查看字符串发现没有system和/bin/sh,但是有libc文件。 3.用gdb的cyclic查询一…

如何正确的在项目中接入微信JS-SDK

微信JS-SDK的功能 如果你点进来,那么我相信你应该知道微信的JS-SDK可以用来做什么了。微信的官方文档描述如下。微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包。通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照、选图、语音、位置等手机系…

kafka的安装与配置

kafka的安装与配置 kafka的安装 在这我才用的是oracle云,系统是Ubuntu,在docker上按照的 安装docker 具体的安装方法请见docker-compose教程 查看docker版本 docker --versionDocker version 27.0.3, build 7d4bcd8创建 Docker Compose 文件 Kafka 依赖 Zookeeper 来管理集群…