zoukankan      html  css  js  c++  java
  • 【C++】C++ primer 第一章学习笔记

    第一章 开始

    1.1 编写一个简单的C++程序

    ​ 每个C++程序都包含一个或多个函数,其中有一个必须是main函数。

    //最简单的main函数
    int main()
    {
    	return 0;
    } 
    

    一个函数的定义包括四部分:

    • 返回类型
    • 函数名
    • 形参列表
    • 函数体

    注意:

    • main函数的返回类型必须是 int 型(int类型是一种内置类型,即语言自身定义的类型)。

    • 当return语句包含一个值时,此返回值的类型必须与函数的返回类型相容。

      在大多数系统中,main的返回值被用来指示状态。返回值0表明成功,非0的返回值含义由系统定义,通常用来指出错误类型

    1.1 编译、运行程序

    程序源文件命名约定

    • 程序文件通常被称为源文件

    • 源文件的名字以一个后缀为结尾,后缀是一个句点后接一个或多个字符组成的。

      后缀告诉系统这个文件是一个C++程序,不同编译器使用不同的后缀命名约定,最常见的包括.cc、.cxx、.cpp、.cp 及 .C

    从命名行运行编译器

    见P3~P4

    再探编译

    编译器的一部分工作是寻找程序文本中的错误。编译器没有能力检查一个程序是否按照其作者的意图工作,但可以检查形式上的错误。下面是一些最常见的编译器可以检查出来的错误:

    • 语法错误

      //错误:main的参数列表漏掉了
      int main(
      {
          //错误:endl后使用了冒号而非分号
          std::cout << "Read each file" << std::endl:
          //错误:字符串字面值常量的两侧漏掉了分号
          std::cout << Update master. <<std::endl;
          //错误:漏掉了第二个输出运算符
          std::cout << "Write new master." std::endl;
          //错误:return语句漏掉了分号
          return 0
      }
      
    • 类型错误:C++中每个数据项都有其类型。例如:10的类型是int;单词“hello”,包括两边的双引号标记,则是一个字符串字面值常量。一个类型错误的例子:向期望参数为int的函数传递了一个字符串字面值常量。

    • 声明错误:C++程序中每个名字都要先声明后使用。名字声明失败通常会导致一条错误信息。两种常见的错误声明:

      • 对来自标准库的名字忘记使用 std::
      • 标识符名字拼写错误

    按照编译器提示的报告顺序逐个修正错误是一种好习惯。因为一个单个错误常常会具有传递效应,导致编译器在其后报告比实际数量多得多的错误信息。

    另一个好习惯是在每修正一个错误后就立即重新编译代码,或者最多是修正了一小部分明显的错误后就重新编译。这就是所谓的 “编辑-编译-调试” 周期。

    1.2 初始输入输出

    ​ C++语言未定义任何输入输出IO语句,取而代之的是包含了一个全面的标准库来提供IO机制(以及很多其他设施)。

    ​ iostream 库包含两个基础类型 istream(输入流) 和 ostream(输出流)。

    ​ 一个流就是一个字符系列,是从IO设备读出或写入IO设备的。术语“流”想表达的是:随着时间的推移,字符是顺序生成或消耗的。

    标准输入输出对象

    ​ 标准库定义了4个IO对象。

    处理输入:

    • cin(istream类型的对象),该对象也被称为标准输入

    处理输出:

    • cout(ostream类型的对象),该对象也被称为标准输出
    • cerr(ostream类型的对象),通常用 cerr 来输出警告和错误消息,因此也被称为标准错误
    • clog(ostream类型的对象),用来输出程序运行时的一般性信息

    一个使用IO库的程序

    示例:

    ​ 一个提示用户输出两个数,然后输出它们的和程序:

    #include<iostream>
    int main()
    {
        std::cout << "Enter two number:" << std::endl;
        int v1 = 0, v2 = 0;
        std::cin >> v1 >> v2;
        std::cout << "The sum of " << v1 << "and" << v2
                  << "is" << v1 + v2 << std::endl;
        return 0;
    }
    

    头文件

    • 第一行告诉编译器我们想使用iostream库。尖括号中的名字指出了一个头文件
    • 每个使用标准库设施的程序都必须包含相关的头文件
    • 对于来自标准库的头文件应用尖括号(< >)包围头文件名,对于不属于标准库的头文件,则用双引号(“ ”)包围
    • include指令和头文件必须写在同一行

    • 通常,#include指令必须出现在所有函数之外,一般将一个程序的所有#include指令放在源文件的开始

    向流写入数据

    ​ 在C++中,一个表达式产生一个计算结果,它由一个或多个运算对象和(通常是)一个运算符组成。
    ​ << (输出运算符)接受两个运算对象:左侧的运算对象必须是一个ostream对象,右侧的运算对象是要打印的值。此运算符将给定的值写到给定的ostream对象中。输出运算符的计算结果就是其左侧运算对象。

    ​ 对于语句std::cout << "Enter two number:" << std::endl;,使用了两次 << 运算符,因为此运算符返回其左侧的运算对象,因此第一个运算符的结果成为了第二个运算符。这样,就可以将输出请求连接起来。
    ​ 链中每个运算符的左侧运算对象都是相同的(本例中是:std::cout)。因此可以用两条语句生成相同的输出。

    • std::cout << "Enter two number:" << std::endl;
    • <=> (std::cout << "Enter two number:") << std::endl;
    • <=> std::cout << "Enter two number:"; std::cout << std::endl;

    操纵符 endl

    ​ endl是一个被称为操纵符的特殊值。写入endl的效果是结束当前行,并将与设备关联的缓冲区中的内容刷到设备中。缓冲刷新操作可以保证到目前为止的所有输出都真正写入输出流中,而不是仅停留在内存中等待写入流。

    在调试试我们经常添加打印语句。这类语句应保证“一直”刷新流。否则程序崩溃,输出可能还留在缓冲区中,从而导致关于程序崩溃位置的错误推断。

    从流读取数据

    ​ 初始化一个变量,就是在变量创建的同时为它赋予一个值。

    ​ >>(输入运算符)与输出运算符类似,接受一个istream作为其左侧运算对象,接受一个对象作为其右侧运算对象。他从给定的istream读入数据,并存入给定对象中。与输出运算符类似,输出运算符返回其左侧运算对象作为其计算结果。

    同理有:

    • std::cin >> v1 >> v2;
    • <=> (std::cin >> v1) >> v2;
    • <=> std::cin >> v1; std::cin >> v2;

    使用标准库中的名字

    • 前缀std::指出名字 cout 和 endl 是定义在名为 std 的命名空间(namespace)中的。命名空间可以帮助我们避免不经意的名字定义冲突,以及使用库中相同名字导致的冲突。
    • 标准库定义的所有名字都在命名空间 std 中。
    • 通过命名空间使用标准库的副作用:当使用标准库中的一个名字时,必须显式说明我们想使用来自命名空间 std 中的名字。

    1.3 注释简介

    注意:当修改代码时,不要忘记同时更新注释!

    C++中注释种类

    ​ C++中有两种注释:单行注释和界定符对注释。

    • 单行注释:以双斜线(//)开始,以换行符结束。这种注释可以包含任何文本。
    • 注释界定符:继承自C语言的两个界定符(/* 和 */)。可以包含除 */ 以外的任何内容。
      当注释界定符跨越多行时,最好能显式指出其内部的程序都属于多行注释的一部分。因此我们采用的风格是,注释内的每一行都以一个星号开头,从而指出整个范围都是多行注释的一部分
    /*
    * 注释对/* */不能嵌套。
    * “不能嵌套”几个字会被认为是源码,
    * 像剩余程序一样处理。
    */
    

    1.4 控制流

    语句块:用花括号包围的零条或多余语句的序列。

    1.4.1 while语句

    ​ while语句反复执行一段代码,直至给定条件为假为止。

    while语句形式:

    while(condition)
    	statement
    

    1.4.2 for语句

    ​ 由于在循环条件中检测变量、在循环体中递增变量的模式使用非常频繁,以至于C++语言专门定义了第二种循环语句——for语句

    ​ 每个for语句都包括两部分:循环头和循环体。循环头控制循环体的执行次数,它由三部分组成:一个初始化语句(init-statement)、一个循环条件(condition)以及一个表达式(expression)。

    • 初始化语句只在for循环入口处执行一次
    • 循环体内次执行前先检查循环条件
    • 表达式在for循环体之后执行

    1.4.3 读取数量不定的输入数据

    ​ 如 当我们预先不知道要对多少个数求和时,就需要不断读取数据直至没有新的输入为止:

    #include<iostream>
    int main()
    {
        int sum = 0, value = 0;
        //读取数据直至遇到文件尾,计算所有读入的值的和
        while(std::cin >> value) {
            sum += value;
        }
        std::cout << "Sum is : " << sum << std::endl;
        return 0;
    }
    

    ​ 当使用一个istream对象作为条件时,其效果是检测流的状态。

    • 如果流是有效的,即流未遇到错误,那么检测成功。
    • 当遇到文件结束符(end-of-file),或遇到一个无效输入时(如读入的值不是一个整数),istream对象的状态会变为无效。处于无效状态的istream对象会使条件变为假。

    1.4.4 if语句

    用if语句写一个程序,来统计在输入中每个值连续出现了多少次:

    #include<iostream>
    int main() 
    {
    	//currVal是我们正在统计的数;将读入的新值存入val
    	int currVal = 0, val = 0;
    
    	//读取第一个数,并确保确有数据可以处理
    	if (std::cin >> currVal) {
    		int cnt = 1; //保存正在处理的当前值个数
    
    		while (std::cin >> val) { //读取剩余数字
    			if (val == currVal)
    				++cnt;
    			else {
    				std::cout << currVal << "occurs"
    					<< cnt << "times" << std::endl;
    				currVal = val; //记住新值
    				cnt = 1; //重置计数器
    			}
    		}//while循环在这结束
    
    		//记住打印文件中最后一个值的个数
    		std::cout << currVal << "occurs"
    			<< cnt << "times" << std::endl;
    	}
    	
    	return 0;
    }
    

    1.5 类简介

    • 一个类定义了一个类型,以及与其关联的一组操作。

    • 习惯上,头文件根据其中定义的类的名字来命名。通常使用.h作为头文件的后缀,也有一些程序员习惯用.H、.hpp或.hxx

    • 标准库头文件通常不带后缀。

    • 编译器一般不关心头文件名的形式,但有的IDE对此有特定要求。

    1.5.1 Sales_item类

    ​ 每个类都定义了一个新的类型,其类型名就是类名。因此,Sales_item 类定义了一个名为Sales_item 的类型。

    ​ 语句:Sales_item item;
    ​ 想表达的item是一个Sales_item类型的对象。通常将“一个Sales_item类型的对象” 简单说成”一个Sales_item对象“ 或更简单的”一个Sales_item“。

    //Sales_item类
    class Sales_item {
    	// these declarations are explained section 7.2.1, p. 270 
    	// and in chapter 14, pages 557, 558, 561
    	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:
    	// constructors are explained in section 7.1.4, pages 262 - 265
    	// default constructor needed to initialize members of built-in type
    #if defined(IN_CLASS_INITS) && defined(DEFAULT_FCNS)
    	Sales_item() = default;
    #else
    	Sales_item() : units_sold(0), revenue(0.0) { }
    #endif
    	Sales_item(const std::string &book) :
    		bookNo(book), units_sold(0), revenue(0.0) { }
    	Sales_item(std::istream &is) { is >> *this; }
    public:
    	// operations on Sales_item objects
    	// member binary operator: left-hand operand bound to implicit this pointer
    	Sales_item& operator+=(const Sales_item&);
     
    	// operations on Sales_item objects
    	std::string isbn() const { return bookNo; }
    	double avg_price() const;
    	// private members as before
    private:
    	std::string bookNo;      // implicitly initialized to the empty string
    #ifdef IN_CLASS_INITS
    	unsigned units_sold = 0; // explicitly initialized
    	double revenue = 0.0;
    #else
    	unsigned units_sold;
    	double revenue;
    #endif
    };
    

    类定义了行为:

    一般而言,类的作者决定了类类型对象上可以使用的所有操作(如Sales_item的作者定义了类对象可以执行的所有动作)。

    1.5.2 初始成员函数

    代码:

    #include<iostream>
    #include"Sales_item.h"
    int main()
    {
        Sales_item item1,item2;
        std::cin >> item1 >>item2;
        //首先检查item1和item2是否表示相同的书
        if(item1.isbn() == item2.isbn()) {
            std::cout <<item1 + item2 <<std::endl;
            return 0; //表示成功
        } else {
            std::cerr << "Data must refer to same ISBN" << std::endl;
            return -1; //表示失败
        }
    }
    

    上述程序中,if语句检测条件item1.isbn() == item2.isbn(),调用名为 isbn 的成员函数。

    • 成员函数是定义为类的一部分的函数,有时也被称为方法

    • 使用点运算符(.)来表达 某个对象 的 成员 。点运算符只能用于类类型的对象。其左侧运算对象必须是一个类类型的对象,右侧运算对象必须是该类型的一个成员名,运算结果为右侧运算对象指定的成员。

    • 使用调用运算符( () )来调用一个函数。

    1.6 书店程序

    见P21~ P22

  • 相关阅读:
    java关键字之synchronized
    java多线程之线程安全
    java多线程之管道流
    java多线程之多生产者-多消费者
    java多线程之生产者-消费者
    java多线程之wait和notify
    python读取json文件并解析
    java之继承中的静态变量
    shell多线程(3)while循环
    equals与hashcode
  • 原文地址:https://www.cnblogs.com/LFVH-Coding/p/14284677.html
Copyright © 2011-2022 走看看