数组

(1)传统的数组实现方式
见另一篇博客传统数组
(2)自动分配数组
(1)一维数组(malloc/delete)
#include <iostream>
        #include<iterator>
        #include<list>
        #include<stdlib.h>
        #include<stdio.h>
        #include<time.h>

        using namespace std;
        int main(void)
        {
                cout<<"使用malloc实现动态分配的数组空间"<<endl;
                int *p1 = (int *)malloc(sizeof(int)*10);
                for(int i=0; i<10; i++) {
                        *(p1+i) = i+10;
                }
                for(int i=0; i<10; i++) {
                        cout << *(p1+i);
                }
            cout << endl;
                free(p1);

                cout<<"\n使用new实现动态分配的数组空间"<<endl;
                int *p2 = new int[10];
                for(int i=0; i<10; i++) {
                        *(p1+i) = i+20;
                }
                for(int i=0; i<10; i++) {
                        cout << *(p1+i);
                }
            cout << endl;
                delete p2;

                return 0;
        }
(2)多维数组
#include <iostream>
        #include<iterator>
        #include<list>
        #include<stdlib.h>
        #include<stdio.h>
        #include<time.h>

        using namespace std;
        int main(void)
        {
                cout<<"使用malloc开辟e二维数组"<<endl;
                int **p1 = (int **)malloc(sizeof(int *)*5);
                for(int i=0; i<5; i++) {
                        *(p1+i) = (int *)malloc(sizeof(int)*5);
                }
                for(int i=0; i<5; i++) {
                        for(int j=0; j<5; j++) {
                                p1[i][j] = i+j;
                        }
                }
                for(int i=0; i<5; i++) {
                        for(int j=0; j<5; j++) {
                                cout<< *(*(p1+i)+j)<<" ";
                        }
                        cout<<endl;
                }
                for(int i=0; i<5; i++) {
                        free(*(p1+i));
                }
                free(p1);

                cout<<"\n使用new关键字动态开辟二位数组"<<endl;
                int **p2 = new int*[5];
                for(int i=0; i<5; i++) {
                        *(p2+i) = new int[5];
                }
                for(int i=0; i<5; i++) {
                        for(int j=0; j<5; j++) {
                                p2[i][j] = i+j;
                        }
                }
                for(int i=0; i<5; i++) {
                        for(int j=0; j<5; j++) {
                                cout<< *(*(p2+i)+j)<<" ";
                        }
                        cout<<endl;
                }
                for(int i=0; i<5; i++) {
                        delete(*(p2+i));
                }
                delete p2;

                return 0;
        }
(3)使用动态分配方式实现数组时需要注意
    (1)动态分配实现多维数组时,利用的是多级指针来实现的,而传统的
        多维数组是靠数组指针这种特殊形式的指针实现的,但是让它
        们在多维构建的逻辑上都是一样。

    (2)传统方式实现的多位数组本质还是一维数组,元素全部都是连续的
        但是动态分配空间不是的,它是由指针数组组织起来的,所有
        的一维数组的空间不一定是连续的。

    (3)动态方式实现多维数组时,由于单维数组间的空间并不连续,因此
        在释放内存空间时一定要小心,不要导致内存泄漏。需要分批
        释放空间,就像上面的例子所示。

    (4)传统的多位数组中*的作用与动态分配的多维数组访问时*的含义是不同
        的,比如如二维数组*访问形式:
        传统方式:*(*(buf+i)+j) = 5; buf[i][j]
            其中的*(buf+i)中的*实际上是强制转换的功能,强制的
            将数组指针类型转换为数组元素指针类型。


        动态分配方式:*(*(p+i)+j) = 5; buf[i][j]
            其中的*(p+i)中*其实时寻找空间操作,或者也称为解引用
            操作。

    (5)动态分配的数组不能初始化,只能使用赋值的方式给值。


    (6)传统方式实现的数组,特别是多维数组会大量涉及数组指针的概念
        动态的方式实现的数组则大量涉及多级指针的概念。

(4)什么时候使用自动内存分配的方式实现数组
    当需要程序运行后,动态确定数组的大小的时候,这个时候就是必须使用这种方式。
(3)C++提供数组类封装的方式式。
c++中还有一种数组类封装的实现方式,就对传统和动态分配这两种方式进行了类封装,类名为array,有些编译器不支持这样的实现方式。
使用

(1)一维
array<int,5> myarray={1,2,3,4,5};  

(2)二维 
array<array<int,2>,3 > myarray2D={1,2,3,4,5,6}; 
(4)c++中数组实现方式总结
(1)传统方式 
    自定义固定长度数组时,常用这种方式
(2)动态分配方式
    需要在程序运行时具体决定元素个数时使用这种方式,C++中的STL vector
    容器就是使用的动态分配数组的方式封装实现的。

(3)array类封装方式
    array对数组进行了类封装,至于它的具体实现方式要看定义类对象的
    方式。如果是通过new关键字实现的,就是使用动态分配的方式。
    否者就是使用传统的方式实现。

在java中,java摈弃了c++个各种各样复炸的数组实现方式,只保留了Array类封装
样式的数组,在java中由于类对象空间全部都是开辟于动态分配区(堆),因此本质上
java的数组全部采用动态空间分配方式,单维数组空间之间不连续。


(3)字符串(特殊的字符数组)
(1)C样式字符串
    (1)数组形式
    (2)指针形式

(2)C++提供的string形式
    (1)声明   
        //string str1 = "hello world";
            //string str1("hello wolrd");
            string *str1 = new string("hello world");

        如果不初始化字符串就是空字符串。


    (2)string对[]/=/==/+进行了重载
        (1)可以使用[]访问字符串字符
        (2)可以使用=直接相互间赋值
        (3)可以使用==比较两个字符串对象是否相等,但是如果是指针形式的对象,不能使用==判断
                string *str1 = new string("hello world");
                string *str2 = new string("hello world");
                string str3("hello world");
                string str4("hello world");

                str1[0] = '$';

                string str;
                if(str3 == str4) {
                        str = "==";
                } else {
                        str = "!=";
                }   
                cout << str  << endl;

        (4)字符串可以使用+进行连接,但是要求第一个必须是string类型的字符串
            不能使用字符串字面量(常量字符串,任何形式的C类型的字符串),因为
            只有string重载了+运算符
                    string str1 = "hello!, ";
                    string str = str1+"world"+" is "+ "world";


            注意:
                    string *str1 = new string("hello!, ");
                    char *str2= " wwww ";
                    string str = *str1+"world"+ str2 + " is "+ "world";

                    cout << str << endl;  
        (5)+=的使用
            (1)左边的第一个必须是string类型字符串
            (2)右边的string类型变量必须先声明后使用
                        string *str1 = new string("hello!, ");
                        string str;
                        // = *str1 +  "world"+" is "+ "world";
                        str += *str1 + "world"+" is "+ "world";

                        cout << str << endl;    


        (6)使用>>向string操作数中输入字符串时,无法输入带有空格的字符串
            (1)使用getline(cin, str);函数,就可以输入带有空格的字符串,
                默认结尾符是回车。

            (2)使用第三参数输入指定结尾符的字符串
                getline(cin, str,'#');//输入#结尾的字符串

    (3)访问字符串的字符
        由于string对[]进行了重载,因此,可以使用[]访问字符串中的元素,既可以作为左值使用
        也可以作为右值使用。
                string str;

                getline(cin, str);

                for(int i=0; i<str.length(); i++) {
                        str[i] = std::toupper(str[i]);
                }

                cout<< str << endl;


    (4)常见操作字符串的一些string的成员函数的回顾
        (1)substr():提取子字符串
            (1)只有一个参数时:指定索引位置
                如果指定的索引位置超出范围,会抛出超出范围的异常。

            (2)两个参数时:第一个参数指定索引位置,第二个参数指定提取的字符串长度
                (1)如果指定的索引位置超出范围,会抛出超出范围的异常。
                (2)如果指定的长度超过范围,自动提取到字符串结束为止即可。

        (2)字符串比较
            (1)c字符串的比较
                (1)比较的函数:使用strcmp或者strncmp函数进行比较
                    (1)strcmp函数:比较两个字符串是否完全相等
                        char *p = "hello";
                        char buf[] = {"hellw"};
                        int ret = strcmp(p, buf);
                    (2)strncmp函数:比较两个字符串前n个字符是否相等
                        char *p = "hello";
                        char buf[] = {"hellw"};
                        int ret = strncmp(p, buf, 4);

                    (3)函数返回值:如果两个字符串相等,返回0,如果第一个参数指向的字符串小于第二个参数指向的字符串,
                    返回一个小于0的数,否则就返回一个大于0的数。


                (2)字符串比较的规则(以strcmp为例)
                    将两个字符串的字符逐个今次那个比较,知道找到不同的字符或者到达字符串的末尾,如果找到不同字符,就
                    根据器asscii值进行比较(函数返回asscii差值),如果两个字符串找到最后发现长度不相等,就返回长度差值。


            (2)使用重载后的比较运算符 ==/!=/<=/>=进行比较
                (1)比较的方法与strcmp同
                (2)对string对象进行比较,或者将string对象与c样式的字符串进行比较
                            string str1 = "hello";
                            string str2 = "he";

                            string str;
                            if(str1 < "dsdf") {
                                    str = "small";
                            } else {
                                    str = "lage";
                            }

                            cout<< str << endl;


            (3)使用compare成员函数进行比较
                (1)比较的方法与strcmp同
                (2)对string对象进行比较,或者将string对象与c样式的字符串进行比较
                (3)compare不同的重载版本
                    (1)word.compare(string str);:比较word与str是否完全相等
                    (2)word.compare(int index, int num, string str1);:比较word中从index开始向后num个字符与str1是否完全相等。
                    (3)word.compare(int index1, int num1, string str1, int dex2, int num2);:比较word与str1的子字符串是否相等。

                (4)使用substr实现子字符串的比较
                    if(word.substr(2,4)==word.substr(3,5));


        (3)搜索字符串
            (1)搜索成员函数find:返回索引
            (2)的不同重载版本
                (1)word.find(char c):在word中搜索字符,成功返回索引,失败返回string::npos(4294967295)表示非法字符位置。
                (2)word.find(string/char * str):    
                (3)word.find(string/char * str, int i):从word的i位置开始找。
                (2)word.find(string/char * str, int i, int n):从word的i位置开始找str中前n个字符。

            (3)逆向搜索函数rfind,用法同find
            (4)在字符串中搜索字符集中的字符
                (1)涉及函数
                    (1)word.find_first_of(string/char str);:从word头开始索引,第一次出现str中字符的位置
                    (2)word.find_first_not_of(string/char str);:从word头开始索引,第一次出现非str中字符的位置
                    (3)word.find_last_of(string/char str);:从word尾部开始索引,第一次出现str中字符的位置
                    (4)word.find_last_not_of(string/char str);:从word尾部开始索引,第一次出现非str中字符的位置

                (2)使用例子:将字符串拆分成子字符串
#include <stdlib.h>
                        #include <iostream>
                        #include <string>

                        using namespace std;
                        int main(void)
                        {
                                string str = "sdfa sdaf,sdffsdf,fsdf/fsdf";
                                int start = 0;
                                int end = 0;
                                string s = " ,/";

                                start = str.find_first_not_of(s);
                                while(start != string::npos) {
                                        end = str.find_first_of(s, start+1);
                                        if(end == string::npos)
                                                end = str.length();

                                        cout << str.substr(start, end-start) << endl;

                                        start = str.find_first_not_of(s, end+1);
                                }

                                return 0;
                        }
(4)修改字符串
            (1)插入字符串
                (1)涉及成员函数:insert
                (2)不同重载版本
                    (1)word.inset(int i, string/char *str):将字符串插入word的i之前
                    (2)word.inset(int i, string/char *str, int n):将字符串插入str中前n个字符word的i之前
                    (2)word.inset(int i, string/char *str, int j, int n):将字符串插入str中j位置开始的n个字符word的i之前

                (3)测试例子

            (2)字符串的替换
                (1)涉及成员函数:replace
                (2)涉及不同的重载版本
                    (1)word.replace(int i, int n, string/char * str);:将word中的i位置开始的n个字符,用str替换
                    (2)word.replace(int i, int n, string/char * str,int n1);:将word中的i位置开始的n个字符,用str中的前n1个替换
                    (3)word.replace(int i, int n, string/char * str,int i1, int n1);:将word中的i位置开始的n个字符,用str中i1位置开始的n1个字符替换。
                (3)用例


            (3)删除字符
                (1)涉及成员函数erase
                (2)重载版本
                    (1)word.erase(int i, int n);:将word中的i位置开始的n个字符删除

                (3)用例

    (5)字符串数组
        (1)c样式的字符串数组

        (2)c样式字符串数组
            char *p[] = {"hello", "world", "is", "buitful"};

        (3)string样式字符串              
            string p[] = {"hello", "world", "is", "buitful"};


        (4)二者的区别
            c样式的字符串数组中,字符串是常量,存放在常量区,内容不能被更改,否者会导致段错误。
            string样式字符串,字符串在string类中,是以字符串数组的形式存放的,内容是可以修改的。

        (5)用例
#include <stdio.h>
                #include <stdlib.h>
                #include <iostream>
                #include <string>

                using namespace std;
                int main(void)
                {
                        #if 0
                        char *p[] = {"hello", " world", " is", " buitful"};

                        p[0][1] = 'w';
                        #endif  

                        string p[] = {"hello", " world", " is", " buitful"};
                        p[0][1] = 'w';

                        cout << p[0] << endl;

                        return 0;
                }       
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值