1-23 汇总前面的学习经验(第四章、第五章)(壹)

第四章  数组和指针

1、类似于vector和iterator高级符合类型,数组和指针是低级符合类型。数组不允许添加元素,指针则可以像迭代器遍历和检查数组中的元素;

      数组无法进行size、push_back等操作

      数组是由类型名、标识符和尾数组成的复合数据类型

2、vector 使用 vector::size_type 作为下标的类型,而数组下标的正确类型则是 size_t(size_t为bitset.size()返回二进制位的个数,)

       数组的维数必须用值大于等于1的常量表达式定义:整型字面值常量、枚举常量、常量表达式初始化的整型const对象(非const变量以及到运行阶段才知道其值的const变量都是非法的)

        内置类型初始化为0,若是类类型则调用该类的默认构造函数进行初始化。

    字符数组的两种表达方式:

char ca1[] = {'C', '+', '+'};              // no null维数3
char ca2[] = {'C', '+', '+', '\0'};        // explicit null维数4
char ca3[] = "C++";                        // null terminator added automatically 维数4
                                           // null作为空字符用于结束字符串

3、数组的长度是固定的,区别于vector类型,数组不提供push_back或者其他的操作在数组中添加新元素。管理好内存很关键。

     导致安全问题的最常见原因是所谓“缓冲区溢出(buffer overflow)”错误。当我们在编程时没有检查下标,并且引用了越出数组或其他类似数据结构边界的元素时,就会导致这类错误。

     与使用标准 vector 类型的程序相比,依赖于内置数组的程序更容易出错而且难于调试。

4、4.2指针的引入

      vector的遍历可使用下标、迭代器,数组的遍历使用下标、指针。

      指针是指向某种类型对象的复合数据类型,是用于数组的迭代器:指向数组中的一个元素。

      解引用操作符  * dereference operator     自增操作符  ++ increment operator

      指针用于指向对象。类似于迭代器,指针提供对其所指对象的间接访问。指针用于指向单个对象,而迭代器只能用于访问容器内的元素。

      指针保存的为另一个对象的地址,只能初始化或赋值为同类型的变量地址或另一指针。void *可以保存任何类型对象的地址。

       指针声明语句时,请从右向左阅读。

       除了使用数值0或在编译时值为 0 的 const 量外,还可以使用 C++ 语言从 C 语言中继承下来的预处理器变量 NULL,该变量在 cstdlib 头文件中定义,其值为 0。如果在代码中使用了这个预处理器变量,则编译时会自动被数值 0 替换。

       给指针赋值:对左操作数进行解引用,修改的是指针所指对象的值。

       通过指针进行赋值:没有使用解引用操作,修改的是指针本身的值。

       引用必须初始化,始终指向同一个特定对象。

       指针本身也可用指针指向的内存对象。指针占用内存空间存放其值,因此指针的存储地址可存放在指针中。

       **操作符指派一个指针指向另一指针。

        两个指针的减法操作结果是标准库类型ptrdiff_t的数据。ptrdiff_t类似于size_t类型,机器相关的类型,在cstddef头文件中定义。size_t 是 unsigned类型,而 ptrdiff_t 是 signed类型。

         lsat = *(ia + 4) 指的是ia[0]后的第四个元素

        计算数组的超出末端指针

        for循环的性质:只要定义的多个变量具有相同的类型,就可以在for循环的初始化与剧中定义他们。

         for (int *pbegin = int_arr, *pend = int_arr + arr_size; pbegin != pendl; ++ pbegin)

         类似于其他内置类型,数组也没有成员函数。因而,数组不提供begin和end操作。

const size_t arr_sz = 5;
int int_arr[arr_sz] = { 0, 1, 2, 3, 4 };
// pbegin points to first element, pend points just after the last
for (int *pbegin = int_arr, *pend = int_arr + arr_sz;
            pbegin != pend; ++pbegin)
     cout << *pbegin << ' '; // print the current element



 // equivalent loop using iterators to reset all the elements in ivec to 0
for (vector<int>::iterator iter = ivec.begin();
            iter != ivec.end(); ++iter)
    *iter = 0; // set element to which iter refers to 0

           内置数组类型具有标准库容器的性质,与数组联合使用的指标本身是迭代器。

           

              

         如果指针所指的对象是const类型,那么指针也必须是const类型。const int  *noddle,约定的是prt而不是noddle。

         const类型的变量,必须要求对应的指针也是const类型。指向const的指针指向的对象可以不是const类型。

         void *指针也同样要求const void *才可以保存const变量。

int errNumb = 0;
int *const curErr = &errNumb; // curErr is a constant pointer  const指针的表达方式
curErr 是指向 int 型对象的 const 指针
const double *const pi_ptr = &pi;
 
指针和typedef
typedef string *pstring;
const pstring cstr;
cstr的类型是const pstring类型,更进一步的是指向string类型对象的const指针。
等价于string *const cstr;

const int  ic = 1; 定义了一个int型const对象ic,并用int型对象对其进行初始化
const int *p = &ic; 定义指向int型const对象的指针p,并用ic的地址对其进行初始化
int *const p = &ic; 定义int型对象的const对象,但是初始化的是const int型对象ic的地址
const int *const p = &ic; 定义指向int型const对象的const指针p,并用ic的地址对其进行初始化。

5、4.3 C-style 的字符串    

      C风格字符串是以空字符null结束的字符数组

      字符串字面值的类型就是const char类型的数组。

      C++语言通过 const char* 类型的指针来操作C风格字符串,碰到null终止运行。使用指针的算术操作来遍历C风格字符串:     

const  char *cp = “some value”;
while  (*cp){
       ++cp;
        }

        操纵C风格字符串的标准库函数(必须要有null结束),必须包含相应的C头文件:#include<cstring>

        strlen(s)返回s长度,不包括字符串结束符null

        strcmp(s1,s2)比较是否相同,大于正数,小于负数

        strcat(s1,s2)将字符串s2连接到s1后,返回s1

        strcpy(s1,s2)将s2赋值给s1,并返回s1

        strncat(s1,s2,n)将s2的前n个字符连接到s1后面,并返回s1

        strncpy(s1,s2,n)将s2的前n个字符赋值给s1,并返回s1

6、4.3.1动态数组

        每一个程序在执行时都占用一块可用的内存空间,用于存放动态分配的对象,内存空间称为程序的自由存储区或者堆。

        int *pia = new int[10]   ();    new和delete语句进行内存空间的划定,类型+数组维数。

        const int *pia = new const int[100];

         允许动态分配空数组:

         size_t   n = get_size();

          int  *p = new int[n];

          for(int *q = p; q != p +n; ++q)

         释放空间   delete  [ ]  pia;

#include <iostream>
#include <vector>
using namespace std;

int main()
{
    vector<int> ivec;
    int numbers;
 
    //读入元素数据并建立vector
    cout << "Enter nubmers:" << endl;
    while(cin>> numbers)
        ivec.push_back(numbers);
    
    //创建一个与vector相同的数组
    size_t n = getsize(ivec);
    int *p = new int[n];
    int *tp = p;
    for(vector<int>::iterator iter = ivec.begin(); iter != ivec.end(); ++iter,++tp)
       *tp = *iter;
    deleter [] p;

    return 0;
}

          标准库string与C风格的转换:char *str = st2.c_str();  

          c_str函数返回C风格字符串,即返回指向字符数组首地址的指针,以null结尾。

          int ia[3][4] = {

                (0,1,2,3),

                (4,5,6,7),

                (8.9.10.11)    };

           多维数组的指针:typedef

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

标准输入设备读入字符串,并存放到字符数组。处理可变长的输入

#include<iostream>
#include<string>
#include<cstring>   //c++中的c字符串

int main()
{
   string s1;
   const size_t n = 10;
   char s2[n+1];
   
   cout << "Enter a string(<=" << n << "characters):" << endl;
   cin >> s1;
   //比较len与n的关系,进而判断

   size_t len = strlen(s1.c_str());
   if(len > n){
      len = n;
      cout << "String is longer than" << n << "characters and is stored only"
           << n << "characters!" << endl;
    }
   //复制元素并实现添加
   strcpy(s2, s1, len);
   s2[len+1] = "\0";   末尾添加空字符

   return 0;
}

用int型数组初始化vector对象:vector 从int数组中选择

把int型vector复制给int型数组:  int *p = new int[ivec.size()]      delete  [ ]  p;

4.34例题:

#include<iostream>
#include<string>
#include<vector>
using namespace std;

int main()
{
   //读入string类型的数据,并存到vector中
   string st1;
   vector<string>  ivec; 
   cout << "please input a string:" << endl;
   while(cin >> st1)
       ivec.push_back(st1);

   //复制到字符指针数组,为元素创建数组
   char **p = new char*[ivec.size()];     //创建的“字符指针数组”需要加两个※
 
   //为每一个vector元素创建一个字符数组
   size_t n = 0;
   for(vector<string>::iterator iter = ivec.begin(); iter != ivec.end(); ++iter,++n){
       char *pat = new char[(*iter).size()+1];
       //复制vector元素的数据到字符数组
       strcpy(pat, (*iter).c_str());
       //将指向该字符数组的指针插入到字符指针数组
       p[n] = pat;
    }
    //释放各个字符数组
    for(ix = 0; ix != ivec.size();++ix)
         delete [] p[ix];
    //释放字符指针数组
         delete [] p;
    return 0;   
}

typedef简化指向多维数组的指针 

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

int (*p)[4]是指向4个元素的数组的指针
int *p[4]是指向int型的数组指针

vector为更灵活更容易管理的数组

string是C风格字符串的改进类型,而C风格字符串是以空字符结束的字符数组。指针和迭代器都能访问所指向的对象。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章