C++ Primer学习笔记第一、二单元

一、基础知识

1.4控制流

 1.在for循环中,循环控制变量的初始化和修改都放在语句头部分,形式较简洁,且特别适用于循环次数已知的情况。在while循环中,循环控制变量的初始化一般放在while语句之前,循环控制变量的修改一般放在循环体中,形式上不如for语句简洁,但它比较适用于循环次数不易预知的情况(用某一条件控制循环)。两种形式各有优点,但它们在功能上是等价的,可以相互转换。

2.读取数量不定的输入数据

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

windows系统中,文件结束符的方法是ctrl+z,然后按Enter或Return。

1.5类简介

练习1.20

头文件Sales_item.h

#ifndef SALESITEM_H
#define SALESITEM_H
#include <iostream>
#include <string>

class Sales_item
{
public:
	Sales_item(const std::string& book) :isbn(book), units_sold(0), revenue(0.0) {}
	Sales_item(std::istream& is) { is >> *this; }
	friend std::istream& operator>>(std::istream&, Sales_item&);
	friend std::ostream& operator<<(std::ostream&, const Sales_item&);
public:
	Sales_item& operator+=(const Sales_item&);
public:
	double avg_price() const;
	bool same_isbn(const Sales_item& rhs)const
	{
		return isbn == rhs.isbn;
	}
	Sales_item() :units_sold(0), revenue(0.0) {}
public:
	std::string isbn;
	unsigned units_sold;
	double revenue;
};

using std::istream;
using std::ostream;
Sales_item operator+(const Sales_item&, const Sales_item&);
inline bool operator==(const Sales_item& lhs, const Sales_item& rhs)
{
	return lhs.units_sold == rhs.units_sold && lhs.revenue == rhs.revenue && lhs.same_isbn(rhs);
}
inline bool operator!=(const Sales_item& lhs, const Sales_item& rhs)
{
	return !(lhs == rhs);
}

inline Sales_item& Sales_item::operator +=(const Sales_item& rhs)
{
	units_sold += rhs.units_sold;
	revenue += rhs.revenue;
	return *this;
}
inline Sales_item operator+(const Sales_item& lhs, const Sales_item& rhs)
{
	Sales_item ret(lhs);
	ret += rhs;
	return ret;
}
inline istream& operator>>(istream& in, Sales_item& s)
{
	double price;
	in >> s.isbn >> s.units_sold >> price;
	if (in)
		s.revenue = s.units_sold * price;
	else
		s = Sales_item();
	return in;
}
inline ostream& operator<<(ostream& out, const Sales_item& s)
{
	out << s.isbn << "\t" << s.units_sold << "\t" << s.revenue << "\t" << s.avg_price();
	return out;
}
inline double Sales_item::avg_price() const
{
	if (units_sold)
		return revenue / units_sold;
	else
		return 0;
}
#endif

主函数

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

int main(int argc, char** argv)
{
    Sales_item item;
    while (std::cin >> item)
        std::cout << item << std::endl;
    getchar();
    return 0;
}

1.6书店程序

读取销售记录,生成每本书销售报告,显示售出册数、总销售额、平均售价。

#include <iostream>
#include "Sales_item.h" 
int main()
{
	Sales_item total;
	if (std::cin >> total)
	{
		Sales_item trans;
		while (std::cin >> trans)
		{
			if (total.isbn == trans.isbn)
				total += trans;
			else 
			{
				std::cout << total << std::endl;
				total = trans;
			}
		}
		std::cout << total << std::endl;
	}
	else
	{
		std::cerr << "No date!" << std::endl;
		return -1;
	}
	return 0;
}

二、变量和基本类型

2.1基本内置类型

1.选择类型

1.long一般与int有一样的尺寸,

2.算数表达式不用char或bool,存放字符或布尔值时才使用,因为char的有无符号与机器有关系;

3.一般用double,因为与float比精度高,但计算代价小,long double 运行消耗不容忽视。

2.类型转换

1.对无符号的类型一个超出范围的值,则为该值对无符号数取模的余数

2.注意无符号类型做循环时,负数的取余行为导致的死循环。

3.字面值常量、转义序列

1.指定字面值类型,前后缀的使用表2.2

前缀:u                 unicode16字符

            U                 unicode32字符

            L                  宽字符

            u8               utf-8

后缀:u或U    表示该字面值为无符号类型

             l或L     表示该字面值的类型至少为long

             ll或LL   表示该字面值的类型至少为long long 

             f或F      表示该字面值为float类型

前后缀可以交叉结合使用:后缀UL时,表示无符号长整型。

字符用单引号‘’,字符串用双引号“”。

十进制:20   八进制:020    十六进制:0x20或者0X20

2.2变量

1.初始化与赋值的不同之处

2.声明与定义的区别:

声明一个变量而非定义它 ,在变量名前添加关键字extern;

2.3复合类型

一条声明语句由一个基本数据类型和一个声明符号列表组成。

2.3.1引用(别名)

定义:int i = 2;    int &g = i;

必须初始化,且是绑定对象的别名,不能引用引用,不能与字面值或表达式的计算结构绑定;

2.3.2指针

double dval;

double *pd=&daval;//指向double类型对象的地址

1.*解引用符,得出所指的对象

2.空指针 int*p=nullptr;或0;或NULL;

3.任何非0指针指向的条件值都是true;

4.void*指针:存放一个地址,对地址到底是什么类型的变量不了解,之后继续会讲到。

2.3.3符合类型的声明

类型修饰符只是声明的一部分:

int i=1024,*p=&i,&r=i;

1.可以有指向指针的指针,可以多次解引用,如**ppi和***pppi;

2.可以有指针的引用,反过来不行,如 int *&r=p;

2.4const限定符

1const对象必须初始化,对象只在文件内有效,多文件内可以独立定义。

2.需要在多文件中共享时,用extern关键字

extern const int bufSize;

2.4.1const的引用

const int ci=1024;

const int &r1=ci;

1.作为“常量的引用”,不能修改所绑定的对象,

2.初始化常量引用时允许用任意表达式作为初始值,只要表达式能转换成引用的类型即可。

int i=42;

const int &r1=i;

const int &r2=r1*2;//r2是一个常量引用

3.可以绑定到另外一个类型上:

double dval=3.14;

const int &ri =dval;

4.const引用可能引用一个非常量、字面值、一般表达式,可以通过其他途径改变值,但是普通的引用不能绑定到const引用上;

int i=42;

int &r1=i;

const int &r2=i;//可以引用非常量

5.不能用非常量引用来引用const常量;

const int g=10;

int %r3=g;

2.4.2指针和const

1.指向常量的指针:用法与const引用差不多;

//指向常量的指针可以指向一个非常量对象

double dval =3.14;

const double *cptr=&dval; //指向常量的指针可以指向一个非常量对象

2.常量指针

1.必须初始化,且不再改变,即存储的地址不在变,但是指向对象的内容可以根据对象的类型进行修改。

int errNumb = 0;
int* const curErr = &errNumb;
const double pi=3.14159;
const double *const pip=&pi;//pip是一个指向常量对象的常量指针

通过从右向左阅读,搞清楚声明的含义

2.4.3顶层const

1.顶层const可以表示任意的对象是常量,底层const则与指针和引用等复合类型的基本类型有关。

2.指针可以使顶层也可以是底层const,

const int * const p3=p2;//第一个是底层const,第二个是顶层const;

3.拷贝对象时,顶层const不受影响,底层const

考虑时,可以不在乎顶层const,但是必须清楚指向的对象是常量。p58页此处比较饶,需要分清楚多看几次。

2.4.4constexpr和常量表达式

1.不会改变并且在编译过程就能得到计算结果的表达式,const对象、字面值都是。

2.将变量声明为constexpr类型,一定是常量,而且必须用常量表达式初始化;

3.字面值类型;

4.constexpr声明如果定义一个指针,则对指针有效,所指对象无关

constexpr int *p=nullptr;//用contexpr将q置为顶层const

2.5处理类型

2.5.1类型别名

1.传统方法:typedef double wages

新标准规定:using SI=Sales_item;

2.定义复合类型或常量时多注意:typedef char *pstring;是将char*取别名pstring。

2.5.2auto类型说明符

编译器根据初始值来推算变量的类型。

auto item = val1+val2;//0.必须有初始值,且一条语句中所有变量的初始基本数据类型都必须一样。

1.编译器将引用对象的类型(与decltype不同)作为auto的类型

2.auto一般会忽略顶层const,保留底层const

3.如果需要推断出的auto类型是顶层const,则需要明确指出

const auto f=ci;ci为int类型, f为const int类型

4.将引用类型设为auto,则原来的初始化规则仍然适用。

5.切记,符号*和&只从属于某个声明,而非基本数据类型的一部分,因此初始值必须是同一类型:

auto k = ci, &l = i; // k是整数,l是整型引用
auto &m = ci, *p = &ci; // m是对整型常量的引用,p是指向整型常量的指针
auto &n = i, *p2 = &ci; // Error: i的类型是int,而&ci的类型是const int

2.5.3decltype类型指示符

选择并返回操作数的数据类型

decltype(fun())   sum = x;     //将fun()的返回值类型作为sum的类型

1.如果decltype适用的表达式是一个变量,则decltype返回该变量的类型(包括顶层const和引用在内)

注意:返回的类型为引用类型时,用于定义变量需要初始化!

2.如果返回的表达式不是一个变量,则decltype返回表达式结果对应的类型

int i=42,*p=&i,&r=i;

decltype (r+0)  b;//满足2为int

decltype(*p) c;//满足1,解引用操作*p,则返回类型为int&,此处错误

3.decltype的表达式多加了一层括号的变量,结果将是永远是引用!!!

decltype ((i)) d;//d是int &,必须初始化,此处错误

decltype (i)  d;//int

赋值的表达式语句本身是一种引用

decltype(a=b)d=a;

decltype与auto主要的区别有两点:

1:如果使用引用类型,auto会识别为其所指对象的类型,decltype则会识别为引用的类型。

2:decltype(())双括号的差别。

2.6自定义数据类型

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值