版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/CV2017/article/details/82624800
开发环境及工具:win7 + vs2010
如果有错误或者更好的写法,互相学习交流,微信号:WangXinBoy09
日常更新,慢慢来,别急
目录
第一章 开始
联系1.1 和 1.2 不会弄,1.2 写了一个看不到效果
//练习1.3 1.4 1.5
#include <iostream>
using namespace std;
int main()
{
int iNumberA = 5;
int iNumberB = 8;
cout << "HelloWorld" << endl;
cout << "iNumberA * iNumberB = " << iNumberA * iNumberB << endl;
cout << "The city is ";
cout << "HangZhou or ChengDu";
return 0;
}
//练习1.7
#include <iostream>
using namespace std;
int main()
{
int iNumberA = 5;
int iNumberB = 8;
cout << "HelloWorld" << endl;
cout << "iNumberA * iNumberB = " << iNumberA * iNumberB << endl;
/*cout << "The city is ";
cout << "beautiful"; /* 注释界定符不能嵌套*/
cout << "HangZhou or ChengDu";*/
return 0;
}
//练习1.8
#include <iostream>
using namespace std;
int main()
{
cout << "/*";// 在cout中的 " "内将其作为字符处理,/* */分别单独出现在两行不会将之间的内容注释
cout << "*/";
cout << /* "*/" */"; //在这一行的分号前多加了一个引号,跟书上不同,可以对比看出,/* */成对出现在一行会将之间的内容注释
cout << /* "*/" /* "/*" */;
return 0;
}
//练习1.9
#include <iostream>
using namespace std;
int main()
{
int iSum = 0; //iSum 和 iNumber 为两个局部变量
int iNumber = 50;
while (iNumber <= 100)
{
iSum += iNumber;
iNumber++;
}
cout << "iSum = " << iSum;
return 0;
}
//练习1.10
#include <iostream>
using namespace std;
int main()
{
int iNumber = 10;
while (iNumber >= 0)
{
cout << iNumber << " ";
iNumber--;
}
return 0;
}
//练习1.11
#include <iostream>
using namespace std;
int main()
{
int iNumA = 0;
int iNumB = 0;
cout << "请输入两个整数:" << endl;
cin >> iNumA >> iNumB;
while (iNumA < iNumB)
{
if (iNumA == iNumB - 1)
{
break;
}
else
{
cout << iNumA + 1 << " ";
iNumA++;
}
}
while (iNumA > iNumB)
{
if (iNumB == iNumA - 1)
{
break;
}
else
{
cout << iNumA - 1 << " ";
iNumA--;
}
}
return 0;
}
//练习1.13
#include <iostream>
using namespace std;
int main()
{
//1.9
int iSum = 0; //iSum 和 iNumber 为两个局部变量
for (int iNumber = 50; iNumber <= 100; iNumber++)
{
iSum += iNumber;
}
cout << "iSum = " << iSum <<endl;
//1.10
for (int iNumber = 10; iNumber >= 0; iNumber--)
{
cout << iNumber << " ";
}
cout << endl;
//1.11
int iNumA = 0;
int iNumB = 0;
cout << "请输入两个整数:" << endl;
cin >> iNumA >> iNumB;
for (;iNumA < iNumB;)
{
if (iNumA == iNumB - 1)
{
break;
}
else
{
cout << iNumA + 1 << " ";
iNumA++;
}
}
for (;iNumA > iNumB;)
{
if (iNumB == iNumA - 1)
{
break;
}
else
{
cout << iNumA - 1 << " ";
iNumA--;
}
}
return 0;
}
//练习1.16
#include <iostream>
using namespace std;
//运行此程序看到结果需要在输入一组数后,先按ctrl + Z,再按 Enter
int main()
{
int iSum = 0;
int iNumber = 0;
cout << "请输入一组数: " << endl;
while (cin >> iNumber)
{
iSum += iNumber;
}
cout << "iSum = " << iSum << endl;
return 0;
}
//统计连续输入一组数,每个数出现了几次
#include <iostream>
using namespace std;
int main()
{
int iCurrVal = 0;
int iVal = 0;
cout << "请输入一组数: " << endl;
if (cin >> iCurrVal)
{
int iCount = 1;
while (cin >> iVal)
{
if (iVal == iCurrVal)
{
++iCount;
}
else
{
cout << iCurrVal << " occurs " << iCount << " times " << endl;
iCurrVal = iVal;
iCount = 1;
}
}
cout << iCurrVal << " occurs " << iCount << " times " << endl;
}
return 0;
}
//练习1.20 第一种写法
#include <iostream>
#include "Sales_item.h"
using namespace std;
int main()
{
Sales_item book1,book2,book3;
cout << "请输入书的ISBN号、售出的册数以及销售价格:" << endl;
cin >> book1 >> book2 >> book3;
cout << book1 << endl;
cout << book2 << endl;
cout << book3 << endl;
return 0;
}
//练习1.20 第二种写法
#include <iostream>
#include "Sales_item.h"
using namespace std;
int main()
{
Sales_item book;
cout << "请输入书的ISBN号、售出的册数以及销售价格:" << endl;
while (cin >> book)
{
cout << "书的ISBN号、售出的册数、销售总价及平均价格:" << book << endl;
}
return 0;
}
//练习1.21 自己写的
#include <iostream>
#include "Sales_item.h"
using namespace std;
int main()
{
Sales_item book1,book2;
cout << "请输入书的ISBN号、售出的册数以及销售价格:" << endl;
cin >> book1 >> book2;
cout << "书的ISBN号、售出的册数、销售总价及平均价格:" << book1 + book2 << endl;
return 0;
}
//练习1.21 标准答案
#include <iostream>
#include "Sales_item.h"
using namespace std;
int main()
{
Sales_item book1,book2;
cout << "请输入两条ISBN相同的销售记录:" << endl;
cin >> book1 >> book2;
if (compareIsbn(book1,book2))
{
cout << "书的ISBN号、售出的册数、销售总价及平均价格:" << book1 + book2 << endl;
}
else
{
cout << "两条销售记录的ISBN不同" << endl;
}
return 0;
}
//练习1.22
#include <iostream>
#include "Sales_item.h"
using namespace std;
int main()
{
Sales_item total,trans;
cout << "请输入几条ISBN相同的销售记录:" << endl;
if (cin >> total)
{
while (cin >> trans)
{
if (compareIsbn(total,trans))
{
total = total + trans;
}
else
{
cout << "两条销售记录的ISBN不同" << endl;
return -1;
}
}
cout << "书的ISBN号、售出的册数、销售总价及平均价格:" << total << endl;
}
else
{
cout << "没有数据" << endl;
return -1;
}
return 0;
}
//练习1.23
#include <iostream>
#include "Sales_item.h"
using namespace std;
int main()
{
Sales_item trans1,trans2;
int iCount = 0;
cout << "请输入几条ISBN相同的销售记录:" << endl;
if (cin >> trans1)
{
iCount = 1;
while (cin >> trans2)
{
if (compareIsbn(trans1,trans2))
{
iCount++;
}
else
{
cout << "ISBN:" << trans1.isbn() << "有 " << iCount << " 条销售记录" << endl;
trans1 = trans2;
iCount = 1;
}
}
cout << "ISBN:" << trans1.isbn() << "有 " << iCount << " 条销售记录" << endl;
}
else
{
cout << "没有数据" << endl;
return -1;
}
return 0;
}
//练习1.24代码同1.23
//练习1.25 书店程序
#include <iostream>
#include "Sales_item.h"
using namespace std;
int main()
{
Sales_item total,trans;
cout << "请输入几条ISBN相同的销售记录:" << endl;
if (cin >> total)
{
while (cin >> trans)
{
if (compareIsbn(total,trans))
{
total += trans;
}
else
{
cout << total << endl;
total = trans;
}
}
cout << total << endl;
}
else
{
cout << "没有数据" << endl;
return -1;
}
return 0;
}
第二章 变量和基本类型
//练习2.1
short 是 2 字节,int 、long 都是 4 字节,long long 是 8 字节
无符号类型的数没有符号位,必须大于等于 0,带符号类型数的第一位为 0 表示正数,1 表示负数,带符号类型可以表示正数、负数或 0
float 是 4 字节,有效位数为 7 位,double 是 8 字节,有效位数为 16 位
//练习2.2
因为利率、本金、付款都可能是有几位小数的,均用 double 类型
//练习2.3
32
-32 + 4294967296 = 4294967264
32
-32
0
0
//练习2.4
#include <iostream>
using namespace std;
int main()
{
unsigned u = 10, u2 = 42;
cout << u2 - u << endl;
cout << u - u2 << endl;
int i = 10, i2 = 42;
cout << i2 - i << endl;
cout << i - i2 << endl;
cout << i - u << endl;
cout << u - i << endl;
return 0;
}
//练习2.5
'a' 表示字符 a,L'a' 表示宽字符型字面值 a 且类型是 wchar_t,"a" 表示字符串 a,L"a" 表示宽字符型字符串 a
10 是普通整数,10u 表示一个无符号数,10L 表示一个长整型数,10uL 表示一个无符号长整型数,012 表示一个八进制数,0xC 表示十六进制数(12)
3.14 是普通浮点类型字面值,3.14f 表示 float 类型单精度,3.14L 表示 long double 类型的扩展精度浮点数
10 普通整数,10u 无符号整数,10. 是一个浮点数,10e-2 科学计数法表示的浮点数,大小为 10*10^-2 = 0.1
//练习2.6
第一组正确,第二组报错,因为 0 开头表示八进制数,9 显然超过了范围
//练习2.7
转义序列
31.4
1024.f
long double 扩展精度浮点数
//练习2.8
#include <iostream>
using namespace std;
int main()
{
cout << "2M\n";
cout << "2\t\M" << endl;
return 0;
}
//练习2.9
在输入流中定义,输入运算符右边需要一个明确的变量名称
列表初始化中值的损失,导致出错
声明多个变量时,需要用逗号将其分开
double salary, wage;
salary = wage = 9999.99;
cout << "salary = " << salary << endl;
cout << "wage = " << wage << endl;
int i = 3.14, i 的值会为 3,精度损失,不建议这样写
//练习2.10
global_str 为空字符串,global_int 为 0
local_int 的值是未定义,如果使用会遇到未定义的奇异值,local_str 空字符串
string 类型的变量接收无参数的初始化方式,不论变量定义在函数内还是函数外都被默认初始化为空串
//练习2.11
因为有初始化了,所以是定义
声明并定义
声明
//练习2.12
double 是关键字,不能用作变量名
b 合法
- 非法
不能以数字开头
e 合法,大写D开头,跟double有区别,可以滴
//练习2.13
j = 100,第一个 i 为全局变量,在 main 函数内重定义同名局部变量 i ,然后用局部变量 i 的值初始化j
//练习2.14
100 45
for 循环之外为外层作用域,for 循环内的 i 重新定义了 i ,那么这个局部变量 i 值只在 for 循环内有效,所以在输出时的 i 值是外层作用域的 i = 100,内层没有重新定义 sum,因此 sum 的初始值是 0 并在此基础上依次累加,变成了 45
//练习2.15
合法
非法,引用只能绑定对象,不能与字面值绑定在一起
合法,引用绑定对象,并且类型也匹配
非法,引用没有初始化
//练习2.16
合法,为引用赋值实际上是把值赋给了与引用绑定的对象
合法,以引用作为初始值实际上是以引用绑定的对象作为初始值
合法,双精度数转换成整数,窄化操作
合法
//练习2.17
10 10
引用不是对象,是为已经存在的对象起了另外一个名字,因此更新后的值是 10,输出结果是一样的
//练习2.18
#include <iostream>
using namespace std;
int main()
{
int* p = nullptr;
int iNum = 5;
cout << "指针 p 的初始值为:" << p << endl;
p = &iNum;
cout << "修改后指针 p 的值为:" << p << endl;
cout << "修改前 p 所指对象的值:" << *p << endl;
*p = 10; //显式地更改指针 p 所指的内容
cout << "修改指针指向对象的值后,指针 p 的值为:" << p << endl;
cout << "修改指针指向对象的值后,指针 p 所指对象的值为:" << *p << endl;
cout << "修改指针指向对象的值后,指针 p 所指对象本身的值 iNum 为:" << iNum << endl;
iNum = 10; //与 *p = 10 效果相同
return 0;
}
//练习2.19
指针和引用同为复合类型,都与内存中实际存在的对象有联系,指针指向内存中的某个对象,引用绑定到内存中的某个对象,他们都实现了对其他对象的间接访问
指针是一个对象,可以进行赋值和拷贝,在指针的生命周期内,可以指向几个不同的对象;引用不是一个对象,无法令引用重新绑定到另外一个对象
指针无须在定义时赋初值,和其他内置类型一样,在块作用域内定义的指针如果没有被初始化,也将拥有一个不确定的值;引用则必须在定义时赋初值
//练习2.22
if(p) 指针本身的值作为判断条件,若指针为空,则为 false,若指针指向一个真实存在的变量,则为 true
if(*p) 指针指向的内容作为判断条件,指针所指的内容为 0,则为 false,如果不为 0,则为 true
//练习2.24
因为lp的类型不是int,而void*定义了一个空指针,可以接受任意类型的对象
//练习2.35
#include <iostream>
using namespace std;
int main()
{
const int i = 42;
auto j = i;
const auto &k = i; //错误
auto *p = &i;
const auto j2 = i, &k2 = i;
cout << typeid(i).name() << endl;
cout << typeid(j).name() << endl;
cout << typeid(k).name() << endl;
cout << typeid(p).name() << endl;
cout << typeid(j2).name() << endl;
cout << typeid(k2).name() << endl;
return 0;
}
//练习2.36
a int, b int, c int, d int&
//练习2.38
auto 和 decltype 是两种类型推断的方式,auto 和 decltype 的区别主要有以下三个方面:
第一,auto 类型说明符用编译器计算变量的初始值来推断其类型,而 decltype 虽然也让编译器分析表达式并得到它的类型,但是不实际计算表达式的值
第二,编译器推断出来的 auto 类型有时候和初始值的类型并不完全一样,编译器会适当地改变结果类型使其更符合初始化规则,例如 auto 一般会忽略顶层 const,而把底层 const 保留下来,decltype 会保留变量的顶层 const
第三,与 auto 不同,decltype 的结果类型与表达式形式密切相关,如果变量名加上了一对括号,则得到的类型与不加括号时会有所不同,如果 decltype 使用的是一个不加括号的变量,则得到的结果是该变量的类型,如果给变量加上了一层或多层括号,则编译器将推断得到引用类型
#include <iostream>
#include <typeinfo>
using namespace std;
int main()
{
int a = 3;
auto c1 = a;
decltype(a) c2 = a;
decltype((a)) c3 = a;
const int d = 5;
auto f1 = d;
decltype(d) f2 = d;
cout << typeid(c1).name() << endl;
cout << typeid(c2).name() << endl;
cout << typeid(c3).name() << endl;
cout << typeid(f1).name() << endl;
cout << typeid(f2).name() << endl;
c1++;
c2++;
c3++;
f1++;
// f2++; //错误:f2 是整型常量,不能执行自增操作
cout << "a = " << a << " " << "c1 = " << c1 << " " << "c2 = " << c2 << " " << "c3 = " << c3 << ""
" " << "f1 = " << f1 << " " << "f2 = " << f2 << endl;
return 0;
}
//练习2.39
Foo 后面接 int 是非法的
//练习2.40
struct Sales_data
{
string bookNo; //书籍编号
unsigned units_sold = 0; //销售量
double sellingprice = 0.0; //零售价
double saleprice = 0.0; //实售价
double discount = 0.0; //折扣
};
//练习2.41
不会
//练习2.42
不会
第三章 字符串、向量和数组
//练习3.2
//从标准输入中一次读入一行
#include <iostream>
#include "Sales_item.h"
using namespace std;
int main()
{
string line;
while (getline(cin, line))
{
if (!line.empty())
{
cout << line << endl;
}
}
return 0;
}
//从标准输入中一次读入一个词
#include <iostream>
#include "Sales_item.h"
using namespace std;
int main()
{
string word;
while (cin >> word)
{
if (!word.empty())
{
cout << word << endl;
}
}
return 0;
}
//练习3.3
标准库 string 类的运算符自动忽略字符串开头的空白(包括空格符、换行符、制表符等),从第一个真正的字符开始读起,直到遇到下一处空白为止
#include <iostream>
#include <string>
#include "Sales_item.h"
using namespace std;
int main()
{
string word, line;
cout << "请选择读取字符串的方式:1 表示逐词读取,2 表示整行读取" << endl;
char ch;
char cInput;
cin >> ch;
if (ch == '1')
{
cout << "请输入字符串:Welcome to C++ family! " << endl;
cin >> word;
cout << "系统读取的有效字符是:" << endl;
cout << word << endl;
return 0;
}
//清空缓冲区
cin.clear(); //让错误标识改回为 0,让我们可以继续输入
cin.sync(); //清空流数据,继续输入
if (ch == '2')
{
cout << "请输入字符串:Welcome to C++ family! " << endl;
getline(cin, line);
cout << "系统读取的有效字符串是:" << endl;
cout << line << endl;
return 0;
}
cout << "你的输入有误!";
return -1;
}
//练习3.4
//比较两个字符串是否相等,不等的话输出较大的那个字符串
#include <iostream>
#include <string>
#include "Sales_item.h"
using namespace std;
int main()
{
string s1, s2;
cout << "请输入两个字符串:" << endl;
cin >> s1 >> s2;
if (s1 == s2)
{
cout << "两个字符串相等" << endl;
return 0;
}
else if (s1 > s2)
{
cout << "s1 > s2" << endl;
}
else
{
cout << "s1 < s2" << endl;
}
return 0;
}
//比较比较两个字符串是否等长,如果不等长,输出长度较大的那个字符串
#include <iostream>
#include <string>
#include "Sales_item.h"
using namespace std;
int main()
{
string s1, s2;
cout << "请输入两个字符串:" << endl;
cin >> s1 >> s2;
if (s1.size() == s2.size())
{
cout << "两个字符串长度相等" << endl;
return 0;
}
else if (s1.size() > s2.size())
{
cout << "s1的长度 > s2的长度" << endl;
return 0;
}
else
{
cout << "s1的长度 < s2的长度" << endl;
return 0;
}
return 0;
}
//练习3.6 因为VS2010,不支持C++11标准的范围for循环,所以这里用for循环代替
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "0123456789ABCDEF";
cout << "改变前的s = " << s << endl;
decltype(s.size()) n = 0;
for (; n < s.size(); n++)
{
s[n] = 'X';
}
cout << "Your hex number is:" << s << endl;
return 0;
}
//3.8
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "0123456789ABCDEF";
cout << "改变前的s = " << s << endl;
decltype(s.size()) n = 0;
while (n <= s.size())
{
s[n] = 'X';
n++;
}
cout << "Your hex number is:" << s << endl;
return 0;
}
for循环看起来更简洁明了
//3.10
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s, result;
cout << "读入一个包含标点符号的字符串:" << endl;
getline(cin, s);
decltype(s.size()) n = 0;
while (n < s.size())
{
if (!ispunct(s[n]))
{
result += s[n];
}
n++;
}
cout << "将标点删除后输出字符串剩下的部分:" << result << endl;
return 0;
}
第 七 章 类
//练习7.11
sales_data add(const sales_data &lhs, sales_data &rhs)
{
sales_data sum = lhs;
sum.combine(rhs);
return sum;
}
iostream &read(istream &is, sales_data &item)
{
is >> item.bookNo >> item.units_sold >> price;
item.revenue = price * item.units_sold;
return is;
}
ostream &print(ostream &os, const sales_data &item)
{
os << item.isbn() << " " << item.units_sold << " "
<< item.revenue << " " << item.avg_price();
}
//练习7.7
#include <iostream>
#include "Sales_data.h"
#include <string>
using namespace std;
int main()
{
cout << "请输入交易记录(ISBN、销售量、原价、实际售价):" << endl;
sales_data total;
//读入第一条交易记录,并确保有数据可以处理
if (read(cin, total))
{
sales_data trans;
while (read(cin, total))
{
if (total.isbn() == trans.isbn())
{
total = add(total, trans);
}
else
{
print(cout, total);
cout << endl;
total = trans;
}
}
print(cout, total);
cout << endl;
}
else
{
//没有输入!警告读者
cerr << "No data?!" << endl;
return -1;
}
return 0;
}
//练习7.8
read 函数将其 sales_data 参数定义成普通的引用是因为我们需要从标准输入流中读取数据并将其写入到给定的 sales_data 对象,因此需要有修改对象的权利,而 print 将其参数定义成常量引用是因为它只负责数据的输出,不对其做任何更改
//练习7.9
sales_data add(const sales_data &lhs, sales_data &rhs)
{
sales_data sum = lhs;
sum.combine(rhs);
return sum;
}
istream &read(istream &is, Person &per)
{
is >> per.strName >> per.strAddress;
return is;
}
ostream &print(ostream &os, const Person &per)
{
os << per.getName() << per.getAddress();
return os;
}
//练习7.10
因为 read 函数的返回类型是引用,所以 read(cin, data1) 的返回值可以继续作为外层 read 函数的实参使用,该条件检验读入 data1 和 data2 的过程是否正确,如果正确,条件满足;否则条件不满足
//练习7.11
//头文件
#ifndef Sales_data_h
#define Sales_data_h
#include <string>
#include <iostream>
struct Sales_data
{
Sales_data() = default;
Sales_data(const std::string &s) :bookNo(s) {}
Sales_data(const std::string &s, unsigned n, double p) :bookNo(s), units_sold(n), revenue(n*p) {}
Sales_data(std::istream &is);
std::string isbn() const { return bookNo; };
Sales_data& combine(const Sales_data&);
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
std::istream &read(std::istream &is, Sales_data &item)
{
double price = 0;
is >> item.bookNo >> item.units_sold >> price;
item.revenue = price * item.units_sold;
return is;
}
std::ostream &print(std::ostream &os, const Sales_data &item)
{
os << item.isbn() << " " << item.units_sold << " " << item.revenue;
return os;
}
Sales_data add(const Sales_data &lhs, const Sales_data &rhs)
{
Sales_data sum = lhs;
sum.combine(rhs);
return sum;
}
Sales_data::Sales_data(std::istream &is)
{
read(is, *this);
}
Sales_data& Sales_data::combine(const Sales_data& rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
#endif /* Sales_data_h */
//main.cpp
#include <iostream>
#include "Sales_data.h"
//using namespace std;
int main(int argc, const char * argv[]) {
Sales_data item1;
print(std::cout, item1) << std::endl;
Sales_data item2("0-201-78345-X");
print(std::cout, item2) << std::endl;
Sales_data item3("0-201-78345-X", 3, 20.00);
print(std::cout, item3) << std::endl;
Sales_data item4(std::cin);
print(std::cout, item4) << std::endl;
return 0;
}
//练习7.12
struct Sales_data
{
Sales_data() = default;
Sales_data(const std::string &s) :bookNo(s) {}
Sales_data(const std::string &s, unsigned n, double p) :bookNo(s), units_sold(n), revenue(n*p) {}
Sales_data(std::istream &is) { is >> *this };
std::string isbn() const { return bookNo; };
Sales_data& combine(const Sales_data&);
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
//练习7.15
class Sales_data
{
private:
string strName;
string strAddress;
public:
Person() = default;
Person(const string &name, const string &add)
{
strName = name;
strAddress = add;
}
Person(istream &is) { is >> *this; }
public:
string getName() const {return strName;}
string getAddress() const {return strAddress;}
};
//练习7.20
友元为类的非成员接口函数提供了访问其私有成员变量的能力,友元可能会破坏类的封装性
//练习7.22
隐藏细节的含义是指把 Person 类的数据成员以及不应该被外部访问的函数成员设置成 Private,把数据成员设置为 private 来确保类的封装性
//练习7.23