• C++学习2 字符串、向量和数组


    C++学习2 字符串、向量和数组

    string表示可变长的字符串序列,vector存放的是某种给定类型对象的可变长序列。

    命名空间的using声明

    域作用符(::)用来将命令空间中的函数或对象进行调用。
    可以使用using声明来使得可以直接访问命名空间或者命名空间中的某个函数。

    using std:cin;    //这样就可以直接调用cin函数

    可变长字符序列之string库

    使用string库之前必须先包括其头文件和作用域。

    #include<string>
    using std::string;

    定义和初始化string对象

    分为直接初始化和拷贝初始化.

    string s1; //默认为空字符串
    string s2(s1); //s2为s1的副本
    string s3="liangzi"; //拷贝初始化
    string s4(s3); //s4时s3的副本
    string s4=s3;//与上一条指令等价
    string s5("liangzi");//直接初始化
    string s6(100,'cc'); //将cc重复100遍得到的字符串

    string对象上的操作

    os<<s   //将s中的字符串写到输出流os之中,返回os
    is>>s //与上一条指令相似,将输入的字符串存储到s之中
    is=getline(is, s)   //该函数将从is中读取一行赋值给s,之后返回is
    s.empty()  // 判断字符串是否为空
    s.size()  //返回字符串中字符的个数
    s[n]   //返回字符串中的第n个字符,从0开始
    s1+s2 //两个字符串进行连接
    s1==s2 //二者完全一致
    <, <=, >, >= //利用字符在字典中的顺序进行比较

    下面给出一个读写string对象的简单例子。

    int main()
    {
        string s;
        cout << "please input a string" << endl;
        cin >> s;
        cout << s << endl;
        return 0;
    }

    使用getline读取一整行

    与cin不同,如果一开始的输入是一个换行符,getline函数读取之后会得到一个空字符。
    使用示例

    int main()
    {
    
    //使用C++读取文本文件的示例
        string file_path, line;
        fstream read_file;  //文件流类型,以后会详细介绍
        cout << "please input the need read path" << endl;
        cin >> file_path;
        read_file.open(file_path);
        while (!read_file.eof())
        {
            getline(read_file,line);
            cout << line << endl;
        }
        read_file.close();
        system("pause");
        return 0;
    }

    字符串常量和string对象相加

    必须注意C++中“+”左右至少有一个string对象,即两个字符串常量不能进行相加操作。

    string s1="liangzi", s2="zuishuai";
    string ss=s1+s2;                                //正确
    string sss=s1+"---------->>"+s2;         //正确
    string ssss="liangzi"+"zuishuai";       //错误

    对string对象中的字符进行处理

    首先介绍一下c语言库中的一些常用函数

    cctype(或ctype.h)

    #incldue<cctype>
    using std::cctype;
    
    isalnum(c)  //当c为字母或者数字时为真
    isalpha(c)  //当c为字母时为真
    iscntrl(c)   //当c为控制字符时为真
    isdigit(c)   //当c为数字时为真
    isgraph(c) //当c不是空格但是可以打印时为真
    islower(c) //当c是小写字母时为真
    isprint(c)  //当c是可打印字符时为真
    ispunct(c)  //当c是标调符号时为真
    isspace(c)  //当c是空白时为真
    isupper(c)  //当c为大写字母时为真
    isxdigit(c)  //当c是十六进制数字时为真
    tolower(c)  //若c为大写字母,将其变为小写字母,否则不变
    toupper(c) //若c为小写字母,将其变为大写字母,否则不变

    使用基于范围的for语句来遍历string对象中的每一个字符

    范围for语句(range for)是c++11中提出的,这种语句可以实现对给定序列中的每一个值进行处理。

    //例如,输出一个字符串的每一个字符
    sting s("liangzid");
    for(auto i:s)
    {
        cout<<i<<endl;
    }

    再给出一个统计标点符号的示例。

    string s("liangzi zi zui shuai ! ");
    i=0;
    for (auto &c:s)
    {
        if (ispunct(c))
        {
            ++i;
        }
    }
    cout<<" the number of punctuation characters is : "<<i<<endl;

    标准库类型vector

    标准库类型vector表示同一类型的若干对象的集合,且集合中的每一个对象都有一个对应的索引。因为该向量(vector)容纳着这些对象,所以说vector也被称作是容器(container)。后面将会对容器进行更详细的介绍。

    C++中既有类模板(class template),也有函数模板。模板本身不是类和函数,模板相当于是编译器为了生成类或者函数而编写的一份说明。编译器根据模板创建类或者函数的过程被称为实例化(instantiation)

    对于类模板,需要添加一些额外信息以确定模板到底实例化成什么样的类,一般来说,提供信息的方式为:再模板后面跟一对尖括号,里面放上相应的信息。

    vector是一个类模板。
    注释:在c++11中,两层vector的话必须在最后的两个尖括号处放置空格,即vector<vector<int> >而非vector<vector<int>>

    定义和初始化vector对象

    与string的定义和初始化类似,vector的用法如下:

    vector<Type> v1       //v1是一个空的容器,执行Type类型的默认初始化
    vector<Type> v2(v1)  //v2是v1的副本
    vector<Type> v3=v1  //直接初始化
    vector<Type> v4(n,val)  //v4包括了n个重复的均为val的元素
    vector<Type> v5{a,b,c,...}  //v5中容纳的元素包括a,b,c,...
    vector<Type> v6={a,b,c,...}//同上

    向vector对象中添加元素

    使用 push_back() 函数来将一个元素压入vector对象的尾端。

    //示例:初始化一个数列,里面储存着从0到99的整数
    vector<int> sequence;
    for(int i=0;i !=100;i++)
    {
        sequence.push_back(i);
    }
    //使用示例:将之前读取的没一行作为一个元素,实现对任何不定长文件的动态储存。
    int main()
    {
       string file_path, line;
       fstream read_file;
       vector<string> all_lines;
       cout << "please input the need read path" << endl;
       cin >> file_path;
       read_file.open(file_path);
       while (!read_file.eof())
       {
       	getline(read_file,line);
       	all_lines.push_back(line);
       }
       read_file.close();
       system("pause");
       return 0;
    }

    vector的其他使用注意

    和使用string一样,也可以使用范围for语句进行处理。
    比如对前面读取得到的vector向量进行逐元素的输出,则可以使用range for语句。

    int main()
    {
        string file_path, line;
        fstream read_file;
        vector<string> all_lines;
        cout << "please input the need read path" << endl;
        cin >> file_path;
        read_file.open(file_path);
        while (!read_file.eof())
        {
            getline(read_file,line);
            all_lines.push_back(line);
        }
        read_file.close();
        for (auto &cc : all_lines)
        {
            cout << cc << endl;
        }
        system("pause");
        return 0;
    }
    

    同样地,我们可以使用下标索引来访问vector<Type> CC中的每一个元素,但是无法用下标来创造一个新的元素。

    迭代器(iterator)

    迭代器是一种机制(可以看作是一种类型),类似于指针类型,迭代器提供了对对象进行间接访问的方式。迭代器可以间接访问容器中的某个元素或者string对象中的某一个字符。迭代器可以访问某个元素,也可以从一个元素移动到另外一个函数。迭代器有有效无效之分,与指针相同,当迭代器指向某个元素或者尾元素的下一个位置时迭代器有效,其他情况均为无效。

    使用iterator

    一般利用beginend来进行对容器的指向。begin成员负责返回第一个元素(或字符)的迭代器,end用来返回指向容器尾元素的下一个位置的迭代器——即该迭代器标记了容器的一个根本不存在的”尾后“(off the end)元素,用来表示我们已经处理完了容器中的所有元素。end成员返回的迭代器通常被称为**尾后迭代器(off-the-end iterator)**或尾迭代器(end iterator)。如果容器为空,则begin与end均返回尾迭代器。
    详细见示例。

    vector<int> liangzi{1,2,3,4,5};
    auto begin_liangzi=liangzi.begin();
    auto end_liangzi=liangzi.end();
    //之所以使用auto,是因为我们也不确定到底其指定的是什么类型

    iterator运算符

    //通过以下运算符可以看出迭代器和指针的类似之处
    
    *iter                                   //返回迭代器iter所指向元素的引用
    iter->mem                        //解引用iter并获取该元素的名为mem的成员,等价于(*iter).mem
    ++iter                                 //令iter指向容器中的下一个元素
    --iter                                 //令iter指向容器中的上一个元素
    iter1==iter2                //若相等,指它们指向了容器中的同一个元素
    iter1 != iter2                  //同上 

    迭代器的运算部分

    数组

    数组是一种类似于vector的数据结构,但是数组的长度是固定的。数组在提高了一点性能的同时丧失了一点灵活性。

    定义和初始化内置数组

    定义数组时必须指定数组的类型(不能使用auto),定义数组时中括号里的量一定要是常量或者常量表达式。不能使用一个数组对另外一个数组进行初始化。

    int i=100;      //不是常量表达式
    constexpr int ii=100;
    int array1[100];                       //正确
    int *parray[100];                      //正确,数组中的每个元素都是指向整型数据的指针
    string array2[i];                      //错误
    string array3[ii];                        //正确
    
    int a[ ]={1,2,3};
    int aa[ ]=a;            //错误
    
    int &liangzi[100]={1,2,3,...};                //错误,引用不是一个对象,不能被数组储存
    
    int *pliangzi[100];                          //正确,数组中的每个圆度都是指针
    int (*pliangzii)[100]=&array1;                   //正确,定义了一个指针,指向一个有100个元素的数组
    int (&liangzia)[100]=array;                      //正确,是对一个数组的引用
    
    /* 可以记住一句口诀:从右向左,从内向外*/

    访问数组元素

    使用下标访问

    指针和数组的关系

    与C语言中相似,数组名即是一个指向数组中第一个元素的指针。试图定义一个指针指向数组中的某一个元素,可以使用

    int a[100];
    int *p=&a[20]; 

    也可以使用

    int *p2=a;

    对于指针也相当于迭代器,c++11特别引入了两个函数begin()和end()来描述一个数组的首端和尾后。有

    int array[10];  
    int *parray=&array[10];         //尾后指针,不能进行解引用,也不能进行递增
    int *begin_array=begin(array);        //下指向首元素的指针,相当于array
    int *end_array=end(array);             //尾后指针

    多维数组

    严格来说并不存在多维数组,多维数组表达的意义是数组的嵌套。比如说二维数组就是一个数组的数组。

    在理解多维数组时,越靠近自变量名字的下标代表越基本的元素分布。比如int a[2][3][4];就代表有一个数组,长度为2,其中的每一个元素都包含着三个元素,这三个元素每一个都是一个长度为4的数组。

    多维数组的初始化

    与python的numpy类似,但是此处使用花括号。

    int ia[3][4]={
    {1,2,3,4},
    {5,6,7,8},
    {1,2,3,4}
    };

    当然,由于多维数组本质上是由1维数组表示的,所以也可以采用直接的一长串来表示。

    多维数组的下标引用

    可以使用下标运算符来访问多维数组的元素。当下标的数目少于数组本身的维度时,返回的是一个差值维度的数组。

    int ra[3][4];
    int arr[3][4][5];
    
    ra[2][3]=arr[0][0][0];       //元素之间的赋值操作
    int (&row)[4]=ra[1];        //row是对一个长度为4的数组的引用

    利用range for 处理多维数组

    以二维数组为例进行说明。

    //实现对二维数组中的所有元素进行求和
    sum=0;
    for (auto &i:array)
       for (auto &j:i)
       {
       	sum+=j;
       }
  • 相关阅读:
    POJ3094 UVALive3594 HDU2734 ZOJ2812 Quicksum【进制】
    UVALive5583 UVA562 Dividing coins
    POJ1979 HDU1312 Red and Black【DFS】
    POJ1979 HDU1312 Red and Black【DFS】
    POJ2386 Lake Counting【DFS】
    POJ2386 Lake Counting【DFS】
    HDU4394 Digital Square
    HDU4394 Digital Square
    UVA213 UVALive5152 Message Decoding
    UVA213 UVALive5152 Message Decoding
  • 原文地址:https://www.cnblogs.com/liangzid/p/10910120.html
Copyright © 2020-2023  润新知