C++ Primer Plus 第十二章答案 类和动态内存分配

简介: 只有聪明人才能看见的摘要~( ̄▽ ̄~)~

 复习题

//12.9
//1
a, 语法是正确的,但没有将str指针初始化,应该将指针设置成NULL或使用new来初始化它
b, 没有创建新的字符串,而只是复制了原有字符串的地址,应该使用new[]和strcpy()
c, 复制了字符串但没有分配存储空间,应该使用new char[len + 1]分配内存
//2
首先,当这种类型的对象过期时,对象的成员指针指向的数据仍然保留在内存中,导致占用
空间但是又不可访问,因为指针已经丢失。解决方法是让类的析构函数删除构造函数中new
分配的内存。其次,析构函数释放这种内存后,如果程序将这样的对象初始化为另一个对象,
析构函数会试图释放这些内存两次,这是因为将一个对象初始化为另一个对象的默认初始化
将复制指针值但不复制指向指针的数据,这样两个指针就指向同一个数据。解决方法是定义
一个复制构造函数,使初始化复制指向的数据。第三,将一个对象赋给另一个对象也会导致
两个指针指向相同的数据,解决方法是重载赋值运算符,使它复制数据而不是指针。
//3
C++自动提供下面的成员函数:
如果没有定义,将自动提供
默认构造函数,复制构造函数,赋值运算符,默认析构函数,地址运算符
默认构造函数不完成任何工作,但使得可以声明数组和未初始化的对象。
默认复制构造函数和默认赋值运算符使用成员赋值。
默认析构函数也不完成任何工作。
隐式地址运算符返回调用对象的人地址。(即this指针的值)
//4
#include<iostream>
#include<cstring>
using namespace std;
class nifty {
private:
  char* personality;
  int talents;
public:
  nifty();
  nifty(const char* s);
  nifty(const nifty& n);
  ~nifty() { delete[]personality; };
  nifty& operator=(const nifty& n);
  friend ostream& operator<<(ostream& os, const nifty& n);
};
nifty::nifty() {
  personality = nullptr;
  talents = 0;
}
nifty::nifty(const char* s) {
  personality = new char[strlen(s) + 1];
  strcpy(personality, s);
  talents = 0;
}
nifty::nifty(const nifty& n) {
  char* personality = new char[strlen(n.personality)];
  strcpy(personality, n.personality);
}
nifty& nifty::operator=(const nifty& n) {
  if (this == &n)
    return *this;
  delete[]personality;
  char* personality = new char[strlen(n.personality)];
  strcpy(personality, n.personality);
  return *this;
}
ostream& operator<<(ostream& os, const nifty& n) {
  os << n.personality << endl;
  os << n.talents << endl;
  return os;
}
//5
#1 默认构造函数
#2 构造函数,使用一个默认参数
#3 构造函数
#4 默认构造函数
#5 复制构造函数
#6 构造函数
#7 默认赋值运算符
#8 构造函数,默认赋值运算符
对于#5和#6有的编译器还会调用默认赋值运算符
应该定义一个复制数据(而不是地址)的赋值运算符

image.gif

practice1

使用strcpy总是有很多麻烦,换成strcpy_s可能麻烦更多

参考C++中strcpy()函数和strcpy_s()函数的使用及注意事项_strcpy_s函数_Leonardo Liu的博客-CSDN博客

#pragma once
//cow.h
#ifndef COW_H_
#define COW_H_
class Cow {
  char name[20];
  char* hobby;
  double weight;
public:
  Cow();
  Cow(const char* nm, const char* ho, double wt);
  Cow(const Cow& c);
  ~Cow() { delete[]hobby; }
  Cow& operator=(const Cow& c);
  void ShowCow()const;
  char* f() { return hobby; }//显示地址作为观察
};
#endif
//cow.cpp
#include"cow.h"
#include<iostream>
#include<cstring>
#pragma warning( disable : 4996)
using namespace std;
Cow::Cow() {
  strcpy(name, "");
  hobby = nullptr;
  weight = 0.0;
}
Cow::Cow(const char* nm, const char* ho, double wt) {
  strcpy(name, nm);
  hobby = new char[strlen(ho) + 1];
  strcpy(hobby, ho);
  weight = wt;
}
Cow::Cow(const Cow& c) {
  strcpy(name, c.name);
  hobby = new char[strlen(c.hobby) + 1];
  strcpy(hobby, c.hobby);
  weight = c.weight;
}
Cow& Cow::operator=(const Cow& c) {
  strcpy(name, c.name);
  delete[]hobby;
  hobby = new char[strlen(c.hobby) + 1];
  strcpy(hobby, c.hobby);
  weight = c.weight;
  return *this;
}
void Cow::ShowCow()const {
  cout << "Information of cow named " << name << endl;
  if (hobby == 0)
    cout << "Hobby is NULL" << endl;
  else
    cout << "Hobby: " << hobby << endl;
  cout << "Weight: " << weight << endl;
}
//main.cpp
#include<iostream>
#include"cow.h"
int main() {
  using namespace std;
  Cow cow1;
  cow1.ShowCow();
  cout << "Hobby address: " << (void*)cow1.f() << endl;
  cout << endl;
  char name[] = "cow one";
  Cow cow2(name, "drink", 180.5);
  cow2.ShowCow();
  cout << "Hobby address: " << (void*)cow2.f() << endl;
  cout << endl;
  Cow cow3 = cow2;
  cow3.ShowCow();
  cout << "Hobby address: " << (void*)cow3.f() << endl;
  cout << endl;
  Cow cow4;
  cow4 = cow3;
  cow4.ShowCow();
  cout << "Hobby address: " << (void*)cow4.f() << endl;
  cout << endl;
  return 0;
}

image.gif

practice2

唉,又要抄程序清单

//string2.h
#ifndef STRING2_H_
#define STRING2_H_
#include<iostream>
using namespace std;
class String {
  char* str;
  int len;
  static int num_strings;
  static const int CINLIM = 80;
public:
  String(const char* s);
  String();
  String(const String& s);
  ~String();
  int length()const { return len; }
  String& operator=(const String& s);
  String& operator=(const char* s);
  char& operator[](int i);
  const char& operator[](int i)const;
  friend bool operator<(const String& s1, const String& s2);
  friend bool operator>(const String& s1, const String& s2);
  friend bool operator==(const String& s1, const String& s2);
  friend ostream& operator<<(ostream& os, const String& s);
  friend istream& operator>>(istream& is, String& s);
  static int HowMany();
  friend String operator+(const String& s1, const String& s2);
  void stringlow();
  void stringup();
  int has(char c);
};
#endif
//string2.cpp
#include"string2.h"
#include<cstring>
#include<cctype>
#pragma warning( disable : 4996)
int String::num_strings = 0;
int String::HowMany() {
  return num_strings;
}
String::String(const char* s) {
  len = strlen(s);
  str = new char[len + 1];
  strcpy(str, s);
  num_strings++;
}
String::String() {
  len = 4;
  str = nullptr;
  num_strings++;
}
String::String(const String& s) {
  len = s.len;
  str = new char[len + 1];
  strcpy(str, s.str);
  num_strings++;
}
String::~String() {
  delete[]str;
  num_strings--;
}
String& String::operator=(const String& s) {
  if (this == &s)
    return *this;
  delete[]str;
  len = s.len;
  str = new char[len + 1];
  strcpy(str, s.str);
  return *this;
}
String& String::operator=(const char* s) {
  delete[]str;
  len = strlen(s);
  str = new char[len + 1];
  strcpy(str, s);
  return *this;
}
char& String::operator[](int i) {
  return str[i];
}
const char& String::operator[](int i)const {
  return str[i];
}
bool operator<(const String& s1, const String& s2) {
  return (strcmp(s1.str, s2.str) < 0);
}
bool operator>(const String& s1, const String& s2) {
  return s2 < s1;
}
bool operator==(const String& s1, const String& s2) {
  return (strcmp(s1.str, s2.str) == 0);
}
ostream& operator<<(ostream& os, const String& s) {
  os << s.str;
  return os;
}
istream& operator>>(istream& is, String& s) {
  char temp[String::CINLIM];
  is.get(temp, String::CINLIM);
  if (is)
    s = temp;
  while (is && is.get() != '\n')
    continue;
  return is;
}
String operator+(const String& s1, const String& s2) {
  String temp;
  temp.len = s1.len + s2.len;
  temp.str = new char[temp.len + 1];
  strcpy(temp.str, s1.str);
  strcat(temp.str, s2.str);
  return temp;
}
void String::stringlow() {
  for (int i = 0; i < len; i++)
    str[i] = tolower(str[i]);
}
void String::stringup() {
  for (int i = 0; i < len; i++)
    str[i] = toupper(str[i]);
}
int String::has(char c) {
  int sum = 0;
  for (int i = 0; i < len; i++)
    if (str[i] == c)
      sum++;
  return sum;
}
//main.cpp
#include<iostream>
using namespace std;
#include"string2.h"
int main() {
  String s1(" and I am a C++ student.");
  String s2 = "Please enter your name: ";
  String s3;
  cout << s2;
  cin >> s3;
  s2 = "My name is " + s3;
  cout << s2 << ".\n";
  s2 = s2 + s1;
  s2.stringup();
  cout << "The string\n" << s2 << "\ncontains " << s2.has('A')
    << " 'A' characters in it.\n";
  s1 = "red";
  String rgb[3] = { String(s1),String("green"),String("blue") };
  cout << "Enter the name of a primary color for mixing light: ";
  String ans;
  bool success = false;
  while (cin >> ans)
  {
    ans.stringlow();
    for (int i = 0; i < 3; i++)
    {
      if (ans == rgb[i])
      {
        cout << "That's right!\n";
        success = true;
        break;
      }
    }
    if (success)
      break;
    else
      cout << "Try again!\n";
  }
  cout << "Bye!\n";
  return 0;
}

image.gif

practice3

//stock.h
#pragma once
#ifndef STOCK3_H_
#define STOCK3_H_
#include<iostream>
class Stock {
  char* company;
  int shares;
  double share_val;
  double total_val;
  void set_tot() { total_val = shares * share_val; }
public:
  Stock();
  Stock(const char* c, long n = 0, double pr = 0.0);
  ~Stock();
  void buy(long num, double price);
  void sell(long num, double price);
  void updata(double price);
  const Stock& topval(const Stock& s)const;
  friend std::ostream& operator<<(std::ostream& os, const Stock& s);
};
#endif
//stock.cpp
#include"stock3.h"
#include<cstring>
#pragma warning(disable:4996)
using namespace std;
Stock::Stock() {
  company = nullptr;
  shares = 0;
  share_val = 0.0;
  total_val = 0.0;
}
Stock::Stock(const char* c, long n, double pr) {
  company = new char[strlen(c) + 1];
  strcpy(company, c);
  if (n < 0) {
    cout << "Number of shares can't be negative; "
      << company << "shares set to 0.\n";
    shares = 0;
  }
  else
    shares = n;
  share_val = pr;
  set_tot();
}
Stock:: ~Stock() {
  delete[]company;
}
void Stock::buy(long num, double price) {
  if (num < 0) {
    cout << "Number of shares purchased can't be negative."
      << "Transaction is aborted.\n";
  }
  else
  {
    shares += num;
    share_val = price;
    set_tot();
  }
}
void Stock::sell(long num, double price) {
  if (num < 0)
    cout << "Number of shares sold can't be negative."
    << "Transaction is aborted.";
  else if (num > shares)
    cout << "You can't sell more than you have!"
      << "Transaction is aborted!";
  else {
    shares -= num;
    share_val = price;
    set_tot();
  }
}
void Stock::updata(double price) {
  share_val = price;
  set_tot();
}
const Stock& Stock::topval(const Stock& s)const {
  if (s.total_val > total_val)
    return s;
  else
    return *this;
}
std::ostream& operator<<(std::ostream& os, const Stock& s) {
  ios_base::fmtflags orig = cout.setf(ios_base::fixed, ios_base::floatfield);
  streamsize prec = cout.precision(3);
  cout << "Company: " << s.company
    << "  Shares: " << s.shares << endl;
  cout << "  Shares Price: $" << s.share_val;
  cout.precision(2);
  cout << "  Total Worth: $" << s.total_val << endl;
  cout.setf(orig, ios_base::floatfield);
  cout.precision(prec);
  return os;
}
//main.cpp
#include"stock3.h"
#include<iostream>
const int STKS = 4;
int main() {
  using namespace std;
  Stock stocks[STKS] = {
    Stock("NanoSmart",12,20.0),
    Stock("Boffo Objects",200,2.0),
    Stock("Monolithic Obelisks",130,3.25),
    Stock("Fleep Enterprises",60,6.5)
  };
  cout << "Stock holding:\n";
  int st;
  for (st = 0; st < STKS; st++)
    cout << stocks[st];
  const Stock* top = &stocks[0];
  for (st = 1; st < STKS; st++)
    top = &top->topval(stocks[st]);
  cout << "\nMost valuable holding:\n";
  cout << *top << endl;
  return 0;
}

image.gif

practice4

#pragma once
//stack11.h
#ifndef STACK11_H_
#define STACK11_H_
typedef unsigned long Item;
class Stack {
  enum{MAX=10};
  Item* pitems;
  int size;
  int top;
public:
  Stack(int n = MAX);
  Stack(const Stack& s);
  ~Stack();
  bool isempty()const;
  bool isfull()const;
  bool push(const Item& item);
  bool pop(Item& item);
  Stack& operator=(const Stack& s);
};
#endif
//stack11.cpp
#include"stack11.h"
Stack::Stack(int n) {
  size = n;
  top = 0;
  pitems = new Item [size];
}
Stack::Stack(const Stack& s) {
  size = s.size;
  top = s.top;
  delete[]pitems;
  pitems = new Item[size];
  for (int i = 0; i < size; i++)
    pitems[i] = s.pitems[i];
}
Stack::~Stack() {
  delete[]pitems;
}
bool Stack::isempty()const {
  return top == 0;
}
bool Stack::isfull()const {
  return top == size;
}
bool Stack::push(const Item& item) {
  if (top == size)
    return false;
  else {
    pitems[top++] = item;
    return true;
  }
}
bool Stack::pop(Item& item) {
  if (top == 0)
    return false;
  else {
    item = pitems[--top];
    return true;
  }
}
Stack& Stack::operator=(const Stack& s) {
  if (this == &s)
    return *this;
  else {
    size = s.size;
    top = s.top;
    delete[]pitems;
    pitems = new Item[size];
    for (int i = 0; i < size; i++)
      pitems[i] = s.pitems[i];
  }
}
//stacker.cpp
#include<iostream>
#include"stack11.h"
#include<cctype>
void action(Stack& s);
//把对一个栈的操作分为三部分分别对三个栈完成,来检验复制构造函数和赋值运算符
//分开的部分,每一部分的操作要以q退出
int main() {
  using namespace std;
  Stack s1;
  action(s1);
  Stack s2 = s1;
  action(s2);
  Stack s3;
  s3 = s2;
  action(s3);
  cout << "Bye!\n";
  return 0;
}
void action(Stack& s) {
  using namespace std;
  char c;
  unsigned long po;
  cout << "Please enter A to add a purchase order,\n"
    << "P to process a PO, or Q to quit.\n";
  while (cin >> c && toupper(c) != 'Q') {
    while (cin.get() != '\n')
      continue;
    if (!isalpha(c)) {
      cout << '\a';
      continue;
    }
    switch (c) {
    case'A':
    case'a':cout << "Enter a PO number to add: ";
      cin >> po;
      if (s.isfull())
        cout << "Stack already full.\n";
      else
        s.push(po);
      break;
    case'P':
    case'p':if (s.isempty())
      cout << "Stack already empty.\n";
         else {
      s.pop(po);
      cout << "PO #" << po << "popped\n";
    }
         break;
    }
    cout << "Please enter A to add a purchase order,\n"
      << "P to process a PO, or Q to quit.\n";
  }
}

image.gif

practice5

//queue.h
#pragma once
class Customer {
  long arrive;
  int processtime;
public:
  Customer() { arrive = processtime = 0; }
  void set(long when);
  long when()const { return arrive; }
  int ptime()const { return processtime; }
};
typedef Customer Item;
class Queue {
  struct Node { Item item; Node* next; };
  enum { Q_SIZE = 0 };
  Node* front;
  Node* rear;
  int items;
  const int qsize;
  Queue(const Queue& q) :qsize(0) {}
  Queue& operator=(const Queue& q) { return *this; }
public:
  Queue(int qs = Q_SIZE);
  ~Queue();
  bool isempty()const;
  bool isfull()const;
  int queuecount()const;
  bool enqueue(const Item& item);
  bool dequeue(Item& item);
};
//queue.cpp
#include<cstdlib>
#include"queue.h"
using namespace std;
void Customer::set(long when) {
  arrive = when;
  processtime = rand() % 3 + 1;
}
Queue::Queue(int qs) :qsize(qs) {
  front = rear = nullptr;
  items = 0;
}
Queue::~Queue() {
  Node* temp;
  while (front != nullptr) {
    temp = front;
    front = front->next;
    delete temp;
  }
}
bool Queue::isempty()const {
  return items == 0;
}
bool Queue::isfull()const {
  return items == qsize;
}
int Queue::queuecount()const {
  return items;
}
bool Queue::enqueue(const Item& item) {
  if (isfull())
    return false;
  Node* add = new Node;
  add->item = item;
  add->next = nullptr;
  items++;
  if (front == nullptr)
    front = add;
  else
    rear->next = add;
  rear = add;
  return true;
}
bool Queue::dequeue(Item& item) {
  if (isempty())
    return false;
  item = front->item;
  items--;
  Node* temp = front;
  front = front->next;
  delete temp;
  if (items == 0)
    rear = nullptr;
  return true;
}
//bank.cpp
#include<iostream>
#include<ctime>
#include<cstdlib>
#include"queue.h"
using namespace std;
const int MIN_PER_HR = 60;
bool newcustomer(double x) {
  return(rand() * x / RAND_MAX < 1);
}
int main() {
  srand(time(0));
  int hours[5] = { 100,150,200,250,300 };
  for (int i = 0; i < 2; i++)
  {
    long cyclelimit = hours[i] * MIN_PER_HR;
    cout << "Hours: " << hours[i] << endl;
    for (int perhour = 10; perhour < 31; perhour++) 
    {
      Queue line(10);//line不能在外面定义,因为凡是循环里面用到的变量都需要重置
      //否则当turnaways出现后,line没有自动销毁,慢慢的就会累计错误
      //结果会出现负数,我找了半天才发现是因为在外面定义了line
      double min_per_cust = MIN_PER_HR / (double)perhour;
      Item temp;
      long turnaways = 0;
      long customers = 0;
      long served = 0;
      long sum_line = 0;
      int wait = 0;
      long line_wait = 0;
      for (int cycle = 0; cycle < cyclelimit; cycle++) 
      {
        if (newcustomer(min_per_cust)) 
        {
          if (line.isfull())
            turnaways++;
          else {
            customers++;
            temp.set(cycle);
            line.enqueue(temp);
          }
        }
        if (wait <= 0 && !line.isempty())
        {
          line.dequeue(temp);
          wait = temp.ptime();
          line_wait += (cycle - temp.when());
          served++;
        }
        if (wait > 0)
          wait--;
        sum_line += line.queuecount();
      }
      cout << "The average wait time by " << perhour
        << " customers every hours: " << double(line_wait) / served
        << " minuties\n";
    }
  }
  cout << "答案为18" << endl;
  cout << "Done!\n";
  return 0;
}

image.gif

practice 6

前两个文件不变

//bank.cpp
#include<iostream>
#include<ctime>
#include<cstdlib>
#include"queue.h"
using namespace std;
const int MIN_PER_HR = 60;
bool newcustomer(double x) {
  return(rand() * x / RAND_MAX < 1);
}
int main() {
  srand(time(0));
  int hours[5] = { 100,150,200,250,300 };
  for (int i = 0; i < 4; i++)
  {
    long cyclelimit = hours[i] * MIN_PER_HR * 6;
    //需要增加精度,cycle为10s
    cout << "Hours: " << hours[i] << endl;
    for (int perhour = 30; perhour < 41; perhour++)
    {
      Queue line1(10);
      Queue line2(10);
      double sec10_per_cust = MIN_PER_HR / (double)perhour * 6;
      Item temp1, temp2;
      long turnaways = 0;
      long customers = 0;
      long served = 0;
      long sum_line = 0;
      int wait1 = 0;
      int wait2 = 0;
      long line_wait = 0;
      for (int cycle = 0; cycle < cyclelimit; cycle++)
      {
        if (newcustomer(sec10_per_cust))
        {
          if (line1.queuecount() <= line2.queuecount())
          {
            if (line1.isfull());
            else
            {
              temp1.set(cycle);
              line1.enqueue(temp1);
            }
          }
          else
          {
            if (line2.isfull());
            else
            {
              temp2.set(cycle);
              line2.enqueue(temp2);
            }
          }
        }
        if (wait1 == 0 && !line1.isempty())
        {
          line1.dequeue(temp1);
          wait1 = temp1.ptime() * 6;
          line_wait += cycle - temp1.when();
          served++;
        }
        if (wait1 > 0)
          wait1--;
        if (wait2 == 0 && !line2.isempty())
        {
          line2.dequeue(temp2);
          wait2 = temp2.ptime() * 6;
          line_wait += cycle - temp2.when();
          served++;
        }
        if (wait2 > 0)
          wait2--;
      }
      cout << "The average wait time by " << perhour
        << " customers every hours: " << double(line_wait) / served / 6
        << " minuties\n";
    }
  }
  cout << "答案为34" << endl;
  cout << "Done!\n";
  return 0;
}

image.gif


目录
相关文章
|
2天前
|
存储 编译器 C++
|
1天前
|
C++
C++类和类模板——入门
C++类和类模板——入门
7 1
|
3天前
|
数据安全/隐私保护 C++
C++ 中的类是一种用户定义的数据类型,用于表示具有相似特征和行为的对象的模板。
C++ 中的类是一种用户定义的数据类型,用于表示具有相似特征和行为的对象的模板。
|
6天前
|
存储 编译器 C++
【C++初阶】—— 类和对象 (中)
【C++初阶】—— 类和对象 (中)
20 3
|
6天前
|
编译器 C++
【C++初阶】—— 类和对象 (下)
【C++初阶】—— 类和对象 (下)
9 2
|
6天前
|
存储 编译器 C语言
【C++初阶】—— 类和对象 (上)
【C++初阶】—— 类和对象 (上)
13 1
|
3天前
|
C++
C++ 是一种面向对象的编程语言,它支持对象、类、继承、多态等面向对象的特性
C++ 是一种面向对象的编程语言,它支持对象、类、继承、多态等面向对象的特性
|
7天前
|
存储 C++
C++类的实例:Stock(股票)类。
C++类的实例:Stock(股票)类。
|
7天前
|
编译器 数据安全/隐私保护 C++
c++primer plus 6 读书笔记 第十三章 类继承
c++primer plus 6 读书笔记 第十三章 类继承
|
7天前
|
C++
c++primer plus 6 读书笔记 第十一章 使用类
c++primer plus 6 读书笔记 第十一章 使用类

热门文章

最新文章