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 之上的。

posted @ 2021-05-13 18:36  Xuperior  阅读(88)  评论(0编辑  收藏  举报