Cpp primer plus notes ch2&&ch3
Cpp primer plus notes
ch2. get start
include 预处理器编译指令。
using namespace 编译指令。
void关键字显示说明不接受任何参数。
//myfirst.cpp
#include <iostream>
int main(void)
{
using namespace std;
cout << "Come up and c++ me some time.";// << : 为插入运算符,将字符串插入到输出流当中. [cout对象]
cout << endl;
cout << "You won't regret it!" << endl;
return 0;
}
// << 运算符被重载, 同一个符号可能有多重含义,编译器根据上下文确定其具体功能.
// endl 是C++ 的特殊符号. 控制符:重启一行.在iostream中定义 位于std namespace中. [ manipulator ] 等同于:\n
// 差别在于endl保证程序继续运行前刷新输出, 使用\n不能保证.
main函数被启动代码调用,启动代码是编译器添加到程序中的。在C语言中main()函数省略返回值类型,默认是返回int,在C++中弃用了这种用法,显式声明。
// cpp的输入输出工具, 需要包含如下两行代码 cin cout包含在iostream中.
// 预处理指令作用: 将iostream文件内容添加到程序中; 在源码编译之前,添加或者替换文本.
#include <iostream>
using namespace std;
#include <iostream>
int main()
{
using namespace std;
int carrots; // 变量声明 指定变量类型和存储名称. defining declaration == definition编译器会为该变量分配内存空间 C++首次使用前声明
carrots = 25;
cout << "I have ";
cout << carrots;
cout << " carrots.";
cout << endl;
carrots = carrots - 1;
cout << "Crunch, crunch. Now I have " << carrots << " carrots." << endl;
return 0;
}
#include <iostream>
int main()
{
using namespace std;
int carrots;
cout << "How many carrots do you have?" << endl;
cin >> carrots; // cin也是一个智能对象 需要右侧提供一个变量抽取信息
cout << "Here are two more. ";
carrots += 2;
cout << "Noew you have " << carrots << " carrots." << endl;
return 0;
}
// cin 是 istream类对象 也是在iostream中定义的.
在使用函数之前C++必须知道函数的参数类型和返回值类型.
#include <iostream>
#include <cmath>
int main()
{
using namespace std;
double area;
cout << "Enter the floor area, in square feet, of your home: ";
cin >> area;
double side;
side = sqrt(area);
cout << "That's the equivalent of a square " << side
<< " feet to the side." << endl;
cout << "How fascinating!" << endl;
return 0;
}
#include <iostream>
void simon(int);
int main()
{
using namespace std;
simon(3);
cout << "Pick an integer: ";
int count;
cin >> count;
simon(count);
cout << "Done!" << endl;
return 0;
}
void simon(int n)
{
using namespace std;
cout << "Simon says touch your toes " << n << " times" << endl;
}
#include <iostream>
int stonetolb(int);
int main()
{
using namespace std;
int stone;
cout << "Enter the weight in stone: ";
cin >> stone; // >> 抽取运算符
int pounds = stonetolb(stone);
cout << stone << " stone = ";
cout << pounds << " pounds." << endl;
return 0;
}
int stonetolb(int sts)
{
return 14 * sts;
}
ch3. 处理数据
变量名: 精确,统一.
ANSI C99变量名63个字符长度;
整型:char、 short(至少16bit) 、int、 long(至少32bit) 、long long(至少64bit c++11)
sizeof运算符获取变量位宽. 单位字节.
#define 也是预处理器编译指令
#include <iostream>
#include <climits>
int main()
{
using namespace std;
int n_int = INT_MAX;
short n_short = SHRT_MAX;
long n_long = LONG_MAX;
long long n_llong = LLONG_MAX;
cout << "int is " << sizeof(int) << " bytes." << endl;
cout << "short is " << sizeof n_short << " bytes." << endl;
cout << "long is " << sizeof n_long << " buyes." << endl;
cout << "long long is " << sizeof n_llong << " bytes." << endl;
cout << "Maximum values:" << endl;
cout << "int: " << n_int << endl;
cout << "short: " << n_short << endl;
cout << "long: " << n_long << endl;
cout << "long long: " << n_llong << endl << endl;
cout << "Mimium int value = " << INT_MIN << endl;
cout << "Bits per byte = " << CHAR_BIT << endl;
return 0;
}
// sizeof的运算符. 对于变量来说括号()是可选的 !
C++初始化语法
int wrens(423); // int wrens = 423;
int wrens = {423};
int wrens{423};
int wrens = {}; // 大括号是空的场景,变量将被初始化为0. 【大括号初始化器 ---- 使常规变量与类变量方式更像】
int wrens{};
警告:如果不对函数内部定义的变量进行初始化,该变量的值是不确定的,这意味着该变量的值将是它被创建之前,相应内存单元保存的值.【残留值】
#include <iostream>
#include <climits>
#define ZERO 0
int main()
{
using namespace std;
short sam = SHRT_MAX;
unsigned short sue = sam;
cout << "Sam has " << sam << " dollars and Sue has " << sue;
cout << " dollars deposited." << endl
<< "Add $1 to each account." << endl << "Now ";
sam += 1; // 翻转为负值最小值 -32768
sue += 1;
cout << "Sam has " << sam << " dollars and Sue has " << sue;
cout << " dollars deposites.\nPoor Sam!" << endl;
sam = ZERO;
sue = ZERO;
cout << "Sam has " << sam << " dollars and Sue has " << sue;
cout << " dollars deposites." << endl;
cout << "Take $1 form each account." << endl << "Now ";
sam -=1;
sue -=1; // 翻转为最大值 65535
cout << "Sam has " << sam << " dollars and Sue has " << sue;
cout << " dollars deposites.\nLucky Sue!" << endl;
return 0;
}
[root@localhost cpp]# ./a.out
Sam has 32767 dollars and Sue has 32767 dollars deposited.
Add $1 to each account.
Now Sam has -32768 dollars and Sue has 32768 dollars deposites.
Poor Sam!
Sam has 0 dollars and Sue has 0 dollars deposites.
Take $1 form each account.
Now Sam has -1 dollars and Sue has 65535 dollars deposites.
Lucky Sue!
无论是有符号数还是无符号数,整型最大值和最小值相邻的 +1 -1转换;
对于short 无符号 0 - 1 --> 65535
对于short有符号 32767 + 1 --> -32768 -32768 - 1 --> 32767
注意 上溢和下溢;
自然长度int 如果没有特别理由选择int作为变量类型, 处理效率最高。
//3.3
#include <iostream>
int main()
{
using namespace std;
int chest = 42;
int waist = 0x42;
int inseam = 042;
cout << "Monsieur cuts a striking figure!\n";
cout << "chest = " << chest << " (42 in decimal)\n";
cout << hex; // 改变显示字面值的base 16进制 控制符std::hex 修改显示整数的方式
cout << "waist = " << waist << " (0x42 in hex)\n";
cout << oct; // 改变显示字面值的base 8进制
cout << "inseam = " << inseam << " (042 in octal)\n";
return 0;
}
默认情况下cout以十进制显示整数.
C++如何确定常量类型:
除非有理由存储为其他类型(特殊后缀,数值太大) C++将整形常量存储为int.
//p48 3.5
#include <iostream>
int main()
{
using namespace std;
char ch;
cout << "Enter a characto: " << endl;
cin >> ch;
cout << "Hola! ";
cout << "Thank you fot the " << ch << " charactor." << endl;
return 0;
}
//p49 3.6
#include <iostream>
int main()
{
using namespace std;
char ch = 'M';
int i = ch;
cout << "The ASCII codfe for " << ch << " is " << i << endl;
cout << "Add one to the charactor code : " << endl;
ch += 1;
i = ch;
cout << "The ASCII codfe for " << ch << " is " << i << endl;
cout << "Dispalying char ch using cout.put(ch): ";
cout.put(ch);// 显示 ‘N’
cout.put('!');
cout.put(i); // 显示 ‘N’
cout << endl << "Done" << endl;
return 0;
}
// C++转义序列:
// \n \t \v \b 退格 \r回车 \a振铃 \\ \? \' \"
//p51 3.7
// bondini.cpp
#include <iostream>
int main()
{
using namespace std;
cout << "\aOperation \"HyperHyper\" is now activated!\n";
cout << "Enter your agent code:________\b\b\b\b\b\b\b\b";
long code;
cin >> code;
cout << "\aYou entered " << code << "...\n";
cout << "\aCode verified! Process with Plan Z3!\n";
return 0;
}
char在默认情况下既不是有符号 也不是无符号, 是否有符号由C++实现决定。
宽字符:
wcha_t
wcha_t bob = L'P';
wcout << L"tall" << endl;
C++11新增
char16_t ch16 = u'q'; // 16-bit
char32_t ch32 = U'\U0000222B'; // 32-bit
bool类型 对任何非零的数据都解释为 true
常量 const限定符
const int Months = 12; // 符号常量表示12, 常量被初始化之后值就固定了,编译器不允许修改常量的值。
常量应该在定义的时候进行初始化。
推荐使用 const 替换 #define 原因3点: 指定类型; 作用域限制; 用于更复杂的结构斌量;
C++可以用来声明数组长度;
浮点数 float / double / long double
3.14
314E-2
0.314e12
0.314e+12
表示范围在cfloat中说明
float精度测试
//p57 3.8 floatnum.cpp
#include <iostream>
int main()
{
using namespace std;
cout.setf(ios_base::fixed, ios_base::floatfield); // 禁止 cout 输出删除数字结尾的 0
float tub = 10.0 / 3.0; / flocat C++ 只保证6位有效
double mint = 10.0 / 3.0;
const float million = 1.0e6;
cout << "tub = " << tub;
cout << ", a million tubs = " << million * tub;
cout << ",\nand ten million tubs = ";
cout << 10 * million * tub << endl;
cout << "mint = " << mint << " and a million mints = ";
cout << million * mint << endl;
return 0;
}
// tub = 3.333333, a million tubs = 3333333.250000,
// and ten million tubs = 33333332.000000
// mint = 3.333333 and a million mints = 3333333.333333
// 浮点常量在默认的情况下是double类型
C++变量类型自动转换三种场景:
1.不同种变量类型赋值.
2.表达式中包含不同类型的变量.
3.参数传递给函数.
在计算表达式的时候C++将 bool 、char、 unsigned char、signed char、 shor t转换为 int ==== 整型提升
详细转换规则将 p64 描述;
转换顺序 long double --> double -->float -->int
再整形提升场景-----
两个操作数通符号-----转换为更高级别的类型
两个操作数为 无符号 和有符号 ---- 无符号比有符号级别高,转换为 无符号;
如果有符号数能表示无符号类型的所有可能取值 -----转换为有符号;
其他场景转换为 有符号类型的无符号版本;
传递参数转换
对 char short进行整型提升
对float进行double类型提升 -----兼容C操作的操作(C语言默认将float 提升为double ---- 即使都是float)
static_cast<typeName> (value)
// p66 3.14
#include <iostream>
int main()
{
using namespace std;
int auks, bats, coots;
auks = 19.99 + 11.99;
bats = (int) 19.11 + (int) 11.99;
coots = int (19.99) + int (11.99);
cout << "auks = " << auks << ", bats = " << bats;
cout << ", coots = " << coots << endl;
char ch = 'Z';
cout << "The code for " << ch << " is ";
cout << int(ch) << endl; // int模式输出
cout << "Yes, the code is ";
cout << static_cast<int>(ch) << endl; // int模式输出
return 0;
}
关于C++11 auto 应用场景
std:: vector<double> scores;
auto pv = scores.begin(); // 简化替换原有的 std::<double>::itetator pv = scores.begin();
ch4. 复合类型
数组
// p72 4.1
#include <iostream>
int main()
{
using namespace std;
int yams[3];
yams[0] = 7;
yams[1] = 6;
yams[2] = 8;
int yamcosts[3] = {20, 30, 5};
cout << "Total yums = ";
cout << yams[0] + yams[1] + yams[2] << endl;
cout << "The package with " << yams[1] << " yams costs ";
cout << yamcosts[1] << " cents per yam.\n";
int total = yams[0] * yamcosts[0] + yams[1] * yamcosts[1];
total += yams[2] * yamcosts[2];
cout << "The total yam expense is " << total << " cens.\n";
cout << "Size of yams array = " << sizeof yams; // 数组大小
cout << "bytes.\n";
cout << "Size of one element = " << sizeof yams[0]; // 单元素大小
cout << " bytes.\n";
return 0;
}
// Total yums = 21
// The package with 6 yams costs 30 cents per yam.
// The total yam expense is 360 cens.
// Size of yams array = 12bytes.
// Size of one element = 4 bytes.
数组初始化
long total[500] = {0}; // 部分元素初始化, 其他元素将被编译器初始化为0
C++11可以省去 = 等号
double earnings[4] {1.2e4, 1.6e4, 1.1e4, 1.7e4};
大括号里面不包含任何东西,所有元素将被设置为0;
unsigned int counts[10] = {}; // all elements set to 0
float balance[100] {}; // all elements set to 0
字符串
以空字符 \0 结束的 char数组
char dog[8] = {'b' , 'e', 'a', 'u', 'x', ' ', 'I', 'I'}; // not a string
char cat[8] = {'f' , 'a', 't', 'e', 's', 's', 'a', '\0'}; // a string
字符串常量 字符串字面值:
char birds[11] = "Mr.Cheeps"; // the \0 is understand
char fish[] = "Bubbles"; // let the compiler count
C++对字符串长度没有限制; C++输入工具通过键盘输入,将字符串读到char数组中时,将自动加上结尾的空字符;
// p76 4.2
#include <iostream>
#include <cstring>
int main()
{
using namespace std;
const int Size = 15;
char name1[Size];
char name2[Size] = "C++owboy";
cout << "Howdy! I'm " << name2;
cout << "! What's your name? \n";
cin >> name1; // 读取一个单词. 输入空格 tab enter减会自动截断; 添加结束字符'\n'
// cin.getline(name1, 20); // 最多读取19个字符,将换行符替换为'\0'保存在字符串尾部
cout << "Well, " << name1 << ", your name has ";
cout << strlen(name1) << " letters and is stored\n";
cout << "in an array of " << sizeof name1 << " bytes.\n";
cout << "Your initial is " << name1[0] << ". \n";
name2[3] = '\0';
cout << "Here are the first three characters of my name: ";
cout << name2 << endl;
return 0;
}
getline()
读取行输入,之后去除换行符;
get()
将换行符保留在输入序列中;
get连续调用获取字符会在第二次的时候获取的是换行字符,误认为输入结束可采用get() 形式调用;
cin.get(name, arSize).get();
因为 cin.get返回的是一个cin对象,所以可以调用get成员函数, 进行拼接;
#include <iostream>
int main()
{
using namespace std;
const int ArSize = 20;
char name[ArSize];
char dessert[ArSize];
cout << " Enter your name: \n";
cin.get(name, ArSize).get();
cout << "Enter your favourite dessert:\n";
cin.get(dessert, ArSize).get();
cout << "I have some decilous " << dessert;
cout << " for you, " << name << ".\n";
return 0;
}
关于输入空行处理
当get读取空行后将设置failbit失效位,接下来的输入将被阻断,可以用cin.clear()恢复输入;
如果输入比接收数组长度更长;
getline()和get()将把余下的字符串留在输入队列中,而getline还会设置设置失效位,关闭后面的输入。
// p81 4.6
#include <iostream>
int main()
{
using namespace std;
cout << "What years was your house built?\n";
int year;
(cin >> year).get(); // attention here
cout << "What is its street adress?\n";
char adress[80];
cin.getline(adress, 80);
cout << "Years built: " << year << endl;
cout << "Adress: " << adress << endl;
cout << "Done! \n";
return 0;
}
// p82 4.7#include <iostream>#include <string>int main(){ using namespace std; char charr1[20]; char charr2[20] = "jaguar"; string str1; // 创建空字符串 string str2 = "panther"; // C风格初始化字符串 cout << "Enter a kind of feline : "; cin >> charr1; cout << "Enter another kind of feline: "; cin >> str1; cout << "Here are some felines: \n"; cout << charr1 << " " << charr2 << " " << str1 << " " << str2 << " " << endl; cout << "The third letter in " << charr2 << " is " << charr2[2] << endl; cout << "The third letter in " << str2 << " is " << str2[2] << endl; return 0;}
// p84 4.8#include <iostream>#include <string>int main(){ using namespace std; string s1 = "penguin"; string s2, s3; cout << "You can assign one string object to another: s2 = s1\n"; s2 = s1; cout << "s1: " << s1 << ", s2: " << s2 << endl; cout << "You can assign a C-style string to a string object.\n"; cout << "s2 = \"buzzard\"\n"; s2 = "buzzard"; cout << "s2: " << s2 << endl; cout << "You can concatenate strings: s3 = s1 + s2\n"; s3 = s1 + s2; // string类可以自动调整大小 cout << "s3: " << s3 << endl; cout << "You can append strings.\n"; s1 += s2; cout << "s1 += s2 yields s1 = " << s1 << endl; s2 += " for a day"; cout << "s2 += \" for a day\" yields s2 = " << s2 << endl; return 0;}
// p86 4.10
#include <iostream>
#include <string>
#include <cstring>
int main()
{
using namespace std;
char charr[20];
string str;
cout << "Length of string in charr before input: "
<< strlen(charr) << endl;
cout << "Length of string in str before input: "
<< str.size() << endl;
cout << "Enter a line of text:\n";
cin.getline(charr, 20);
cout << "You entered: " << charr << endl;
cout << "Enter another line of text:\n";
getline(cin, str); // cin不支持string istream不支持string类 类型
cout << "You entered: " << str << endl;
cout << "The length of string in charr after input: "
<< strlen(charr) << endl;
cout << "Length of ttring in str after input: "
<< str.size() << endl;
return 0;
}
cout << R"+*(Jim "King" Tutt uses "\n" instead of endl.)+*" << '\n';
g++ -std=c++11 strtype4.cpp
raw字符串定义需要指定std 为C++11
4.4 结构体
C++允许在声明结构变量的时候省略关键字struct ----与C语言的差别; 通过“.”运算符获取结构体成员。
// p89 4.11
#include <iostream>
struct inflatable
{
char name[20];
float volume;
double price;
};
// 结构体类型变量 支持大括号初始化 "="号可选; 如果大括号是空的{}成员会被初始化为0;
int main()
{
using namespace std;
inflatable guest =
{
"Glorious Gloria",
1.88,
29.99
};
inflatable pal =
{
"Audacious Arthur",
3.12,
32.99
};
cout << "Expand your guest list with " << guest.name;
cout << " and " << pal.name << "!\n";
cout << "You have both for $";
cout << guest.price + pal.price << "!\n";
return 0;
}
结构体变量可以直接相互赋值,对应成员变量会赋值给对应的成员;
结构体定义中的位字段;
struct torgle_register{ unsigned int SN : 4; unsigned int : 4; // 匿名占位,字段对齐使用 bool goodIn : 1; bool goodTorgle : 1;}
共用体union
struct widget{ char brand[20]; int type; union { long id_num; char id_char[20]; } }// 该union 是匿名的 id_num 和id_char被视为两个成员,他们的地址相同.widget var{};var.id_num = 1;
枚举
enum spectrum {red, orange, yellow, green, blue, violet, indigo, ultraviolet}; 枚举常量默认值从0 开始;也可以指定多个值相同的枚举量。
注意枚举强制类型转换的时候,只要整型数值在枚举的范围内,即使该值没有对应的枚举量对应, 转换也不会报错。
指针
//p101 4.16#include <iostream>int main(){ using namespace std; int higgens = 5; int * pt = &higgens; cout << "Value of higgens = " << higgens << "; Address of higgens = " << &higgens << endl; cout << "Value of *pt = " << *pt << "; Value of pt = " << pt << endl; return 0;}
new运算符
new delete运算符
delete用于释放new申请出来的内存,但是不会修改指针变量本身,指针变量还可以指向其他地址.
只能用delete释放new出来的内存, delete 释放 空指针是安全的.
new创建数组
static binding 静态联编
dynamic binding 动态联编
int * psome = new int [10];
delete [] psome;
// p106 4.18#include <iostream>int main(){ using namespace std; double * p3 = new double [3]; p3[0] = 0.2; p3[1] = 0.5; p3[2] = 0.8; cout << "p3[1] is " << p3[1] << ".\n"; p3 = p3 + 1; // 首地址偏移到第二个element cout << "Now p3[0] is " << p3[0] << " and "; cout << "p3[1] is " << p3[1] << ".\n"; p3 = p3 - 1; // 偏移回到原始地址 delete [] p3; return 0;}
//p107 4.19#include <iostream>int main(){ using namespace std; double wages[3] = {10000.0, 20000.0, 30000.0}; short stacks[3] = {3, 2, 1}; double * pw = wages; short * ps = &stacks[0]; cout << "pw = " << pw << ", *pw = " << *pw << endl; pw = pw +1; cout << "Add 1 to pw pointer:\n"; cout << "pw = " << pw << ", *pw = " << *pw << "\n\n"; cout << "ps = " << ps << ", *ps = " << *ps << endl; ps = ps + 1; cout << "add 1 to the ps pointer:\n"; cout << "ps = " << ps << ", *ps = " << *ps << "\n\n"; cout << "access two elements with pointer notation\n"; cout << "stack[0] = " << stacks[0] << ", stack[1] = " << stacks[1] << endl; cout << "Access two elements with pointer notation\n"; cout << "*stacks = " << *stacks << ", *(stacks + 1) = " << *(stacks + 1) << endl; cout << sizeof wages << " = sizeof wages array\n"; cout << sizeof pw << " = size of pw pointer\n"; return 0;}
# 执行结果
[root@localhost cpp]# ./a.out
pw = 0x7ffffcca9700, *pw = 10000
Add 1 to pw pointer:
pw = 0x7ffffcca9708, *pw = 20000
ps = 0x7ffffcca96f0, *ps = 3
add 1 to the ps pointer:
ps = 0x7ffffcca96f2, *ps = 2
access two elements with pointer notation
stack[0] = 3, stack[1] = 2
Access two elements with pointer notation
*stacks = 3, *(stacks + 1) = 2
24 = sizeof wages array
8 = size of pw pointer
数组和指针的为一区别是 指针变量的值可以修改, 而数组名是常量,值不可以修改。
另一个区别 对于sizeof运算符获取的结果不一样; 一个结果是数组长度,一个结果是指针变量的长度。
// p111 4.20
#include <iostream>
#include <cstring>
int main()
{
using namespace std;
char animal[20] = "bear";
const char * bird = "wren";
char * ps;
cout << animal << " and ";
cout << bird << "\n";
cout << "Enter a kind of animal: ";
cin >> animal;
ps = animal;
cout << ps << "!\n";
cout << "Before using strcpy():\n";
cout << animal << " at " << (int *) animal << endl;// 转换为字符串的地址
cout << ps << " at " << (int *) ps << endl;
ps = new char[strlen(animal) + 1];
strcpy(ps, animal);
cout << "After using strcpy():\n";
cout << animal << " at " << (int * ) animal << endl;
cout << ps << " at " << (int *)ps << endl;
delete [] ps;
return 0;
}
如果使用strncpy的话 如果字符串长度未填满,需要手动将尾部字符设置为结束字符.
// p115 4.21
#include <iostream>
struct inflatable
{
char name[20];
float volume;
double price;
};
int main()
{
using namespace std;
inflatable * ps = new inflatable;
cout << "Enter name of inflatable item: ";
cin.get(ps->name, 20);
cout << "Enter volume in cubic feet: ";
cin >> (*ps).volume;
cout << "Enter price: $";
cin >> ps->price;
cout << "Name: " << (*ps).name << endl;
cout << "Volume: " << ps->volume << " cubic feet\n";
cout << "Price: $" << ps->price << endl;
delete ps;
return 0;
}
//p116 4.22#include <iostream>#include <cstring>using namespace std;char * getname(void);int main(){ char * name; name = getname(); cout << name << " at " << (int *) name << "\n"; delete [] name; name = getname(); cout << name << " at " << (int *) name << "\n"; delete [] name; return 0;}char * getname(){ char temp[80]; cout << "Enter last name: "; cin >> temp; char * pn = new char[strlen(temp) + 1]; strcpy(pn, temp); return pn;}
// p119 4.23#include <iostream>struct antarctica_years_end{ int year;};int main(){ antarctica_years_end s01, s02, s03; s01.year = 1998; antarctica_years_end * pa = &s02; pa->year = 1999; antarctica_years_end trio[3]; trio[0].year = 2003; std::cout << trio->year << std::endl; // 指向指针的指针 注意const const antarctica_years_end * arp[3] = { &s01, &s02, &s03}; std::cout << arp[1]->year << std::endl; const antarctica_years_end ** ppa = arp; auto ppb = arp; // 指向指针的指针 auto 自动推导 C++11 std::cout << (*ppa)->year << std::endl; std::cout << (*(ppb + 1))->year << std::endl; return 0;}
数组模板
vector动态数组;分配在堆空间,利用new和delete管理内存;位于std命名空间中,可以通过变量来指定vector元素个数
#include <vector>
using namespace std;
vector<int> vi;
int n;
cin >> n;
vector<double> vd(n);
模板类 array (C++11)
应用于长度固定的数组,比数组更安全,是C++11新增的模板类。array对象的长度是固定,使用的是栈内存空间
#include <array>
using mamespace std;
array<int, 5> ai;
array<souble, 4> ad = {1.2, 2.1, 3.43, 4.3};
//p121 4.24
#include <iostream>
#include <vector>
#include <array>
int main()
{
using namespace std;
double a1[4] = {1.4, 2.4, 3.6, 4.8};
vector<double> a2(4);
a2[0] = 1.0 / 3.0;
a2[1] = 1.0 / 5.0;
a2[2] = 1.0 / 7.0;
a2[3] = 1.0 / 9.0;
array<double, 4> a3 = {3.14, 2.72, 1.62, 1.41};
array<double, 4> a4;
a4 = a3;
cout << "a1[2]: " << a1[2] << " at " << &a1[2] << endl;
cout << "a2[2]: " << a2[2] << " at " << &a2[2] << endl;
cout << "a3[2]: " << a3[2] << " at " << &a3[2] << endl;
cout << "a4[2]: " << a4[2] << " at " << &a4[2] << endl;
a1[-2] = 20.2; // 此处获取 *(a1-2) = 20.2 写到数组外面, 数组空间前面的偏移两个double 8字节 *2
cout << "a1[-2]: " << a1[-2] << " at " << &a1[-2] << " start at " << &a1[0] << " " << &a1[1] << " " << &a1[2] << " " << &a1[3] << endl;
cout << "a1[-1]: " << a1[-1] << " at " << &a1[-1] << " start at " << &a1[-1] << " " << &a1[-2] << " " << &a1[-3] << " " << &a1[-4] << endl;
cout << "a3[2]: " << a3[2] << " at " << &a3[2] << endl;
cout << "a4[2]: " << a4[2] << " at " << &a4[2] << endl;
return 0;
}
为了安全可以使用a2.at(1) = 2.3; 牺牲效率换取安全性;
字符串可用引号括起来的字符串常量表示,其中隐式包含了结尾的空字符串。
ch5. 循环和关系表达式
for 循环三部分; step1 初始化, step2 循环测试:满足条件执行循环体内容, step3: 循环更新;
for (initialization; test-exprerssion; update-expression)
body;
循环只执行一次初始化,测试条件可能包含多个测试表达时;测试表达式决定循环体是否被执行。
每个表达式都有值,C++将赋值表达式定义为左侧成员的值;注意表达式的副作用 side effect。
//p129 5.3
#include <iostream>
int main()
{
using namespace std;
int x;
cout << "The expression x = 100 has the value ";
cout << (x = 100) << endl;
cout << "Now x = " << x << endl;
cout << "The expression x < 3 has the value ";
cout << (x < 3) << endl;
cout << "The expression x > 3 has the value ";
cout << (x > 3) << endl;
cout.setf(ios_base::boolalpha); // 显示布尔值
cout << "The expression x < 3 has the value ";
cout << (x < 3) << endl;
cout << "The expression x > 3 has the value ";
cout << (x > 3) << endl;
return 0;
}
++ 对于类而言,前缀版本和后缀版本细微差异: 后缀版本先复制一个副本之后将其+ 1 ,然后将赋值的副本返回,对于类而言,前缀版本比后缀版本效率高,但是对于内置数据类型,采用那种没有差异;对用户自定义类型,前缀格式效率高。
逗号表达式的值是右侧的值。
cats = 17, 240; 结果: cats=240;
关系运算符比 算术运算符 优先级低;
//p149 5.14
#include <iostream>
#include <ctime>
int main ()
{
using namespace std;
cout << "Enter the delay time, in second: ";
float second;
cin >> second;
clock_t delay = second * CLOCKS_PER_SEC;
cout << "starting\a\n";
clock_t start = clock();
while (clock() - start < delay)
;
cout << "Done \a\n";
return 0;
}
typedef char * byte_pointer
byte_pointer pa, pb;
可以避免这种形式的宏定义带来的歧义,非预期效果。
//p150 5.11
#include <iostream>
int main ()
{
using namespace std;
int n;
cout << "Enter numbers in 1-10 to find :";
cout << "My favourite numbers\n";
do {
cin >> n;
} while ( n != 7);
cout << "Yes, 7 is my favourite.\n";
// C++11
double prices[5] = {4.99, 10.99, 6.87, 7.99, 8.49};
for (double x : prices)
cout << x << endl;
for (double &x : prices)
x = x * 0.8;
for (double x : prices)
cout << x << endl;
for (int x : {3, 5, 2, 8, 6})
cout << x << " ";
cout << endl;
return 0;
}
//p152 5.16
#include <iostream>
int main ()
{
using namespace std;
char ch;
int count = 0;
cout << "Enter characters, enter # to quite:\n";
cin >> ch;
while (ch != '#')
{
cout << ch;
++count;
cin >> ch; //忽略空白字符串 空格制表符等
}
cout << endl << count << " characters read\n";
return 0;
}
//p153 5.17
#include <iostream>
int main ()
{
using namespace std;
char ch;
int count = 0;
cout << "Enter characters, enter # to quite:\n";
// cin >> ch;
cin.get(ch); // 传递引用
while (ch != '#')
{
cout << ch;
++count;
// cin >> ch;
cin.get(ch); // 获取空格
}
cout << endl << count << " characters read\n";
return 0;
}
//p155 5.18 ctrl+D 模拟EOF
#include <iostream>
int main ()
{
using namespace std;
char ch;
int count = 0;
cout << "Enter characters, enter # to quite:\n";
// cin >> ch;
cin.get(ch);// 返回的是cin对象, 其可以转换为bool while(cin.get(ch)) {};
//while (ch != '#')
while (cin.fail() == false) // test for EOF ctrl+D cin.eof() while(cin)
{
cout << ch;
++count;
// cin >> ch;
cin.get(ch);
}
cout << endl << count << " characters read\n";
return 0;
}
stdio.h
cstdio
getchar
putchar
char ch = cin.get(); // 将字符编码作为int 返回
cout.put(ch); // 参数类型为char
// p157
#include <iostream>
#include <cstdio>
int main ()
{
using namespace std;
char ch;
int count = 0;
cout << "Enter characters, enter # to quite:\n";
// cin >> ch;
cin.get(ch);
//while (ch != '#')
while (cin.fail() == false)
{
cout << ch;
++count;
// cin >> ch;
cin.get(ch);
}
cout << endl << count << " characters read\n";
cin.clear(); // 继续读 cin
int char1; // 注意 必须是int 变量 EOF 一般是 -1 不是任何字符串的编码值
char1 = cin.get();
count = 0;
while (char1 != EOF)
{
cout.put(char1);
// cout.put(char(char1));
++count;
char1 = cin.get();
}
return 0;
}
cin.get(char) 与 cin.get()比较
属性 | cin.get(char); | int ch = cin.get(); |
---|---|---|
传递输入字符的方式 | 赋值给参数char | 将函数返回值赋值给ch |
用于字符输入时函数的返回值 | istream对象,执行bool转换后为true | int类型的字符编码 |
达到EOF时函数的返回值 | istream对象,执行bool转换后为false | EOF (一般为 -1, 不能假设) |
二维数组定义: 行 - 列 :定义
int maxtemps[4][5]; // 声明表示4个元素的数组. 每个元素都是有5个整数组成的数组
// 二维数组的初始化
int maxtemps[4][5] =
{
{96, 100, 87, 101, 105},
{96, 98, 91, 107, 104},
{97, 101, 93, 108, 107},
{98, 103, 95, 109, 108}
}
// 二维数组的初始化 ---- 字符串数组
const int Cities = 5;
const char * cities[Cities] = {
"Gribble City",
"Gribbletoen",
"New Gribble",
"San Gribble",
"Gribble Vista"
};
ch6. 分支语句和逻辑运算符
// p168 6.2
#include <iostream>
int main()
{
char ch;
std::cout << "Type, and I shall repeat.\n";
std::cin.get(ch);
while (ch != '.')
{
if (ch == '\n')
std::cout << ch;
else
{
std::cout << ++ch;
// std::cout << ch + 1; // 输出ascii码
}
std::cin.get(ch);
}
std::cout << "\nPlease excuse the slice confusion.\n";
return 0;
}
#include <cctype>
char ch;
isalpha(ch); // 字符字母
isspace(ch); // 空白
isdigit(ch); // 数字
ispunct(ch); // 标点符号
// p192 6.15
#include <iostream>
#include <fstream>
int main()
{
using namespace std;
int year;
char automobile[50];
double a_price;
double d_price;
ofstream outFile;
outFile.open("carinfo.txt");
cout << "Enter the make and the model of automobile :";
cin.getline(automobile, 50);
cout << "Enter the mobile year: ";
cin >> year;
cout << "Enter the original asking price: ";
cin >> a_price;
d_price = 0.913 * a_price;
cout << fixed;
cout.precision(2);
cout.setf(ios_base::showpoint);
cout << "Make and model: " << automobile << endl;
cout << "Years: " << year << endl;
cout << "Was asking $" << a_price << endl;
cout << "Now asking $" << d_price << endl;
outFile << fixed;
outFile.precision(2);
outFile.setf(ios_base::showpoint);
outFile << "Make and model: " << automobile << endl;
outFile << "Years: " << year << endl;
outFile << "Was asking $" << a_price << endl;
outFile << "Now asking $" << d_price << endl;
outFile.close();
return 0;
}
// p196 6.16
#include <iostream>
#include <fstream>
#include <cstdlib>
const int SIZE = 60;
int main()
{
using namespace std;
char filename[SIZE];
ifstream inFile;
cout << "Enter name of data file: ";
cin.getline(filename, SIZE);
inFile.open(filename);
if(!inFile.is_open())
{
cout << "Could not open the file " << filename << endl;
cout << "Program terminating.\n";
exit(EXIT_FAILURE);
}
double value;
double sum = 0.0;
int count = 0;
inFile >> value;
while (inFile.good())
{
++count;
sum += value;
inFile >> value;
}
if (inFile.eof())
cout << "End of file reached.\n";
else if (inFile.fail())
cout << "Input terminated by data mismatch.\n";
else
cout << "INput terminated for unknown reason.\n";
if (count == 0)
cout << "No data processed.\n";
else
{
cout << "Items read: " << count << endl;
cout << "Sum: " << sum << endl;
cout << "Average: " << sum / count << endl;
}
inFile.close();
return 0;
}
输入和执行结果
[root@localhost cpp]# cat scores.txt
18 19 18.5 13.5 14
16 19.5 20 18 12 18.5
17.5
[root@localhost cpp]# ./a.out
Enter name of data file: scores.txt
End of file reached.
Items read: 12
Sum: 204.5
Average: 17.0417
ch7.函数 ---- C++的编程模块
// p218 7.7
#include <iostream>
const int MAX = 5;
int fill_array(double arr[], int limit);
void show_array(const double ar[], int n);
void revalue(double r, double ar[], int n);
int main ()
{
using namespace std;
double properties[MAX];
int size = fill_array(properties, MAX);
show_array(properties, size);
if (size > 0)
{
cout << "Enter revalue factor: ";
double factor;
while (!(cin >> factor))
{
cin.clear();
while (cin.get() != '\n')
continue;
cout << "Bad input; please enter a number: ";
}
revalue(factor, properties, size);
show_array(properties, size);
}
cout << "Done \n";
cin.get();
return 0;
}
int fill_array(double ar[], int limit)
{
using namespace std;
double temp;
int i;
for (i=0; i < limit; i++)
{
cout << "Enter value #" << (i + 1) << " : ";
cin >> temp;
if (!cin)
{
cin.clear();
while (cin.get() != '\n')
continue;
cout << "Bad input; input process terminated.\n";
break;
}
else if (temp < 0) // 输入负值结束
break;
ar[i] = temp;
}
return i;
}
void show_array(const double ar[], int n)
{
using namespace std;
for (int i = 0; i < n; i++)
{
cout << "Properties #" << (i + 1) << ": $";
cout << ar[i] << endl;
}
}
void revalue(double r, double ar[], int n)
{
for (int i = 0; i < n; i++)
ar[i] *= r;
}
数组区间作为函数参数STL超尾, 即用最后一个元素的后一个表示数组结尾; 即尾部开区间,不包含尾指定的参数;
double elbuod[20];
通过指针定义:elbuod 和 elbuod + 20 表示。
二维数组参数: 以下两种声明方式等价
int data[][] = {{1,2,3,4},{9,8,7,6},{2,4,6,8}};
int sum(int (*ar)[4], int size);
int sum(int ar[][4], int size);
//p234 7.13
#include <iostream>
#include <cmath>
struct polar
{
double distance;
double angle;
};
struct rect
{
double x;
double y;
};
void rect_to_polar(const rect * pxy, polar * pda);
void show_polar(const polar * pa);
int main ()
{
using namespace std;
rect rplace;
polar pplace;
cout << "Enter the x and y value: ";
while (cin >> rplace.x >> rplace.y)
{
rect_to_polar(&rplace, &pplace);
show_polar(&pplace);
cout << "Next two numbers (q to quit):";
}
cout << "Done !\n";
return 0;
}
void show_polar(const polar * pda)
{
using namespace std;
const double Rad_to_deg = 57.29577951;
cout << "diatance = " << pda->distance;
cout << ", angle = " << pda->angle * Rad_to_deg;
cout << " degress\n";
}
void rect_to_polar(const rect * pxy, polar * pda)
{
using namespace std;
pda->distance = sqrt(pxy->x * pxy->x + pxy->y * pxy->y);
pda->angle = atan2(pxy->y, pxy->x);
}
函数指针
ch8. 函数探幽
inline 函数
递归函数不能内联
引用:已定义变量的别名,主要用作函数的参数。 函数使用原来的数据,而不是传值调用类似的副本。按引用传递。
引用必须在声明的时候初始化。
按引用原理: 将形参初始化为参数的引用; vs 传值时,将形参初始化为参数值。
const 引用 创建临时变量; 编译器会生成临时匿名变量。临时变量只在调用期间存在。 参数引用匿名变量。
注意引用,与所引用的变量,与指针关系类似, 不能引用一杯销毁的变量。
// p270
ostream 基类 ofstream 是其派生类; ofstream 是建立在 ostream 之上的。