实验3

一.

image

 

#pragma once
#include <iostream>
#include <string>
class Button {
public:
    Button(const std::string& label_);
    const std::string& get_label() const;
    void click();
private:
    std::string label;
};
Button::Button(const std::string& label_) : label{ label_ } {
}
inline const std::string& Button::get_label() const {
    return label;
}
inline void Button::click() {
    std::cout << "Button '" << label << "' clicked\n";
}
#pragma once
#include <iostream>
#include <vector>
#include <algorithm>
#include "button.hpp"
// 窗口类
class Window {
public:
    Window(const std::string& title_);
    void display() const;
    void close();
    void add_button(const std::string& label);
    void click_button(const std::string& label);
private:
    bool has_button(const std::string& label) const;
private:
    std::string title;
    std::vector<Button> buttons;
};
Window::Window(const std::string& title_) : title{ title_ } {
    buttons.push_back(Button("close"));
}
inline void Window::display() const {
    std::string s(40, '*');
    std::cout << s << std::endl;
    std::cout << "window : " << title << std::endl;
    int cnt = 0;
    for (const auto& button : buttons)
        std::cout << ++cnt << ". " << button.get_label() << std::endl;
    std::cout << s << std::endl;
}
inline void Window::close() {
    std::cout << "close window '" << title << "'" << std::endl;
    click_button("close");
}
inline bool Window::has_button(const std::string& label) const {
    for (const auto& button : buttons)
        if (button.get_label() == label)
            return true;

    return false;
}
inline void Window::add_button(const std::string& label) {
    if (has_button(label))
        std::cout << "button " << label << " already exists!\n";
    else
        buttons.push_back(Button(label));
}
inline void Window::click_button(const std::string& label) {
    for (auto& button : buttons)
        if (button.get_label() == label) {
            button.click();
            return;
        }

    std::cout << "no button: " << label << std::endl;
}
#include "window.hpp"
#include <iostream>
void test() {
    Window w("Demo");
    w.add_button("add");
    w.add_button("remove");
    w.add_button("modify");
    w.add_button("add");
    w.display();
    w.close();
}
int main() {
    std::cout << "用组合类模拟简单GUI:\n";
    test();
}

1.是

2.1优点:has_button可以直接被外部调用,判断是否有相应label并输出结果,增加新的功能

风险: 破坏封装;has_button与add_button相关,不易于维护

2.2public:用户真正需要调用,

private:仅为内部实现,调用会破坏对象状态

3 性能:接口1使用引用,效率高;

安全:接口1使用时和原对象绑定,容易出现问题

4可以;push_back先构造再移动到vector,而emplace_back直接构造,效率高。

image

 

#include <iostream>
#include <vector>
void test1();
void test2();
void output1(const std::vector<int>& v);
void output2(const std::vector<int>& v);
void output3(const std::vector<std::vector<int>>& v);
int main() {
    std::cout << "深复制验证1: 标准库vector<int>\n";
    test1();
    std::cout << "\n深复制验证2: 标准库vector<int>嵌套使用\n";
    test2();
}
void test1() {
    std::vector<int> v1(5, 42);
    const std::vector<int> v2(v1);
    std::cout << "**********拷贝构造后**********\n";
    std::cout << "v1: "; output1(v1);
    std::cout << "v2: "; output1(v2);

    v1.at(0) = -1;
    std::cout << "**********修改v1[0]后**********\n";
    std::cout << "v1: "; output1(v1);
    std::cout << "v2: "; output1(v2);
}
void test2() {
    std::vector<std::vector<int>> v1{ {1, 2, 3}, {4, 5, 6, 7} };
    const std::vector<std::vector<int>> v2(v1);
    std::cout << "**********拷贝构造后**********\n";
    std::cout << "v1: "; output3(v1);
    std::cout << "v2: "; output3(v2);
    v1.at(0).push_back(-1);
    std::cout << "**********修改v1[0]后**********\n";
    std::cout << "v1: \n"; 
    output3(v1);
    std::cout << "v2: \n";
    output3(v2);
}
// 使用xx.at()+循环输出vector<int>数据项
void output1(const std::vector<int>& v) {
    if (v.size() == 0) {
        std::cout << '\n';
        return;
    }

    std::cout << v.at(0);
    for (auto i = 1; i < v.size(); ++i)
        std::cout << ", " << v.at(i);
    std::cout << '\n';
}
// 使用迭代器+循环输出vector<int>数据项
void output2(const std::vector<int>& v) {
    if (v.size() == 0) {
        std::cout << '\n';
        return;
    }

    auto it = v.begin();
    std::cout << *it;
    for (it = v.begin() + 1; it != v.end(); ++it)
        std::cout << ", " << *it;
    std::cout << '\n';
}
// 使用auto for分行输出vector<vector<int>>数据项
void output3(const std::vector<std::vector<int>>& v) {
    if (v.size() == 0) {
        std::cout << '\n';
        return;
    }
    for (auto& i : v)
        output2(i);
}

1.填充式构造,5,5

2.   2;2;3

3.能;v1.at(0)会检查索引合法性,更安全,但是效率更低。

4.1可以;v1.at(0).push_back(-1);将-1添加至v1第 0 个子末尾,之后输出-1;

4.2优势:使用引用,提高效率;

限制:无法修改原对象.

5.1 深复制;

5.2 int&;const int&

是,可以让 const 修饰的 vector 也能安全读取元素

image

 

#pragma once
#include <iostream>
// 动态int数组对象类
class vectorInt {
public:
    vectorInt();
    vectorInt(int n_);
    vectorInt(int n_, int value);
    vectorInt(const vectorInt& vi);
    ~vectorInt();

    int size() const;
    int& at(int index);
    const int& at(int index) const;
    vectorInt& assign(const vectorInt& vi);
    int* begin();
    int* end();
    const int* begin() const;
    const int* end() const;
private:
    int n;// 当前数据项个数
    int* ptr; // 数据区
};
vectorInt::vectorInt() :n{ 0 }, ptr{ nullptr } {
}
vectorInt::vectorInt(int n_) : n{ n_ }, ptr{ new int[n] } {
}
vectorInt::vectorInt(int n_, int value) : n{ n_ }, ptr{ new int[n_] } {
    for (auto i = 0; i < n; ++i)
        ptr[i] = value;
}
vectorInt::vectorInt(const vectorInt& vi) : n{ vi.n }, ptr{ new int[n] } {
    for (auto i = 0; i < n; ++i)
        ptr[i] = vi.ptr[i];
}
vectorInt::~vectorInt() {
    delete[] ptr;
}
int vectorInt::size() const {
    return n;
}
const int& vectorInt::at(int index) const {
    if (index < 0 || index >= n) {
        std::cerr << "IndexError: index out of range\n";
        std::exit(1);
    }
    return ptr[index];
}
int& vectorInt::at(int index) {
    if (index < 0 || index >= n) {
        std::cerr << "IndexError: index out of range\n";
        std::exit(1);
    }
    return ptr[index];
}
vectorInt& vectorInt::assign(const vectorInt& vi) {
    if (this == &vi)
        return *this;
    int* ptr_tmp;
    ptr_tmp = new int[vi.n];
    for (int i = 0; i < vi.n; ++i)
        ptr_tmp[i] = vi.ptr[i];

    delete[] ptr;
    n = vi.n;
    ptr = ptr_tmp;
    return *this;
}
int* vectorInt::begin() {
    return ptr;
}
int* vectorInt::end() {
    return ptr + n;
}
const int* vectorInt::begin() const {
    return ptr;
}
const int* vectorInt::end() const {
    return ptr + n;
}
#include "vectorInt.hpp"
#include <iostream>
void test1();
void test2();
void output1(const vectorInt& vi);
void output2(const vectorInt& vi);
int main() {
    std::cout << "测试1: \n";
    test1();
    std::cout << "\n测试2: \n";
    test2();
}
void test1() {
    int n;
    std::cout << "Enter n: ";
    std::cin >> n;
    vectorInt x1(n);
    for (auto i = 0; i < n; ++i)
        x1.at(i) = (i + 1) * 10;
    std::cout << "x1: "; 
    output1(x1);
    vectorInt x2(n, 42);
    vectorInt x3(x2);
    x2.at(0) = -1;
    std::cout << "x2: "; 
    output1(x2);
    std::cout << "x3: "; 
    output1(x3);
}
void test2() {
    const vectorInt x(5, 42);
    vectorInt y;
    y.assign(x);
    std::cout << "x: "; 
    output2(x);
    std::cout << "y: "; 
    output2(y);
}
// 使用xx.at()+循环输出vectorInt对象数据项
void output1(const vectorInt& vi) {
    if (vi.size() == 0) {
        std::cout << '\n';
        return;
    }

    std::cout << vi.at(0);
    for (auto i = 1; i < vi.size(); ++i)
        std::cout << ", " << vi.at(i);
    std::cout << '\n';
}
// 使用迭代器+循环输出vectorInt对象数据项
void output2(const vectorInt& vi) {
    if (vi.size() == 0) {
        std::cout << '\n';
        return;
    }

    auto it = vi.begin();
    std::cout << *it;
    for (it = vi.begin() + 1; it != vi.end(); ++it)
        std::cout << ", " << *it;
    std::cout << '\n';
}

1.原代码

if (this == &vi)
return *this;

判断调用对象和传入参数是否相同,防止错误;

释放和分配内存顺序不同,防止内存分配失败

2.1作用:将当前对象的指针 this 转换为 const vectorInt* 类型的指针

前:vectorInt*  后:const vectorInt*

目的:让非 const 版本的 at() 函数能够调用 const 版本的 at() 函数

2.2移除 const 限定符,将 const int& 类型转换为 int& 类型。

前:const int&   后:int&

目的:非 const 版本的 at() 函数需要返回可修改的元素引用(int&

3.  it1:无const it2:有const

有const适用于只读

4.可以。 (1)将从 ptr 开始的连续 n 个 int 类型内存单元,全部赋值为 value

(2)从 vi.ptr 指向的内存开始,复制连续 vi.n 个 int 类型元素,粘贴到 ptr 指向的内存区域。

(3)从 vi.ptr 复制连续 vi.n 个 int 元素到 ptr_tmp 指向的新内存中

image

 

#include <iostream>
#include <cstdlib>
#include <algorithm>
#include "matrix.hpp"

Matrix::Matrix(int rows_, int cols_, double value )
{    //
    if (n_rows <= 0 || n_cols <= 0) {
        std::cerr << "Error: 行数/列数不能为非正数\n";
        exit(1);
    }
    n_rows = rows_;
    n_cols = cols_;
    ptr = new double[n_rows * n_cols];
    std::fill(ptr, ptr + n_rows * n_cols, value);
}

Matrix::Matrix(int rows_, double value )
{    
    n_rows = rows_;
    n_cols = rows_;
    ptr = new double[n_rows * n_cols];
    std::fill(ptr, ptr + n_rows * n_cols, value);
}
Matrix::Matrix(const Matrix& x)
{
    n_rows = x.n_rows;
    n_cols = x.n_cols;
    ptr = new double[n_rows * n_cols];
    std::copy(x.ptr,x.ptr + n_rows * n_cols,ptr);
}
Matrix::~Matrix()
{
    delete[] ptr;
}
void Matrix::set(const double* pvalue, int size)
{
    if (size == n_rows * n_cols)
    {
        std::copy(pvalue, pvalue + size, ptr);
    }
    else
    {
        std::cout << "wrong";
        exit(1);
    }
}
void Matrix::clear() 
{
    std::fill(ptr, ptr + n_rows * n_cols,0);
}
const double& Matrix::at(int i, int j) const
{
    if (i<0||j<0||i>=n_rows||j>=n_cols)
    {std::cout << "wrong";
        exit(1);
        
    }
    else
    {
        return ptr[i * n_cols + j];
    }
}
double& Matrix::at(int i, int j)
{
    if (i < 0 || j < 0 || i >= n_rows || j >= n_cols)
    {
        std::cout << "wrong";
        exit(1);

    }
    else
    {
        return ptr[i * n_cols + j];
    }
}
int Matrix::rows() const
{
    return n_rows;
}
int Matrix::cols() const
{
    return n_cols;
}
void Matrix::print() const
{
    for (int i = 0;i < n_rows;i++)
    {
        //std::cout << at(i, 0) << ",";
        
    
    //std::cout << std::endl;
for (int j = 0;j < n_cols;j++)
    std::cout << at(i, j) << ",";
std::cout << std::endl;}
}

image

 



int
ContactBook::index(const std::string& name) const { for (size_t i=0;i< contacts.size();++i ) { if (contacts[i].get_name()==name) return static_cast<int>(i); } return -1; } // 返回联系人在contacts内索引; 如不存在,返回-1 // 待补足2:void ContactBook::sort();实现 void ContactBook::sort() { size_t n = size(); for (size_t i = 0;i <n;++i) { for (size_t j = 0;j < n - i - i;++j) { if (contacts[j].get_name() > contacts[j + 1].get_name()) { std::swap(contacts[j], contacts[j + 1]); } } } }

 

posted @ 2025-12-05 01:00  HdYi  阅读(0)  评论(0)    收藏  举报