自学内容网 自学内容网

C++ Primer 第一章习题

1. c++ primer 第一章习题

1.1 练习1.3

在这里插入图片描述

#include<iostream>

int main(){
    std::cout << "Hello World!\n";
    return 0;
}

下图来自:Hello World
注意:别为了方便cout前不写std::而直接用 using namespace std; 把所有symbols都引入,而是写为 std::cout


写完后编译源码形成可执行文件

在这里插入图片描述
编译时可以加入一些参数



编译和执行过程展示

1.2 练习1.4

#include<iostream>

int main(){
    //初始化两个整数
    int n1,n2;
    std::cout << "Input two integer:";
    //输入两个整数
    std::cin >> n1 >> n2;
    //两个整数相乘
    std::cout << "product of two integer:" << n1*n2 << '\n';
    return 0;
}


下图来自:Input & Output (Basics)

注意:别每次输出都用std::endl结尾,每次调用 std::endl 都会刷新输出缓冲区并立即写入输出,这会造成性能退化


注意:
仅对运算符 << 进行一次调用(每次额外的调用都会产生少量开销)
仅当您绝对需要确保某些输出需要立即实现时才使用 std::endl

1.3 练习1.6

1.4 练习1.7


注意:嵌套注释是非法的

1.5 练习1.9


#include<iostream>

int main(){
    int i=50,result=0;
    while (i<=100)
    {
        result+=i;
        i++;
    }
    std::cout << "sum of 50 to 100:" << result << std::endl;
    return 0;
}



1.6 练习1.10

#include<iostream>

int main(){
    int i=10;
    while (i>=0)
    {
        std::cout << i << '\n';
        i--;
    }
    return 0;
}


1.7 练习 1.11

#include<iostream>

int main(){
    int a=0,b=0;
    std::cout << "please input two integer:";
    std::cin >> a >> b;
    std::cout << "integer from " << a << " to " << b << ": ";
    for (size_t i = a; i <= b; i++)
    {
        std::cout << i << " ";
    }
    std::cout << std::endl;
    return 0;
}

注意:为避免bugs,当我们在声明变量时要进行初始化

注意:要充分考虑用户输入的各种情况


1.8 练习 1.13


1.4.1节中的练习包括:1.9、1.10、1.11


用for重写练习1.9

#include<iostream>

int main(){
    int sum = 0;
    for (size_t i = 50; i <= 100; i++)
    {
        sum += i;
    }
    std::cout << "The sum of 50 to 100 is " << sum << std::endl;
    return 0;
}


什么时候使用size_t?
数组下标、循环计数、指定分配内存大小等等

用for重写练习1.10

#include<iostream>

int main(){
    for (size_t i = 10; i >= 0; i--)
    {
        std::cout << i << '\n';
    }
    std::cout << std::endl;
    return 0;
}

打印出来的不是10到0,而是一堆大整数


原因:当前的代码会导致无限循环,因为 size_t 是无符号整数,当 i 减到 0 时再减 1 会导致它变成一个非常大的正数。
解决:去掉等于0

#include<iostream>

int main(){
    for (size_t i = 10; i > 0; i--) //去掉=0
    {
        std::cout << i << '\n';
    }
    std::cout << std::endl;
    return 0;
}

参考答案:

用for重写练习1.11

#include<iostream>

int main(){
    int a=0,b=0;
    std::cout<<"Enter two numbers:";
    std::cin>>a>>b;
    if (a<=b)
    {
        for (size_t i = a; i <= b; i++)
        {
            std::cout<<i<<'\n';
        }
        
    }
    else
    {
        for (size_t i = b; i <= a; i++)
        {
            std::cout<<i<<'\n';
        }
        
    }
    std::cout<<std::endl;
    return 0;
}

什么时候使用std::endl?

参考答案:

1.9 练习 1.14

1.10 练习 1.15

1.11 练习 1.16

#include<iostream>
int main(){
    int number=0,sum=0;
    std::cout<<"Enter numbers (Add new line in the end):"<<std::endl;
    while (std::cin>>number) //当输入流成功读取一个整数时,循环继续
    {
        sum+=number;
    }
    std::cout<<"the sum of these numbers:"<< sum <<std::endl;
    return 0;
}

参考答案:

1.12 练习 1.20


cpp-primer/sales_item.h

Sales_item.h

/*
#ifndef 和 #endif 是为了防止多次包含相同的头文件。这种技术称为“包含保护”或“头文件保护”。它的目的是避免重复定义和编译错误。
第一次包含:
当头文件第一次被包含时,SALESITEM_H 未定义,因此 #ifndef SALESITEM_H 条件为真,编译器会处理接下来的代码。
#define SALESITEM_H 定义了 SALESITEM_H,以便下次包含该文件时,#ifndef SALESITEM_H 条件为假。
后续包含:
当头文件再次被包含时,SALESITEM_H 已定义,因此 #ifndef SALESITEM_H 条件为假,编译器会跳过 #ifndef 和 #endif 之间的所有代码。
*/
#ifndef SALESITEM_H  // 如果 SALESITEM_H 未定义
#define SALESITEM_H  // 定义 SALESITEM_H

// 包含输入输出流库
#include <iostream>
// 包含字符串库
#include <string>

// 定义 Sales_item 类
class Sales_item {
    // 声明友元函数,允许这些函数访问类的私有成员
    friend std::istream& operator>>(std::istream&, Sales_item&);
    friend std::ostream& operator<<(std::ostream&, const Sales_item&);
    friend bool operator<(const Sales_item&, const Sales_item&);
    friend bool operator==(const Sales_item&, const Sales_item&);
public:
    // 默认构造函数,用于初始化内置类型的成员
    Sales_item() = default;
    // 带参数的构造函数,用于初始化 bookNo
    Sales_item(const std::string &book): bookNo(book) { }
    // 从输入流中读取数据的构造函数
    Sales_item(std::istream &is) { is >> *this; }
public:
    // 成员函数,重载 += 运算符
    Sales_item& operator+=(const Sales_item&);
    
    // 成员函数,返回书籍编号
    std::string isbn() const { return bookNo; }
    // 成员函数,计算平均价格
    double avg_price() const;
private:
    // 私有成员变量,书籍编号
    std::string bookNo;      // 隐式初始化为空字符串
    // 私有成员变量,售出数量
    unsigned units_sold = 0; // 显式初始化
    // 私有成员变量,收入
    double revenue = 0.0;
};

// 内联函数,比较两个 Sales_item 对象的 ISBN
inline
bool compareIsbn(const Sales_item &lhs, const Sales_item &rhs) 
{ return lhs.isbn() == rhs.isbn(); }

// 非成员函数,重载 + 运算符
Sales_item operator+(const Sales_item&, const Sales_item&);

// 内联函数,重载 == 运算符
inline bool 
operator==(const Sales_item &lhs, const Sales_item &rhs)
{
    // 比较两个 Sales_item 对象的所有成员变量
    return lhs.units_sold == rhs.units_sold &&
           lhs.revenue == rhs.revenue &&
           lhs.isbn() == rhs.isbn();
}

// 内联函数,重载 != 运算符
inline bool 
operator!=(const Sales_item &lhs, const Sales_item &rhs)
{
    // 基于 == 运算符定义 != 运算符
    return !(lhs == rhs);
}

// 成员函数,重载 += 运算符
// 假设两个对象都引用相同的 ISBN
Sales_item& Sales_item::operator+=(const Sales_item& rhs) 
{
    // 累加售出数量和收入
    units_sold += rhs.units_sold; 
    revenue += rhs.revenue; 
    return *this;
}

// 非成员函数,重载 + 运算符
// 假设两个对象都引用相同的 ISBN
Sales_item 
operator+(const Sales_item& lhs, const Sales_item& rhs) 
{
    // 创建一个临时对象 ret,初始化为 lhs
    Sales_item ret(lhs);  
    // 将 rhs 的内容添加到 ret
    ret += rhs;           
    // 返回 ret
    return ret;           
}

// 非成员函数,重载 >> 运算符
std::istream& 
operator>>(std::istream& in, Sales_item& s)
{
    // 临时变量,用于存储价格
    double price;
    // 从输入流中读取书籍编号、售出数量和价格
    in >> s.bookNo >> s.units_sold >> price;
    // 检查输入是否成功
    if (in)
        // 计算收入
        s.revenue = s.units_sold * price;
    else 
        // 输入失败,将对象重置为默认状态
        s = Sales_item();  
    return in;
}

// 非成员函数,重载 << 运算符
std::ostream& 
operator<<(std::ostream& out, const Sales_item& s)
{
    // 输出书籍编号、售出数量、收入和平均价格
    out << s.isbn() << " " << s.units_sold << " "
        << s.revenue << " " << s.avg_price();
    return out;
}

// 成员函数,计算平均价格
double Sales_item::avg_price() const
{
    // 如果售出数量不为零,返回平均价格
    if (units_sold) 
        return revenue/units_sold; 
    else 
        // 否则返回 0
        return 0;
}

#endif // 结束 #ifndef 块
#include<iostream>
#include"Sales_item.h"
/*
book私有成员变量
    private:
    // 私有成员变量,书籍编号
    std::string bookNo;      // 隐式初始化为空字符串
    // 私有成员变量,售出数量
    unsigned units_sold = 0; // 显式初始化
    // 私有成员变量,收入
    double revenue = 0.0;

重载输入
// 非成员函数,重载 >> 运算符
std::istream& 
operator>>(std::istream& in, Sales_item& s)
{
    // 临时变量,用于存储价格
    double price;
    // 从输入流中读取书籍编号、售出数量和价格
    in >> s.bookNo >> s.units_sold >> price;
    // 检查输入是否成功
    if (in)
        // 计算收入
        s.revenue = s.units_sold * price;
    else 
        // 输入失败,将对象重置为默认状态
        s = Sales_item();  
    return in;
}

重载输出
// 非成员函数,重载 << 运算符
std::ostream& 
operator<<(std::ostream& out, const Sales_item& s)
{
    // 输出书籍编号、售出数量、收入和平均价格
    out << s.isbn() << " " << s.units_sold << " "
        << s.revenue << " " << s.avg_price();
    return out;
}
*/
int main(){
    //实例化类对象
    Sales_item book;
    //读取ISBN编号、售出数量和总价
    std::cout << "请输入书籍编号、售出数量和总价:" << std::endl;
    //读取多本书籍销售记录
    while(std::cin >> book)
    {
        //将每条记录打印到标准输出上
        std::cout << "ISBN、售出数量、总价、单价" << '\n' << book  << std::endl;
    }
    return 0;
}

参考答案:

1.13 练习 1.21

#include<iostream>
#include"Sales_item.h"
/*
book私有成员变量
    private:
    // 私有成员变量,书籍编号
    std::string bookNo;      // 隐式初始化为空字符串
    // 私有成员变量,售出数量
    unsigned units_sold = 0; // 显式初始化
    // 私有成员变量,收入
    double revenue = 0.0;

重载输入
// 非成员函数,重载 >> 运算符
std::istream& 
operator>>(std::istream& in, Sales_item& s)
{
    // 临时变量,用于存储价格
    double price;
    // 从输入流中读取书籍编号、售出数量和价格
    in >> s.bookNo >> s.units_sold >> price;
    // 检查输入是否成功
    if (in)
        // 计算收入
        s.revenue = s.units_sold * price;
    else 
        // 输入失败,将对象重置为默认状态
        s = Sales_item();  
    return in;
}

重载输出
// 非成员函数,重载 << 运算符
std::ostream& 
operator<<(std::ostream& out, const Sales_item& s)
{
    // 输出书籍编号、售出数量、收入和平均价格
    out << s.isbn() << " " << s.units_sold << " "
        << s.revenue << " " << s.avg_price();
    return out;
}

重载+
// 非成员函数,重载 + 运算符
// 假设两个对象都引用相同的 ISBN
Sales_item 
operator+(const Sales_item& lhs, const Sales_item& rhs) 
{
    // 创建一个临时对象 ret,初始化为 lhs
    Sales_item ret(lhs);  
    // 将 rhs 的内容添加到 ret
    ret += rhs;           
    // 返回 ret
    return ret;           
}
*/
int main(){
    //实例化类对象
    Sales_item book;
    Sales_item book2;
    //输出提示信息
    std::cout << "Please input two books' sales information:" << std::endl;
    //读取两本书的销售信息
    std::cin >> book >> book2;
    //检查两本书是否是同一本
    if(book.isbn() == book2.isbn()){
        //将每条记录打印到标准输出上
        std::cout << "ISBN、售出数量、总价、单价" << std::endl;
        //如果是同一本书,输出两本书的销售信息
        std::cout << book + book2 << std::endl;
    }else{
        //如果不是同一本书,输出错误信息
        std::cerr << "Data must refer to same ISBN" << std::endl;
        return -1;
    }
    return 0;
}

参考答案:
头文件中提供了比较两本书isbn的函数

// 内联函数,比较两个 Sales_item 对象的 ISBN
inline
bool compareIsbn(const Sales_item &lhs, const Sales_item &rhs) 
{ return lhs.isbn() == rhs.isbn(); }

头文件中重载了加号操作符

// 非成员函数,重载 + 运算符
// 假设两个对象都引用相同的 ISBN
Sales_item 
operator+(const Sales_item& lhs, const Sales_item& rhs) 
{
    // 创建一个临时对象 ret,初始化为 lhs
    Sales_item ret(lhs);  
    // 将 rhs 的内容添加到 ret
    ret += rhs;           
    // 返回 ret
    return ret;           
}

1.14 练习 1.22

#include<iostream>
#include"Sales_item.h"

int main() {
    Sales_item total;  // 保存当前 ISBN 的总和
    std::cout << "Please input the sales record: " << std::endl;
    if (std::cin >> total) {  // 读取第一条销售记录
        Sales_item trans;  // 保存每一条销售记录
        while (std::cin >> trans) {  // 读取剩余的销售记录
            if (compareIsbn(total,trans)) {  // 检查 ISBN 是否相同
                total += trans;  // 更新总和,相同书的销售记录合并
            } else {
                std::cout << "ISBN is different" << std::endl;
            }
        }
        std::cout << "Total for ISBN " << total.isbn() << ": " << total << std::endl;  // 输出最后一组 ISBN 的总和
    } else {
        std::cerr << "No data?!" << std::endl;  // 没有输入任何数据
        return -1;  // 表示失败
    }
    return 0;  // 表示成功
}

参考答案:

1.15 练习 1.23

#include <iostream>
#include "Sales_item.h"

int main() {
    Sales_item currentBook, newBook;
    int count = 0;
    int cnt[100] = {0};  // 假设最多有 100 种不同的 ISBN

    // 读取 ISBN、售出数量和价格
    std::cout << "请输入书籍信息(Ctrl+D 结束输入):" << std::endl;

    if (std::cin >> currentBook) {
        cnt[count]++;  // 统计第一条记录
        while (std::cin >> newBook) {
            if (compareIsbn(currentBook, newBook)) {  // ISBN 相同
                cnt[count]++;
            } else {  // ISBN 不同
                currentBook = newBook;  // 更新当前书籍
                cnt[++count]++;  // 统计新 ISBN 的记录
            }
        }
    } else {
        std::cerr << "No data?!" << std::endl;
        return -1;  // 表示失败
    }

    // 打印每个 ISBN 的销售记录数量
    for (int i = 0; i <= count; i++) {
        std::cout << "ISBN " << i + 1 << " has " << cnt[i] << " records." << std::endl;
    }

    return 0;  // 表示成功
}

参考答案:

#include <iostream>
#include "Sales_item.h"

int main() {
    Sales_item trans1, trans2;
    int num = 1;
    std::cout << "输入多条销售记录"<< std::endl;
    if (std::cin>>trans1) 
    {
        while (std::cin>>trans2) //读入后续交易记录
        {
            //检查两条交易记录是否有相同的ISBN
            if (compareIsbn(trans1, trans2))
            {
                num++;
            }else{ //ISBN不同
                std::cout << "ISBN:" << trans1.isbn() << "有" << num << "条销售记录" << std::endl; //打印相同书籍的销售记录
                trans1 = trans2; //将新书籍销售记录赋给trans1
                num = 1; //重置num
            }
        }
        std::cout << "ISBN:" << trans1.isbn() << "有" << num << "条销售记录" << std::endl;
    }else{ //没有读入数据
        std::cerr << "No data?!" << std::endl;
        return -1;
    }
    return 0;
}

每次比较两个书籍的ISBN,如果一样就num加一,再读入一条记录,比较两条记录,如果ISBN不一样,先打印之前的trans1的记录,然后将这条不一样的记录覆盖trans1,用于下一次比较,对应num置1


原文地址:https://blog.csdn.net/weixin_48524215/article/details/142620958

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!