C++Primer 学习

命名空间

标准库的命名空间

#include <iostream>
#include <string>
using std::cout; 
using std::cin; 

数组和指针

数组声明时候的下标类型

整型常量 枚举常量 整型const常量

指针声明应该注意的

1 string *   s1,   s2;

s2 不是指针的了

安全声明方式为

1 string   * s1,   s2;

关于NULL

从C语言继承下来的 在cstdlib中定义的 不属于标准控件

std::NULL 是错误的

void 指针

void指针只能读 不要写 不允许赋值

C++支持指针相减
1 ptrdiff_t   p1     p2;

返回类型是 ptrdiff_t 和 size_t 类似 与机器相关

只不过ptrdiff_t 是signed整型

在文件 cstddef中定义

指针的下标可以为负数

因为指针的下标表示的就是加减的含义

1 int   * p   =   & ia[ 2 ];
2 int   k   =   p[ - 2 ];         // 正确 相当于 *(p - 2)
指针是数组的迭代器
1 const   size_t   arr_sz   =   5 ;
2 int   int_arr[arr_sz]   =   { 0 ,   1 ,   2 ,   3 ,   4 } ;
3 for ( int   * pbegin   =   int_arr,   * pend   =   int_arr   +   arr_sz;   pbegin   ! =   pend;   pbegin + + )
4 {
5         cout < < * pbegin < < endl;
6 }

指针和const

1 // 指针常量 指针指向的单元不能修改 const修饰的是int *p
2 const   int   * p;
3 int   const   * p;
这种指针只能指向任何对象 但是const对象的地址也只能赋给const 指针
虽然可以指向任何对象 一旦指向了某对象就不能通过该指针的解引用修改对象的值

4 // 常量指针 指针本身不能修改 const修饰的是 p
5 int   * const   p;

这种情况下 解引用的值是可以改变的

typedef的情况
1 typedef   string   * pstring;
2 const   pstring   cstr;

const 修饰的是cstr 所以等价于 string * const cstr

字符串操作
 
strlen是不包括NULL在内的字符串的长度
 
new出来数组
 
int *p = new int[10];
delete [] p;

c语言数组和string混合

char * sz = “abcdef”;
string str1(sz);
string str2;
str2 = sz;
str2 = str1 + sz; 

也可以获得string的c方式存储

因为返回的是const char*所以定义必须是const char*

const char *sz = str.c_str();

数组可以初始化vector

const size_t arr_size = 4;
int sz[arr_size] = {0, 1, 2, 3};
vector<int> ivec(sz + 1, sz + arr_size);

多维数组

多维数组实际上就是数组的数组

int a[3][4];      // 数组有3个元素 每个元素是 int[4]的数组
int (*p)[4];      // 指向4个单元元素的数组指针
p = &a[2];        // 表明p指向a二维数组的第三个元素

typedef定义指向数组的指针

int ia[3][4];
typedef int int_array[4]
int_array *ip = ia;
for(int_array *p = ia; p != ia + 3; p++)
{
    for(int *q = *p; q != *p + 4; q++)
    {
        cout<<*q<<endl;
    }
10  }

标准库string类型

c语言是 string.h

c++库是cstring.h

#include <string>
using std::string;

初始化

string s1;
string s2(s1);
string s3("value");
string s4(n, 'c');

输入输出

while(cin>>word)
{
    cout<<word<<endl;
}

输入时会过滤字符串前面的空格

遇到空格时输入完毕

输入一行

string s;
while(getline(cin, s))
{
    cout<<s<<endl;
}
getline是以换行符为标准的 遇到换行符就停止输入

string对象的操作

s.empty();    // 判断字符串是否为空
s.size();     // 字符个数  这里的返回值是  string::size_type  string 库里定义的类型 不能赋值给int 但是可以赋值给unsigned
s[n];         // 从0开始的第n个字符  既可以输入也可以输出
s1 + s2;      // 还有+=操作符
s1 = s2;
v1 == v2      // >= <= == != > <  采用的是字典序

unsigned int 和 unsigned long 表示的是一样的意思

+是可以连着加的,但是+左右必须至少有一个是string类型的

s3 = "Hello" + "world";       // error
2s4 = s1 + "Hello" + "world";  // OK
3s4 = "Hello" + "world" + s1;  // error

最后一个字符是

s[s.size - 1];    // 因为是从0开始的下标

输出每一个字符

for(string::size_type i = 0; i != s.size(); i++) 
{ 
   cout<<s[i]<<endl; 
} 

也可以输入

s[0] = 'a';

索引的范围是  0倒s.size() – 1

string为空的时候size()是0

索引的类型是 unsigned 的 string::size_type

string 还可以对其中的单个字符 进行判断处理

这些函数在 cctype 头文件中加以定义

cctype.h  和 ctype.h 是一样的

只是一个是cpp 方式定义的 还有命名空间 std 一个是 c 方式定义的

标准库vector类型

容器类型 模板

#include <vector>
using std::vector;

vector本身是一个类型  用来定义对象

vector<int> ivec;

初始化

vector<int> ivec1;            // 初始化为空 empty
vector<int> ivec2(ivec1);     // 用一个初始化另一个
vector<int> ivec3(10, -1);    // 初始化10个元素 每一个为-1
vector<int> ivec4(10);        // 初始化10个元素 每一个为默认值 这里为0  vector本身初始化的

虽然有初始化 但通常是定义一个空的对象 然后动态增长

操作

v.empty();        // 判断空否
v.size();         // 获取元素个数
v[n];             // 和string类似
v1 = v2;          // 赋值
v1 == v2;         // 判断相等 > < != >= <= 
v.push_back(t);   // 末尾加入元素

虽然size返回的也是size_type 但要注意类型

vector<int>::size_type;    // OK
vector::size_type;         // error
 
一个push_back的例子
#include <string>
#include <vector>
using std::string;
using std::vector;
 
string word;
vector<string> text;
while(cin>>word)
{
10      text.push_back(word);
11  }

为什么在循环体中每次都调用size() 而不是调用一次 保存size的值每次都使用呢

因为很多类型的size都是动态增长的 所以这么做才是合理的

为什么用 != 作为判断循环的结束 而不是 < 之类的呢

迭代器

迭代器可以起到和下标一样的功能  可以对容器中的元素进行操作

下标操作只有少数容器支持 迭代器对于所有的容器都可以支持

要使用迭代器 首先要定义该容器下的迭代器变量

vector<int>::iterator iter;
 
容器的位置获取
vector<T>::iterator vector::begin();
vector<T>::iterator vector::end();
 
返回值是 迭代器类型哦~
 
vector<int> ivec;
ivec.begin();        // 指向第一个元素 ivec[0]的位置
ivec.end();          // 指向最后一个元素的  后一个元素  这是一个不存在的元素

如果为空

ivec.begin() == ivec.end();

迭代器操作

vector<T>::iterator iter;
 
iter++  ++iter
iter--  --iter
*iter             // 相当于ivec[]操作  也可以被赋值
6iter + n;         // 返回该容器的iterator类型  n 是该容器的size_type 类型 或者 difference_type 类型
7iter – n;         // 返回该容器的iterator类型  n 是该容器的size_type 类型 或者 difference_type 类型
8iter1 – iter2;    // 返回difference_type 类型

difference_type类型和size_type类型唯一不同在于它是signed的

例子

for(vector<T>::iterator iter = ivec.begin(); iter != ivec.end(); iter++)
{
    *iter = 0;
}

对于*iter 有const_iterator这样的迭代器类型的变量 *iter的时候 不能改写变量

标准库bitset类型

#include <bitset>
using std::bitset;

定义

bitset<32> b;   // 默认每一个位都是0

初始化

bitset<n> b;               // 初始化一个元素 每一位都是0
bitset<n> b(u);            // 用unsigned初始化 直接拷贝 低位保留 高位补0 或者截断
bitset<n> b(s);            // 用string类型初始化 string的值必须是像“10101010101”这样的  string的低位被截断了
bitset<n> b(s, pos);       // 用string类型初始化 从string型的 pos位置开始到string::size() - 1
bitset<n> b(s, pos, n);    // 用string类型初始化 从string型的 pos位置开始到 pos + n

高低位的顺序

bitset<32> b;

b[31],b[30],…,b[0]   

而string型是 s[0],s[1],…,s[s.size() - 1]

函数

默认实参

可以在函数声明中采用默认实参

也可以在函数实现中采用

但是2者只能取其一

如果在函数实现中采用的话  应当包含源文件 否则默认实参是无效的

静态局部变量

static int a;

在函数生命期外仍然有效

但是函数外部无法访问到

下次调用该函数的时候

该数据还存在

内联函数

产生原因

和单纯写语句相比,写成函数的方式

好理解  好改  好重用  好统一 但是比语句要慢

内联好处

在内联处展开 效率高

在头文件中声明

inline int fun();

在函数体中实现

inline int fun()
{
}

宏不能访问对象的私有成员。 
宏的定义很容易产生二意性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值