C++Primer 第一章

news2024/12/30 3:14:14

C++概述

程序的组成

  • 数据的集合
  • 算法的集合

面向对象编程:我们通过一组数据抽象来建立问题的模型,简单来说就是把一些数据封装起来,就是我们类

面向过程编程:一个问题可直接由一组算法来建立模型

第一章 开始

1.1 问题的解决

这里有一个简单的例子来让我们看看如何设计编程思路,有的朋友可能想要把这个例子给手写出来,这里我也把自己的写法附在下面,供大家参考,写的比较简单,主要是把思路理顺.

我是这样写的,我们把文件中销售记录给读出来,后面经过排序格式化输入到另一个文件中,这个版本有很大的缺陷,例子说了是两个星期进行一次,这里我没有实现,我的排序是STL库默认的升序,这里大家可以使用降序.我这里都是使用的基本的类型大家可以进行封装,例如把书名和销售量封在一起,看搭建的思路吧.


//某个书店将每本售出图书的书名和出版社输入到一个文件中,这些信息以书售出的时间顺序输入.
//每两周店主将手工计算每本书的销售量以及每个出版社的销售量报表以出版社名称的字母顺序排列以使下订单

#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <map>
#include <unordered_map>
#include <cstring>


#define SPE " "
#define LEN strlen(SPE)


class BookSales 
{
  public:
  BookSales(const std::string& src, const std::string& dest)
    :_file_name(src)
     ,_result_name(dest)
  {}

  public:
  void run()
  {
    readFile();
    calculateSales();
    sortSales();
    result();
  }

  private:
  // 1. 读销售记录
  void readFile()
  {
    // 我们的格式应该是 书名 出版社 年-月-日\r\n 
    std::ifstream read_file(_file_name);
    if(read_file.is_open() == false)
    {
      std::cerr << "文件不存在" <<std::endl;
      return;
    }
    std::string str;
    while(std::getline(read_file, str))
    {
      _sales_records.push_back(std::move(str));
    }
  }

  // 2. 根据书名和出版社计算销售量
  void calculateSales()
  {
    // 这个我们按照
    // 书名 出版社 销售量来
    for(auto& e: _sales_records)
    {
      std::string name;
      std::string publishing_house;
      
      std::size_t pos1 = e.find(SPE, 0);
      if(pos1 == std::string::npos)
        continue;
      std::size_t pos2 = e.find(SPE, pos1+LEN);
      if(pos2 == std::string::npos)
        continue;
      name = e.substr(0, pos1);
      publishing_house = e.substr(pos1+LEN, pos2-pos1-LEN);
      
      std::unordered_map<std::string, int>& m =  _map[publishing_house];
      m[name]++;
    }
  }
  

  // 3. 以出版社名称对书名进行排序
  void sortSales()
  {
    // 注意,我们使用是map,底层是二叉树,已经排好序了,我不知道要不要对销量经行排序,不过
    // 我感觉排好序更加好一线,这里我们来直接排序一下,这里我们继续使用一个map,只不过这里我们让销量做K
    
    for(auto& p:_map)
    {
     auto& it =  _result[p.first];
     auto iter = p.second.begin();
     while(iter != p.second.end())
     {
       it.insert(std::make_pair(iter->second, iter->first));// 销量:书名
       iter++;
     }
    }
  }

  // 4 . 输出结果
  void result()
  {
    // 这里是输出结果,我们把输出的记过放在一个文件中
    std::ofstream outfile(_result_name);
    if(outfile.is_open() == false)
    {
      std::cerr << "打开文件失败" << std::endl;
      return;
    }
    for(auto& p: _result)
    {
      std::string str = p.first;
      str += SPE;
      auto iter = p.second.begin();
      while(iter != p.second.end())
      {
        std::string s = str;
        s += iter->second;
        s += SPE;
        s += std::to_string(iter->first);
        s += "\r\n";
        outfile << std::move(s);
        iter++;
      }
    }
  }

  private:
    std::string _file_name; // 这个是我们保存销售文件的名字
    std::string _result_name;
    std::vector<std::string> _sales_records; // 每一条销售记录 
    std::map<std::string, std::unordered_map<std::string, int>> _map; // 这个是计算销量
    std::map<std::string, std::multimap<int, std::string>> _result; // 这个是计算销量

};

1.2 C++程序

说一下声明和定义,这里是个人理解.

  • 声明 不开辟空间
  • 定义 开辟空间
extern a;   // 声明
int b;      // 个人感觉是定义,开辟空间了
int c = 10; // 定义并初始化

1.3 预处理器指示符

所谓的预处理器指示符就是我们的#,他的作用有下面两个作用

  • 引用头文件
  • 宏定义

来解释一下在引用头文件究竟是如何做到的,这里很简单,但编译器看到这是头文件的引用时,就会在路径中寻找这个文件,然后把这个文件的内容直接添加到我们的代码中,这里到程序是如何运行那里非常清楚.至于宏定义我就不谈了,之前写过博客.

我们一直谈防止头文件被引用?什么意思?我们好像从来没有遇到过这个情况?这里说一下,由于大家可能会把函数的定义写道hpp文件中,那么此时我们多次重复引用这个hpp文件就会出现问题,大家看一下.

image-20230504152234353

这就是我们为何要防止头文件被重复引用的问题,至于如何解决,可以看书或者搜一下,我们不谈.

下面来说如何在命令行中如何定义一个宏,这个还是有点用的,这里很简单,选项是D.

#include <iostream>    
    
int main()    
{    
#ifdef DEBUG     
  std::cout <<"宏已经被定义" << std::endl;    
#else    
  std::cout <<"宏没有被定义" << std::endl;                                                                    
#endif    
  return 0;        
}

image-20230504154015374

说下有作用的两个宏,一个是当前宏所在的函数,一个是得到该程序源文件的名字

image-20230504154539952

注意,下面我们要知道assert是一个宏,注意是一个宏,不是函数.它的用法一般是为了检测参数的合法性,不过所谓的合法性也是存在限制的.

我们知道C++是支持C语言的,那么C语言的头文件如何在C++中引用,这里有两个方法

  • 直接使用,方法不变
  • 把.h去掉,然后前面加上一个c

下面举一个例子,他的作用是一样的.

#include <stdio.h>    
#include <cstdio>    

书上说这两个方式效果不一样?这里我感觉有点疑惑,可能是我没有看太懂,我们std命名空间里面好像是没有assert的,不过我把段话的意思给大家分析一下,就是我们使用C语言风格的方式,那么我们使用没有问题,如果是G++风格的,一些东西可能会被封装到std中,看个人使用遇到的情况吧.

image-20230505171010261

1.4 注释

C++的注释和C语言是一样的,我们要善于使用注释.

1.5 输入/输出初步

C++除了格式化输入和输出之外也支持自己的输入和输出,而且这个更加的方便,下面直接下例子.

#include <iostream>

int main()
{
  int a = 0;
  std::cin >> a;
  std::cout << a;
  std::cout << std::endl; // endl 就是换行符
  std::cerr << a;
  std::cout << std::endl; // endl 就是换行符   
  return 0;                                
}                                          

image-20230505171732135

说的其他的,首先标准输入在输入字符串的时候遇到空格会结束

image-20230505182051629

这里我们推荐使用getline函数,先来看现象.

int main()    
{    
  std::string str;    
  //std::cin >> str;    
  std::getline(std::cin, str);    
  std::cout << str << std::endl;    
  return 0;                 
} 

image-20230505182218638

1.5.1 文件输入和输出

我们可以把一个文件也实例化出一个对象,这样我们也开始可以使用>>或者<<来进行输入和输出的,这是只测试输出,毕竟后面会专门谈到

#include <iostream>
#include <string>
#include <fstream>
               
int main()     
{              
  std::string file_name = "file.txt";
  std::ofstream out_file(file_name); // 打开一个文件供输出
               
  if(out_file.is_open() == false)
  {            
    std::cerr << "打开文件失败" << std::endl;
    return 0;  
  }            
               
  std::string str = "为了测试";
  for(int i = 0; i < 3; i++)
    out_file << str;
  return 0;                                               
}                 

image-20230505183057632

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

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

相关文章

C++ 的类型转换

目录 1. C语言中的类型转换 2. C强制类型转换 2.1static_cast 2.2 reinterpret_cast 2.3 const_cast 2.4 dynamic_cast 3. RTTI&#xff08;了解&#xff09; 1. C语言中的类型转换 在 C 语言中&#xff0c;如果 赋值运算符左右两侧类型不同&#xff0c;或者形参与实参类型不…

华为OD机试真题-扑克牌大小【2023】【JAVA】

一、题目描述 扑克牌游戏大家应该都比较熟悉了&#xff0c;一副牌由54张组成&#xff0c;含3~A、2各4张&#xff0c;小王1张&#xff0c;大王1张。牌面从小到大用如下字符和字符串表示&#xff08;其中&#xff0c;小写joker表示小王&#xff0c;大写JOKER表示大王&#xff09…

【linux的学习】

文章目录 linux的学习一、工具安装与联网&#xff1f;二、Linux软件安装1.安装jdk2.安装MySQL2.读入数据 总结 linux的学习 一、工具安装与联网&#xff1f; 1.1安装好VM后 进入vi /etc/sysconfig/network-scripts/ifcfg-ens33 然后ip addr 查看ip 1.2打开IDEA的tools 二、…

Jpeg算法

Jpeg算法&#xff1a; JPEG会分析图片的各个部分找到并删除人眼不易察觉的元素。使用jpeg算法的时候可以选一个叫’质量’的可变数值来决定压缩的程度&#xff0c;压缩过多的时候我们会得到有缺陷的方框&#xff0c;叫做膺像。 压缩算法之所以有用的原因&#xff1a;人的眼睛并…

Linux开发工具大全 - 软件包管理器yum | vim编辑器 | gcc/g++编译器 | 自动化构建工具Make/Makefile | gdb调试工具

目录 Ⅰ. Linux 软件包管理器 yum 一、yum 背景知识 二、yum 的基本使用 1、查看软件包 2、软件包名称构成 3、安装软件 4、卸载软件 Ⅱ.vim编辑器 一、认识vim 1、vim概念 2、模式及其切换 二、vim使用 1、vim的指令&#xff08;重要&#xff09; 命令模式 插…

PCB表面处理方式详解

上一篇文章中介绍了关于PCB设计中的常用基本概念&#xff0c;那么本篇文章就挑选其中的第三点【表面处理】&#xff0c;给大家展开说一说&#xff0c;顺便也自我温习一下。 什么是表面处理&#xff1f; 由于铜长期与空气接触会使得铜氧化&#xff0c;所以我们需要在PCB表面做一…

【毕业设计】基于springboot的大学生综合素质测评管理系统

目录 前言介绍综合素质测评表特色功能页面展示一&#xff0e;开发环境1.JDK配置2.安装IDEA3.MySQL安装 二&#xff0e;项目导入和配置三&#xff0e;数据库配置1.创建数据库2.修改项目数据库配置 四&#xff0e;项目部署1.项目启动2.项目访问 在线体验其他类似系统关于我 前言 …

UDP协议介绍

文章目录 一、端口号二、UDP协议1.UDP协议格式2.UDP协议的特点3.UDP缓冲区 三、UDP注意事项 一、端口号 端口号是在网络中标识一台主机上进行通信程序的唯一性的&#xff0c;在TCP/IP协议中&#xff0c;用源IP、源端口号、目的IP、目的端口号、协议号这样一个五元组来标识一个…

Android Studio Flamingo | 2022.2.1 Patch 1(火烈鸟版本)

版本概况 Android Studio Flamingo | 2022.2.1 Patch 1 Build #AI-222.4459.24.2221.9971841, built on April 20, 2023 Runtime version: 17.0.60-b2043.56-9586694 amd64 VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o. Windows 11 10.0 GC: G1 Young Generation, G1 Old…

LLMs 记忆体全新升级:六大新功能全面出击,用户体验值拉满!

LLMs 时代之下&#xff0c;CVP Stack 必不可少。 其中&#xff0c;C 代表以 ChatGPT 为代表的大模型&#xff0c;它在 AI 程序中充当中央处理器的角色&#xff1b;V 代表 Vector Database&#xff0c;即以 Zilliz Cloud 和 Milvus 为代表的向量数据库&#xff0c;为大模型提供知…

3ds Max渲染慢怎么办_加快3ds Max渲染的一些技巧!

3ds Max是一款用于建筑可视化、产品建模、角色开发以及动画的3D建模软件。因此无论您是建筑师、产品设计师还是插画家&#xff0c;使用3ds Max制作项目都是您的绝佳软件选择。包括3ds Max在内的3D软件包通常都通过渲染过程&#xff0c;将3D模型转换为CGI。 项目在渲染后我们会看…

如何用ChatGPT做一门课?(包含大纲、脚本、PPT文本)

该场景对应的关键词库&#xff08;13个&#xff09;&#xff1a; 市场调研、在线网络课程、教学平台、社交媒体营销、子主题、细分领域、课程大纲、章节、推广渠道、课程脚本、文案基本要素、案例、具体方法 提问模板&#xff08;6个&#xff09;&#xff1a; 第一步&#xf…

C++实现一个异步日志库

C实现一个异步日志库 一、概念二、代码实现三、小结 一、概念 异步日志库&#xff08;Asynchronous Logging Library&#xff09;是一种用于记录应用程序运行时信息的库。相比于同步日志库&#xff0c;异步日志库能够提供更高的性能和可扩展性&#xff0c;因为它使用了异步写入…

谈谈 地下水数值模拟Visual modflow Flex

Visual MODFLOW Flex是行业标准规范软件&#xff0c;将地下水流和污染物运移、基本分析和校准工具&#xff0c;以及强大的三维可视化功能集成在一个单一的&#xff0c;易于使用的软件环境中。 使用Visual MODFLOW Flex&#xff0c;用户将拥有所有的工具&#xff0c;可用来解决…

单点性能测试-页面Load时间

打开chrome浏览器的调试工具&#xff0c;如图所示&#xff1a; DOMContentLoaded&#xff1a;DOM树构建完成。即HTML页面由上向下解析HTML结构到末尾封闭标签的时间 Load:页面加载完成的时间。 DOM树构建完成后&#xff0c;继续加载html/css 中的图片、音频、视频等等外部资源…

用Python在25行以下代码实现人脸识别

** OpenCV ** OpenCV是最流行的计算机视觉库。最初是用C/C编写的&#xff0c;现在它提供了Python的API。 OpenCV使用机器学习算法来搜索图片中的面孔。因为脸是如此复杂&#xff0c;没有一个简单的测试可以告诉你它是否找到了一张脸。相反&#xff0c;有成千上万的小模式和特…

08-Vue技术栈之过度与动画

目录 1、作用2、写法3、动画的应用4、过度的应用5、animate.css动画库的使用 1、作用 在插入、更新或移除 DOM元素时&#xff0c;在合适的时候给元素添加样式类名。 图示&#xff1a; 2、写法 准备好样式&#xff1a; 元素进入的样式&#xff1a; v-enter&#xff1a;进入的…

U-boot 的使用

编译U-Boot A. 首先在 Ubuntu 中安装 ncurses 库&#xff0c;否则编译会报错&#xff0c;安装命令如下&#xff1a; sudo apt-get install libncurses5-dev B. 解压缩&#xff1a; tar -vxjf uboot-imx-2016.03-2.1.0-g8b546e4.tar.bz2 C. 手工编译 uboot&#xff1a; make …

系统日志规范及最佳实践

作者&#xff1a;蓝旺 打印日志是一门艺术&#xff0c;日志信息是开发人员排查线上问题最主要的手段之一&#xff0c;但规范打日志被开发同学经常所忽视。日志就像保险&#xff0c;平时正常的时候用不上&#xff0c;但是一旦出问题就都想看有没有保险可以用。一条良好的日志&am…

4款不错的UI设计软件推荐

俗话说&#xff0c;如果工人想做好工作&#xff0c;他们必须首先磨利他们的工具。高质量的UI设计软件将使设计事半功倍。 近年来&#xff0c;UI设计软件的逐渐多样化&#xff0c;让一些需要使用UI设计软件的小伙伴不知道如何选择。 我整理了四款优秀的免费UI设计软件。别错过…